pl.project13.maven.git.GitDirLocator.java Source code

Java tutorial

Introduction

Here is the source code for pl.project13.maven.git.GitDirLocator.java

Source

/*
 * This file is part of git-commit-id-plugin by Konrad 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 com.google.common.base.Optional;
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.*;
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(@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 heirarchy 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() {
        MavenProject currentProject = this.mavenProject;

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

            if (isExistingDirectory(dir)) {
                return dir;
            }
            // If the path exists but is not a directory it might be a git submodule "gitdir" link.
            File gitDirLinkPath = processGitDirFile(dir);

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

            /**
             * 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 (currentProject.getParent() == null && currentProject.getParentArtifact() != null) {
                Optional<MavenProject> maybeFoundParentProject = getReactorParentProject(currentProject);

                if (maybeFoundParentProject.isPresent())
                    currentProject = maybeFoundParentProject.get();

            } else {
                // Get the parent, or NULL if no parent AND no parentArtifact.
                currentProject = currentProject.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.
     *
     * @return MavenProject parent project or NULL if no parent available
     */
    private Optional<MavenProject> getReactorParentProject(@NotNull MavenProject project) {
        Artifact parentArtifact = project.getParentArtifact();

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

        return Optional.absent();
    }

    /**
     * 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.
                return new File(file.getParentFile(), parts[1]);
            } catch (FileNotFoundException e) {
                return null;
            } finally {
                if (reader != null) {
                    reader.close();
                }
            }
        } catch (IOException e) {
            return null;
        }
    }

    @NotNull
    private static 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);
    }

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