Skip to content

Fixed to handle git submodules #65

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 50 additions & 43 deletions src/main/java/pl/project13/maven/git/GitCommitIdMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,17 @@ public class GitCommitIdMojo extends AbstractMojo {
* @parameter expression="${reactorProjects}"
* @readonly
*/
private List reactorProjects;
private List<MavenProject> reactorProjects;

/**
* Tell git-commit-id to inject the git properties into all
* reactor projects not just the current one.
*
* @parameter default-value="true"
*/
@SuppressWarnings("UnusedDeclaration")
private boolean injectAllReactorProjects;

/**
* Specifies whether the goal runs in verbose mode.
* To be more specific, this means more info being printed out while scanning for paths and also
Expand Down Expand Up @@ -215,67 +224,70 @@ public class GitCommitIdMojo extends AbstractMojo {
boolean runningTests = false;

@NotNull
LoggerBridge loggerBridge = new MavenLoggerBridge(getLog(), verbose);
LoggerBridge loggerBridge = new MavenLoggerBridge(getLog(), true);

@NotNull
LoggerBridge verboseLoggerBridge = new MavenLoggerBridge(getLog(), true);

public void execute() throws MojoExecutionException {
// Set the verbose setting now it should be correctly loaded from maven.
loggerBridge.setVerbose(verbose);
alwaysLog("Verbose Setting: " + Boolean.valueOf(verbose));

if (isPomProject(project) && skipPoms) {
log("Skipping the execution as it is a project with packaging type: 'pom'");
alwaysLog("Skipping the execution as it is a project with packaging type: 'pom'");
return;
}

dotGitDirectory = lookupGitDirectory();
throwWhenRequiredDirectoryNotFound(dotGitDirectory, failOnNoGitDirectory, ".git directory could not be found! Please specify a valid [dotGitDirectory] in your pom.xml");

if(dotGitDirectory != null) {
log("Running on '%s' repository...", dotGitDirectory.getAbsolutePath());
if (dotGitDirectory != null) {
alwaysLog("Running on '%s' repository...", dotGitDirectory.getAbsolutePath());
} else {
log(".git directory could not be found, skipping execution");
alwaysLog(".git directory could not be found, skipping execution");
return;
}

try {
properties = initProperties();
prefixDot = prefix + ".";

loadGitData(properties);
loadBuildTimeData(properties);

logProperties(properties);

if (generateGitPropertiesFile) {
generatePropertiesFile(properties, generateGitPropertiesFilename);
}

appendPropertiesToMaven(properties);
if (injectAllReactorProjects) {
appendPropertiesToReactorProjects(properties);
}
} catch (IOException e) {
throw new MojoExecutionException("Could not complete Mojo execution...", e);
}

log("Finished running.");
}

private void appendPropertiesToMaven(@NotNull Properties properies) {
log("Appending to Maven properties");
private void appendPropertiesToReactorProjects(@NotNull Properties properies) {
log("Appending git properties to all reactor projects:");

if (project != null) {
if (reactorProjects != null) {
Iterator projIter = reactorProjects.iterator();

while (projIter.hasNext()) {
MavenProject nextProj = (MavenProject) projIter.next();
Properties mavenProperties = nextProj.getProperties();

log("Injecting Git properties to \"%s\" project", nextProj.getName());

for (Object key : properties.keySet()) {
mavenProperties.put(key, properties.get(key));
}
if (reactorProjects != null) {
for (MavenProject mavenProject : reactorProjects) {
Properties mavenProperties = mavenProject.getProperties();

log("Injecting Git properties to \"%s\" project", mavenProject.getName());

for (Object key : properties.keySet()) {
mavenProperties.put(key, properties.get(key));
}
}
}
}

private void throwWhenRequiredDirectoryNotFound(File dotGitDirectory, Boolean required, String message) throws MojoExecutionException {
private void throwWhenRequiredDirectoryNotFound(File dotGitDirectory, Boolean required, String message) throws MojoExecutionException {
if (required && directoryDoesNotExits(dotGitDirectory)) {
throw new MojoExecutionException(message);
}
Expand All @@ -288,12 +300,7 @@ private void throwWhenRequiredDirectoryNotFound(File dotGitDirectory, Boolean re
* @return the File representation of the .git directory
*/
private File lookupGitDirectory() throws MojoExecutionException {
return getGitDirLocator().lookupGitDirectory(project, dotGitDirectory);
}

@NotNull
GitDirLocator getGitDirLocator() {
return new GitDirLocator();
return new GitDirLocator(project, reactorProjects).lookupGitDirectory(dotGitDirectory);
}

private Properties initProperties() throws MojoExecutionException {
Expand All @@ -310,15 +317,15 @@ private Properties initProperties() throws MojoExecutionException {
}

private void logProperties(@NotNull Properties properties) {
log("------------------git properties loaded------------------");
alwaysLog("------------------git properties loaded------------------");

for (Object key : properties.keySet()) {
String keyString = key.toString();
if (isOurProperty(keyString)) {
log(String.format("%s = %s", key, properties.getProperty(keyString)));
alwaysLog(String.format("%s = %s", key, properties.getProperty(keyString)));
}
}
log("---------------------------------------------------------");
alwaysLog("---------------------------------------------------------");
}

private boolean isOurProperty(@NotNull String keyString) {
Expand Down Expand Up @@ -481,24 +488,24 @@ private void put(@NotNull Properties properties, String key, String value) {
}

private void putWithoutPrefix(@NotNull Properties properties, String key, String value) {
if (verbose) {
String s = String.format("Storing: %s = %s", key, value);
log(s);
if (!isNotEmpty(value)) {
value = "Unknown";
}

if (isNotEmpty(value)) {
properties.put(key, value);
} else {
properties.put(key, "Unknown");
}
log("Storing: %s = %s", key, value);
properties.put(key, value);
}

private boolean isNotEmpty(@Nullable String value) {
return null != value && !" ".equals(value.trim().replaceAll(" ", ""));
}

void log(String message, String... interpolations) {
loggerBridge.log(logPrefix + message, interpolations);
loggerBridge.log(logPrefix + message, (Object[]) interpolations);
}

void alwaysLog(String message, String... interpolations) {
verboseLoggerBridge.log(logPrefix + message, (Object[]) interpolations);
}

private boolean directoryExists(@Nullable File fileLocation) {
Expand Down
152 changes: 132 additions & 20 deletions src/main/java/pl/project13/maven/git/GitDirLocator.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,56 +17,168 @@

package pl.project13.maven.git;

import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.project.MavenProject;
import org.eclipse.jgit.lib.Constants;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.List;

/**
* Encapsulates logic to locate a valid .git directory
* @author <a href="mailto:konrad.malawski@java.pl">Konrad 'ktoso' Malawski</a>
*/
public class GitDirLocator {

final MavenProject mavenProject;
final List<MavenProject> reactorProjects;

public GitDirLocator(MavenProject mavenProject, List<MavenProject> reactorProjects){
this.mavenProject = mavenProject;
this.reactorProjects = reactorProjects;
}

@Nullable
public File lookupGitDirectory(MavenProject project, File manualyConfiguredDir) throws MojoExecutionException {
public File lookupGitDirectory(File manuallyConfiguredDir) {

if (isExistingDirectory(manualyConfiguredDir)) {
return manualyConfiguredDir;
if (manuallyConfiguredDir != null && manuallyConfiguredDir.exists()) {

// If manuallyConfiguredDir is a directory then we can use it as the git path.
if (manuallyConfiguredDir.isDirectory()) {
return manuallyConfiguredDir;
}

// If the path exists but is not a directory it might be a git submodule "gitdir" link.
File gitDirLinkPath = processGitDirFile(manuallyConfiguredDir);

// If the linkPath was found from the file and it exists then use it.
if (isExistingDirectory(gitDirLinkPath))
{
return gitDirLinkPath;
}

/**
* FIXME: I think we should fail here because a manual path was set and it was not found
* but I'm leaving it falling back to searching for the git path because that is the current
* behaviour - Unluckypixie.
*/
}

MavenProject mavenProject = project;
return findProjectGitDirectory();
}

File dir;
while (mavenProject != null) {
dir = currentProjectGitDir(mavenProject);
/**
* Search up all the maven parent project heirarchy until a .git
* directory is found.
*
* @return File the location of the .git directory or NULL if none found.
*/
private File findProjectGitDirectory()
{
MavenProject project = this.mavenProject;

while (project != null) {
File dir = getProjectGitDir(project);

if (isExistingDirectory(dir)) {
return dir;
}

if (mavenProject.getBasedir() != null) {
dir = new File(mavenProject.getBasedir().getParentFile(), Constants.DOT_GIT);
if (isExistingDirectory(dir)) {
return dir;
}
/**
* project.getParent always returns NULL for me, but if getParentArtifact returns
* not null then there is actually a parent - seems like a bug in maven to me.
*/
if (project.getParent() == null && project.getParentArtifact() != null) {
project = getReactorParentProject(project);
} else {
// Get the parent, or NULL if no parent AND no parentArtifact.
project = project.getParent();
}
}

mavenProject = mavenProject.getParent();
return null;
}

/**
* Find a project in the reactor by its artifact, I'm new to maven coding
* so there may be a better way to do this, it would not be necessary
* if project.getParent() actually worked.
*
* @param MavenProject project
* @return MavenProject parent project or NULL if no parent available
*/
private MavenProject getReactorParentProject(MavenProject project) {
Artifact parentArtifact = project.getParentArtifact();

if (parentArtifact != null) {
for (MavenProject reactorProject : this.reactorProjects) {
if (reactorProject.getArtifactId().equals(parentArtifact.getArtifactId())){
return reactorProject;
}
}
}

return null;
}

/**
* Load a ".git" git submodule file and read the gitdir path from it.
*
* @param file
* @return File object with path loaded or null
*/
private File processGitDirFile(@NotNull File file) {
try {
BufferedReader reader = null;

try {
reader = new BufferedReader(new FileReader(file));

// There should be just one line in the file, e.g.
// "gitdir: /usr/local/src/parentproject/.git/modules/submodule"
String line = reader.readLine();

// Separate the key and the value in the string.
String[] parts = line.split(": ");

// If we don't have 2 parts or if the key is not gitdir then give up.
if (parts.length != 2 || !parts[0].equals("gitdir")) {
return null;
}

// All seems ok so return the "gitdir" value read from the file.
return new File(parts[1]);
}
catch (FileNotFoundException e)
{
return null;
}
finally
{
if (reader != null)
{
reader.close();
}
}
}
catch (IOException e)
{
return null;
}
}

@NotNull
private File currentProjectGitDir(@NotNull MavenProject mavenProject) {
private File getProjectGitDir(@NotNull MavenProject mavenProject) {
// FIXME Shouldn't this look at the dotGitDirectory property (if set) for the given project?
return new File(mavenProject.getBasedir(), Constants.DOT_GIT);
}

public static boolean isExistingDirectory(@Nullable File fileLocation) {
public boolean isExistingDirectory(@Nullable File fileLocation) {
return fileLocation != null && fileLocation.exists() && fileLocation.isDirectory();
}


}
}