/*
* This file is part of git-commit-id-plugin by Konrad 'ktoso' Malawski <konrad.malawski@java.pl>
*
* git-commit-id-plugin is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* git-commit-id-plugin is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with git-commit-id-plugin. If not, see <http://www.gnu.org/licenses/>.
*/
package pl.project13.maven.git;
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.*;
import java.util.List;
/**
* Encapsulates logic to locate a valid .git directory.
*
*/
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(@NotNull File manuallyConfiguredDir) {
if (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.
*/
}
return findProjectGitDirectory();
}
/**
* Search up all the maven parent project hierarchy until a .git directory is found.
*
* @return File which represents the location of the .git directory or NULL if none found.
*/
@Nullable
private File findProjectGitDirectory() {
if (this.mavenProject == null) {
return null;
}
File basedir = mavenProject.getBasedir();
while (basedir != null) {
File gitdir = new File(basedir, Constants.DOT_GIT);
if (gitdir.exists()) {
if (gitdir.isDirectory()) {
return gitdir;
} else if (gitdir.isFile()) {
return processGitDirFile(gitdir);
} else {
return null;
}
}
basedir = basedir.getParentFile();
}
return null;
}
/**
* Load a ".git" git submodule file and read the gitdir path from it.
*
* @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.
File gitDir = new File(parts[1]);
if (gitDir.isAbsolute()) {
// gitdir value is an absolute path. Return as-is
return gitDir;
} else {
// gitdir value is relative.
return new File(file.getParentFile(), parts[1]);
}
} catch (FileNotFoundException e) {
return null;
} finally {
if (reader != null) {
reader.close();
}
}
} catch (IOException e) {
return null;
}
}
private static boolean isExistingDirectory(@Nullable File fileLocation) {
return fileLocation != null && fileLocation.exists() && fileLocation.isDirectory();
}
}