org.webcat.core.git.GitRepository.java Source code

Java tutorial

Introduction

Here is the source code for org.webcat.core.git.GitRepository.java

Source

/*==========================================================================*\
 |  $Id: GitRepository.java,v 1.3 2012/06/22 16:23:18 aallowat Exp $
 |*-------------------------------------------------------------------------*|
 |  Copyright (C) 2011-2012 Virginia Tech
 |
 |  This file is part of Web-CAT.
 |
 |  Web-CAT is free software; you can redistribute it and/or modify
 |  it under the terms of the GNU Affero General Public License as published
 |  by the Free Software Foundation; either version 3 of the License, or
 |  (at your option) any later version.
 |
 |  Web-CAT 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 Affero General Public License
 |  along with Web-CAT; if not, see <http://www.gnu.org/licenses/>.
\*==========================================================================*/

package org.webcat.core.git;

import java.io.IOException;
import java.io.OutputStream;
import java.util.Map;
import org.apache.log4j.Logger;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.TagCommand;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefComparator;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevSort;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
import org.eclipse.jgit.treewalk.filter.PathSuffixFilter;
import org.eclipse.jgit.treewalk.filter.TreeFilter;
import org.jfree.util.Log;
import org.webcat.archives.IWritableContainer;
import org.webcat.core.EOBase;
import org.webcat.core.NSMutableDataOutputStream;
import org.webcat.core.git.GitUtilities.RefFilter;
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSData;
import com.webobjects.foundation.NSDictionary;
import com.webobjects.foundation.NSKeyValueCoding;
import com.webobjects.foundation.NSKeyValueCodingAdditions;
import com.webobjects.foundation.NSMutableArray;
import com.webobjects.foundation.NSMutableDictionary;

//-------------------------------------------------------------------------
/**
 * TODO real description
 *
 * @author  Tony Allevato
 * @author  Last changed by $Author: aallowat $
 * @version $Revision: 1.3 $, $Date: 2012/06/22 16:23:18 $
 */
public class GitRepository implements NSKeyValueCodingAdditions {
    //~ Constructors ..........................................................

    // ----------------------------------------------------------
    public GitRepository(Repository repository) {
        this.repository = repository;
    }

    //~ Methods ...............................................................

    // ----------------------------------------------------------
    public static GitRepository repositoryForObject(EOBase eo) {
        Repository repo = GitUtilities.repositoryForObject(eo);
        GitRepository gr = new GitRepository(repo);
        gr.provider = eo;
        return gr;
    }

    // ----------------------------------------------------------
    public EOBase provider() {
        return provider;
    }

    // ----------------------------------------------------------
    public Repository repository() {
        return repository;
    }

    // ----------------------------------------------------------
    private NSArray<GitRef> filteredRefs(RefFilter filter) {
        NSMutableArray<GitRef> result = new NSMutableArray<GitRef>();

        Map<String, Ref> refs = repository.getAllRefs();

        for (Ref ref : RefComparator.sort(refs.values())) {
            if (filter == null || filter.accepts(ref)) {
                result.addObject(new GitRef(this, ref));
            }
        }

        return result;
    }

    // ----------------------------------------------------------
    public NSArray<GitRef> headRefs() {
        return filteredRefs(new RefFilter() {
            public boolean accepts(Ref ref) {
                return ref.getName().startsWith(Constants.R_HEADS);
            }
        });
    }

    // ----------------------------------------------------------
    public NSArray<GitRef> tagRefs() {
        return filteredRefs(new RefFilter() {
            public boolean accepts(Ref ref) {
                return ref.getName().startsWith(Constants.R_TAGS);
            }
        });
    }

    // ----------------------------------------------------------
    public NSArray<GitRef> allRefs() {
        return filteredRefs(null);
    }

    // ----------------------------------------------------------
    public GitRef refWithName(String name) {
        Ref ref = null;

        try {
            ref = repository.getRef(name);
        } catch (IOException e) {
            // Do nothing.
        }

        return ref != null ? new GitRef(this, ref) : null;
    }

