eu.trentorise.opendata.josman.test.GitTest.java Source code

Java tutorial

Introduction

Here is the source code for eu.trentorise.opendata.josman.test.GitTest.java

Source

package eu.trentorise.opendata.josman.test;

import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.ImmutableList;
import eu.trentorise.opendata.commons.TodConfig;
import static eu.trentorise.opendata.commons.TodUtils.checkNotEmpty;
import eu.trentorise.opendata.josman.Josmans;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.List;
import java.util.SortedMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.io.FileUtils;
import org.eclipse.egit.github.core.RepositoryTag;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.errors.AmbiguousObjectException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.DepthWalk.RevWalk;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.PathFilter;
import org.junit.BeforeClass;
import org.junit.Test;

/**
 *
 * @author David Leoni
 */
public class GitTest {

    private static final Logger LOG = Logger.getLogger(GitTest.class.getName());
    private static final int DEPTH = 8000;

    @BeforeClass
    public static void beforeClass() {
        TodConfig.init(GitTest.class);
    }

    @Test
    public void testEgit() throws IOException {
        List<RepositoryTag> tags = Josmans.fetchTags("opendatatrentino", "josman");
        SortedMap<String, RepositoryTag> filteredTags = Josmans.versionTags("josman", tags);
        for (String tagName : filteredTags.keySet()) {
            RepositoryTag tag = filteredTags.get(tagName);
            LOG.info(tag.getName());
            LOG.info(tag.getCommit().getSha());
        }
    }

    @Test
    public void testReadRepo() throws IOException, GitAPIException {
        File repoFile = createSampleGitRepo();

        FileRepositoryBuilder builder = new FileRepositoryBuilder();
        Repository repo = builder.setGitDir(repoFile).readEnvironment() // scan environment GIT_* variables
                .findGitDir() // scan up the file system tree
                .build();

        LOG.log(Level.INFO, "directory: {0}", repo.getDirectory().getAbsolutePath());

        LOG.log(Level.INFO, "Having repository: {0}", repo.getDirectory().getAbsolutePath());

        LOG.log(Level.INFO, "current branch: {0}", repo.getBranch());
    }

    @Test
    public void testWalkRepo() throws IOException {
        File repoFile = createJosmanSampleRepo();

        FileRepositoryBuilder builder = new FileRepositoryBuilder();
        Repository repo = builder.setGitDir(repoFile).readEnvironment() // scan environment GIT_* variables
                .findGitDir() // scan up the file system tree
                .build();

        //printFile(repo, tree, "*a.*");
        printDirectory(repo, "master", "src");

        // there is also FileMode.SYMLINK for symbolic links, but this is not handled here yet
        repo.close();
    }

    private static RevTree getTree(Repository repository)
            throws AmbiguousObjectException, IncorrectObjectTypeException, IOException, MissingObjectException {
        ObjectId lastCommitId = repository.resolve(Constants.HEAD);

        // a RevWalk allows to walk over commits based on some filtering
        RevWalk revWalk = new RevWalk(repository, DEPTH);
        RevCommit commit = revWalk.parseCommit(lastCommitId);

        System.out.println("Time of commit (seconds since epoch): " + commit.getCommitTime());

        // and using commit's tree find the path
        RevTree tree = commit.getTree();
        System.out.println("Having tree: " + tree);
        return tree;
    }

    private static void printFile(Repository repository, RevTree tree, String filter) {
        try {
            // now try to find a specific file
            TreeWalk treeWalk = new TreeWalk(repository);
            treeWalk.addTree(tree);
            treeWalk.setRecursive(false);
            treeWalk.setFilter(PathFilter.create(filter));
            if (!treeWalk.next()) {
                throw new IllegalStateException("Did not find expected file " + filter);
            }

            // FileMode specifies the type of file, FileMode.REGULAR_FILE for normal file, FileMode.EXECUTABLE_FILE for executable bit
            // set
            FileMode fileMode = treeWalk.getFileMode(0);
            ObjectLoader loader = repository.open(treeWalk.getObjectId(0));
            System.out.println(treeWalk.getPathString() + ": " + getFileMode(fileMode) + ", type: "
                    + fileMode.getObjectType() + ", mode: " + fileMode + " size: " + loader.getSize());
        } catch (Exception ex) {
            throw new RuntimeException("Error while walkinf files", ex);
        }
    }