    // ----------------------------------------------------------
    public ObjectId resolve(String revstr) {
        try {
            return repository.resolve(revstr);
        } catch (Exception e) {
            Log.error("An error occurred when resolving the string " + revstr + " in the repository at "
                    + repository.getDirectory(), e);
            return null;
        }
    }

    // ----------------------------------------------------------
    public NSArray<GitCommit> commitsWithId(ObjectId commitId, String path) {
        if (commitId != null) {
            return commitsWithIds(new NSArray<ObjectId>(commitId), path);
        } else {
            return null;
        }
    }

    // ----------------------------------------------------------
    /**
     * Parses an array of Git commits and returns an array of commits that
     * affected the specified object.
     *
     * @param repository the Git repository
     * @param commitIds the Git commit IDs to parse
     * @param path the object affected
     * @return an array of {@link GitCommit} objects representing the commits
     */
    public NSArray<GitCommit> commitsWithIds(NSArray<ObjectId> commitIds, String path) {
        try {
            RevWalk rw = new RevWalk(repository);

            try {
                rw.sort(RevSort.COMMIT_TIME_DESC);

                if (path != null) {
                    rw.setTreeFilter(AndTreeFilter.create(PathSuffixFilter.create(path), TreeFilter.ANY_DIFF));
                } else {
                    rw.setTreeFilter(TreeFilter.ALL);
                }

                for (ObjectId commitId : commitIds) {
                    rw.markStart(rw.parseCommit(commitId));
                }

                NSMutableArray<GitCommit> commits = new NSMutableArray<GitCommit>();

                for (RevCommit commit : rw) {
                    commits.add(new GitCommit(commit));
                }

                return commits;
            } finally {
                rw.release();
            }
        } catch (Exception e) {
            log.error("An exception occurred while parsing the commit: ", e);
            return null;
        }
    }

    // ----------------------------------------------------------
    public NSDictionary<GitRef, NSArray<GitCommit>> commitsForRefs(NSArray<GitRef> refs) {
        NSMutableDictionary<GitRef, NSArray<GitCommit>> refsToCommits = new NSMutableDictionary<GitRef, NSArray<GitCommit>>();

        for (GitRef ref : refs) {
            refsToCommits.setObjectForKey(ref.commits(), ref);
        }

        return refsToCommits;
    }

    // ----------------------------------------------------------
    /**
     * Gets the type of the object with the specified ID (either a tree, tag,
     * blob, or commit).
     *
     * @param id the object ID
     * @return the object type, one of the {@code OBJ_*} constants in the
     *     {@link Constants} class.
     */
    public int typeOfObject(ObjectId id) {
        ObjectReader reader = repository.newObjectReader();

        try {
            ObjectLoader loader = reader.open(id);
            return loader.getType();
        } catch (Exception e) {
            return Constants.OBJ_BAD;
        } finally {
            reader.release();
        }
    }

    // ----------------------------------------------------------
    /**
     * Gets the contents of the specified blob as raw data.
     *
     * @param objectId the id of the blob
     * @return an {@code NSData} object containing the raw data from the blob
     */
    public NSData contentForBlob(ObjectId objectId) {
        ObjectReader reader = repository.newObjectReader();

        try {
            ObjectLoader loader = reader.open(objectId);

            NSMutableDataOutputStream output = new NSMutableDataOutputStream();
            loader.copyTo(output);
            output.close();

            return output.data();
        } catch (IOException e) {
            log.error("An exception occurred while getting the blob " + "contents: ", e);
            return null;
        } finally {
            reader.release();
        }
    }

    // ----------------------------------------------------------
    /**
     * Gets the contents of the specified blob as a string.
     *
     * @param objectId the id of the blob
     * @return a string containing the data from the blob
     */
    public String stringContentForBlob(ObjectId objectId) {
        try {
            return new String(contentForBlob(objectId).bytes(), "UTF-8");
        } catch (IOException e) {
            log.error("An exception occurred while getting the blob " + "contents: ", e);
            return null;
        }
    }

    // ----------------------------------------------------------
    /**
     * Writes the contents of the specified blob to an output stream.
     *
     * @param objectId the id of the blob
     * @param stream the stream to write the blob to
     */
    public void writeBlobToStream(ObjectId objectId, OutputStream stream) {
        ObjectReader reader = repository.newObjectReader();

        try {
            ObjectLoader loader = reader.open(objectId);
            loader.copyTo(stream);
        } catch (IOException e) {
            log.error("An exception occurred while getting the blob " + "contents: ", e);
        } finally {
            reader.release();
        }
    }

    // ----------------------------------------------------------
    /**
     * Copies an item from the repository into a container. If the item is a
     * blob, it will be copied into the destination with the specified name; if
     * the item is a tree or commit, its children will be recursively copied.
     *
     * @param objectId the id of the object to copy
     * @param name the destination name to use (only when the item is a blob)
     * @param container the container where the items should be copied
     * @throws IOException if an I/O error occurred
     */
    public void copyItemToContainer(ObjectId objectId, String name, IWritableContainer container)
            throws IOException {
        int type = typeOfObject(objectId);

        if (type == Constants.OBJ_BLOB) {
            OutputStream fileStream = container.createFile(name, -1);
            writeBlobToStream(objectId, fileStream);
            fileStream.close();
        } else if (type == Constants.OBJ_TREE || type == Constants.OBJ_COMMIT) {
            GitTreeIterator iterator = new GitTreeIterator(this, objectId);

            try {
                for (GitTreeEntry entry : iterator) {
                    if (entry.isTree()) {
                        IWritableContainer childContainer = container.createContainer(entry.name());

                        copyItemToContainer(entry.objectId(), entry.name(), childContainer);

                        childContainer.finish();
                    } else {
                        copyItemToContainer(entry.objectId(), entry.name(), container);
                    }
                }
            } finally {
                iterator.release();
            }
        }
    }

    // ----------------------------------------------------------
    public GitRef createTagForObject(String name, ObjectId objectId) {
        TagCommand tag = new Git(repository).tag();
        tag.setName(name);

        if (objectId == null) {
            tag.setObjectId(null);
        } else {
            RevWalk revWalk = new RevWalk(repository);

            try {
                RevCommit commit = revWalk.parseCommit(objectId);
                tag.setObjectId(commit);
            } catch (Exception e) {
                return null;
            } finally {
                revWalk.release();
            }
        }

        try {
            tag.call();
            return refWithName(Constants.R_TAGS + name);
        } catch (Exception e) {
            return null;
        }
    }

    // ----------------------------------------------------------
    @Override
    public int hashCode() {
        return repository.hashCode() ^ 0xEA70BEEF;
    }

    // ----------------------------------------------------------
    @Override
    public boolean equals(Object other) {
        if (other instanceof GitRepository) {
            GitRepository otherRepository = (GitRepository) other;
            return repository == otherRepository.repository;
        } else {
            return false;
        }
    }

    // ----------------------------------------------------------
    public void takeValueForKeyPath(Object value, String keyPath) {
        NSKeyValueCodingAdditions.DefaultImplementation.takeValueForKeyPath(this, value, keyPath);
    }

    // ----------------------------------------------------------
    public Object valueForKeyPath(String keyPath) {
        return NSKeyValueCodingAdditions.DefaultImplementation.valueForKeyPath(this, keyPath);
    }

    // ----------------------------------------------------------
    public void takeValueForKey(Object value, String key) {
        NSKeyValueCoding.DefaultImplementation.takeValueForKey(this, value, key);
    }

    // ----------------------------------------------------------
    public Object valueForKey(String key) {
        return NSKeyValueCoding.DefaultImplementation.valueForKey(this, key);
    }

    //~ Static/instance variables .............................................

    private Repository repository;
    private EOBase provider;

    private static final Logger log = Logger.getLogger(GitRepository.class);
}