    private static void printDirectory(Repository repo, String revStr, String prefix) {
        checkNotNull(repo);
        checkNotNull(prefix);
        checkNotEmpty(revStr, "invalid revisiong string!");
        try {
            // find the HEAD
            ObjectId lastCommitId = repo.resolve(revStr);

            // a RevWalk allows to walk over commits based on some filtering that is defined
            RevWalk revWalk = new RevWalk(repo, DEPTH);
            RevCommit commit = revWalk.parseCommit(lastCommitId);
            // and using commit's tree find the path
            RevTree tree = commit.getTree();
            LOG.log(Level.INFO, "Having tree: {0}", tree);
            // look at directory, this has FileMode.TREE
            TreeWalk treeWalk = new TreeWalk(repo);
            treeWalk.addTree(tree);
            treeWalk.setRecursive(true);

            treeWalk.setFilter(PathFilter.create(prefix));// careful this looks for *exact* dir name (i.e. 'docs' will work for docs/a.txt but 'doc' won't work) 

            while (treeWalk.next()) {
                // FileMode now indicates that this is a directory, i.e. FileMode.TREE.equals(fileMode) holds true
                String pathString = treeWalk.getPathString();

                if (pathString.startsWith(prefix)) {
                    FileMode fileMode = treeWalk.getFileMode(0);
                    System.out.println(pathString + ":  " + getFileMode(fileMode) + ", type: "
                            + fileMode.getObjectType() + ", mode: " + fileMode);

                    ObjectId objectId = treeWalk.getObjectId(0);
                    ObjectLoader loader = repo.open(objectId);

                    InputStream stream = loader.openStream();

                    File outputFile = File.createTempFile("bla", "bla");
                    FileUtils.copyInputStreamToFile(stream, outputFile);
                    stream.close();

                    System.out.println("content:\n" + FileUtils.readFileToString(outputFile));

                }
            }
        }

        catch (Exception ex) {
            throw new RuntimeException("Error while walking directory!", ex);
        }
    }

    private static String getFileMode(FileMode fileMode) {
        if (fileMode.equals(FileMode.EXECUTABLE_FILE)) {
            return "Executable File";
        } else if (fileMode.equals(FileMode.REGULAR_FILE)) {
            return "Normal File";
        } else if (fileMode.equals(FileMode.TREE)) {
            return "Directory";
        } else if (fileMode.equals(FileMode.SYMLINK)) {
            return "Symlink";
        } else {
            // there are a few others, see FileMode javadoc for details
            throw new IllegalArgumentException("Unknown type of file encountered: " + fileMode);
        }
    }

    private static File createFile(Repository repository, String filePath) {

        try {
            // create the file

            File targetFile = new File(repository.getDirectory().getParent(), filePath);
            File parent = targetFile.getParentFile();
            if (!parent.exists() && !parent.mkdirs()) {
                throw new IllegalStateException("Couldn't create dir: " + parent);
            }

            targetFile.createNewFile();

            PrintWriter pw = new PrintWriter(targetFile);
            pw.println("hello");
            pw.close();

            // run the add-call
            new Git(repository).add().addFilepattern(filePath).call();

            return targetFile;

        } catch (Exception ex) {
            throw new RuntimeException("Error while creating file!", ex);
        }
    }

    private static ImmutableList<File> createFiles(Repository repository, String... filePaths) {
        ImmutableList.Builder<File> retb = ImmutableList.builder();
        for (String filePath : filePaths) {
            retb.add(createFile(repository, filePath));
        }
        return retb.build();
    }

    /**
     * Creates a sample josman repo
     *
     *
     * @return
     * @throws IOException
     * @throws GitAPIException
     */
    private static File createJosmanSampleRepo() {
        Repository repository;
        try {
            repository = CookbookHelper.createNewRepository();

            LOG.log(Level.INFO, "Temporary repository at {0}", repository.getDirectory());

            createFiles(repository, "docs/README.md", "docs/CHANGES.md", "docs/img/a.jpg", "src/main/java/a.java",
                    "src/main/java/b.java", "README.md", "LICENSE.txt");

            // and then commit the changes
            new Git(repository).commit().setMessage("Added test files").call();

            File dir = repository.getDirectory();

            repository.close();

            return dir;
        } catch (Exception ex) {
            throw new RuntimeException("Error while creating new repo!", ex);
        }

    }

    private static File createSampleGitRepo() throws IOException, GitAPIException {
        Repository repository = CookbookHelper.createNewRepository();

        System.out.println("Temporary repository at " + repository.getDirectory());

        // create the file
        File myfile = new File(repository.getDirectory().getParent(), "testfile");
        myfile.createNewFile();

        // run the add-call
        new Git(repository).add().addFilepattern("testfile").call();

        // and then commit the changes
        new Git(repository).commit().setMessage("Added testfile").call();

        LOG.info("Added file " + myfile + " to repository at " + repository.getDirectory());

        File dir = repository.getDirectory();

        repository.close();

        return dir;

    }

    private static class CookbookHelper {

        public static Repository openJGitCookbookRepository() throws IOException {
            FileRepositoryBuilder builder = new FileRepositoryBuilder();
            Repository repository = builder.readEnvironment() // scan environment GIT_* variables
                    .findGitDir() // scan up the file system tree
                    .build();
            return repository;
        }

        public static Repository createNewRepository() throws IOException {
            // prepare a new folder
            File localPath = File.createTempFile("TestGitRepository", "");
            localPath.delete();

            // create the directory
            Repository repository = FileRepositoryBuilder.create(new File(localPath, ".git"));
            repository.create();

            return repository;
        }
    }

}