org.gitective.core.RepositoryUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.gitective.core.RepositoryUtils.java

Source

/*
 * Copyright (c) 2011 Kevin Sawicki <kevinsawicki@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */
package org.gitective.core;

import static org.eclipse.jgit.lib.Constants.DEFAULT_REMOTE_NAME;
import static org.eclipse.jgit.lib.Constants.R_HEADS;
import static org.eclipse.jgit.lib.Constants.R_NOTES;
import static org.eclipse.jgit.lib.Constants.R_REMOTES;
import static org.eclipse.jgit.lib.Constants.R_TAGS;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.jgit.api.LsRemoteCommand;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.RemoteConfig;

/**
 * Utilities for dealing with Git repositories.
 * <p>
 * This class provides helpers for getting the branches, tags, and note
 * references in a repository.
 * <p>
 * This class also provides helpers for knowing which references differ between
 * a local and remote repository.
 */
public abstract class RepositoryUtils {

    /**
     * Wrapper class for a remote and local ref that are different
     */
    public static class RefDiff {

        private final Ref local;

        private final Ref remote;

        /**
         * Create ref diff
         *
         * @param local
         * @param remote
         */
        protected RefDiff(final Ref local, final Ref remote) {
            this.local = local;
            this.remote = remote;
        }

        /**
         * Get local ref. This will be null if the ref only exists remotely.
         *
         * @return ref
         */
        public Ref getLocal() {
            return local;
        }

        /**
         * Get non-null remote ref
         *
         * @return ref
         */
        public Ref getRemote() {
            return remote;
        }
    }

    /**
     * Get the refs with prefix in repository
     *
     * @param repository
     * @param prefix
     * @return collection of refs
     */
    protected static Collection<Ref> getRefs(final Repository repository, final String prefix) {
        try {
            return repository.getRefDatabase().getRefs(prefix).values();
        } catch (IOException e) {
            throw new GitException(e, repository);
        }
    }

    /**
     * Get all the note references in the given repository.
     *
     * @param repository
     * @return non-null but possibly empty array of note references
     */
    public static Collection<String> getNoteRefs(final Repository repository) {
        if (repository == null)
            throw new IllegalArgumentException(Assert.formatNotNull("Repository"));

        final Collection<Ref> refs = getRefs(repository, R_NOTES);
        final List<String> notes = new ArrayList<String>(refs.size());
        for (Ref ref : refs)
            notes.add(ref.getName());
        return notes;
    }

    /**
     * Get all the local and remote tracking branch references in the given
     * repository.
     *
     * @param repository
     * @return non-null but possibly array of branch reference names
     */
    public static Collection<String> getBranches(final Repository repository) {
        if (repository == null)
            throw new IllegalArgumentException(Assert.formatNotNull("Repository"));

        final List<String> branches = new ArrayList<String>();
        for (Ref ref : getRefs(repository, R_HEADS))
            branches.add(ref.getName());
        for (Ref ref : getRefs(repository, R_REMOTES))
            branches.add(ref.getName());
        return branches;
    }

    /**
     * Get all the tag references in the given repository.
     *
     * @param repository
     * @return non-null but possibly array of branch reference names
     */
    public static Collection<String> getTags(final Repository repository) {
        if (repository == null)
            throw new IllegalArgumentException(Assert.formatNotNull("Repository"));

        return repository.getTags().keySet();
    }

    /**
     * List the origin remote references and return all remote references that
     * are missing locally or have a different remote object id than the local
     * reference.
     *
     * @param repository
     * @return non-null but possibly empty collection of {@link RefDiff}
     */
    public static Collection<RefDiff> diffOriginRefs(final Repository repository) {
        return diffRemoteRefs(repository, DEFAULT_REMOTE_NAME);
    }

    /**
     * Does the given remote exist in the repository?
     *
     * @param repository
     * @param remote
     * @return true if exists, false otherwise
     * @throws URISyntaxException
     */
    protected static boolean hasRemote(final Repository repository, final String remote) throws URISyntaxException {
        final RemoteConfig config = new RemoteConfig(repository.getConfig(), remote);
        return !config.getURIs().isEmpty() || !config.getPushURIs().isEmpty();
    }

    /**
     * List remote references and return all remote references that are missing
     * locally or have a different remote object id than the local reference.
     *
     * @param repository
     * @param remote
     * @return non-null but possibly collection of {@link RefDiff}
     */
    public static Collection<RefDiff> diffRemoteRefs(final Repository repository, final String remote) {
        if (repository == null)
            throw new IllegalArgumentException(Assert.formatNotNull("Repository"));
        if (remote == null)
            throw new IllegalArgumentException(Assert.formatNotNull("Remote"));
        if (remote.length() == 0)
            throw new IllegalArgumentException(Assert.formatNotEmpty("Remote"));

        final LsRemoteCommand lsRemote = new LsRemoteCommand(repository);
        lsRemote.setRemote(remote);
        try {
            final Collection<Ref> remoteRefs = lsRemote.call();
            final List<RefDiff> diffs = new ArrayList<RefDiff>();
            if (hasRemote(repository, remote)) {
                final String refPrefix = R_REMOTES + remote + "/";
                for (Ref remoteRef : remoteRefs) {
                    String name = remoteRef.getName();
                    if (name.startsWith(R_HEADS))
                        name = refPrefix + name.substring(R_HEADS.length());
                    else if (!name.startsWith(R_TAGS))
                        name = refPrefix + name;
                    final Ref localRef = repository.getRef(name);
                    if (localRef == null || !remoteRef.getObjectId().equals(localRef.getObjectId()))
                        diffs.add(new RefDiff(localRef, remoteRef));
                }
            } else
                for (Ref remoteRef : remoteRefs) {
                    final Ref localRef = repository.getRef(remoteRef.getName());
                    if (localRef == null || !remoteRef.getObjectId().equals(localRef.getObjectId()))
                        diffs.add(new RefDiff(localRef, remoteRef));
                }
            return diffs;
        } catch (Exception e) {
            throw new GitException(e, repository);
        }
    }

    /**
     * Map names to e-mail addresses for all given {@link PersonIdent} instances
     * <p>
     * {@link PersonIdent} entries with a null or empty name will be ignored.
     *
     * @see PersonIdent#getName()
     * @see PersonIdent#getEmailAddress()
     * @param persons
     * @return non-null but possibly empty map of names to e-mail addresses
     */
    public static Map<String, Set<String>> mapNamesToEmails(final Collection<PersonIdent> persons) {
        if (persons == null || persons.isEmpty())
            return Collections.emptyMap();

        final Map<String, Set<String>> namesToEmails = new HashMap<String, Set<String>>(persons.size());
        for (PersonIdent person : persons) {
            String name = person.getName();
            if (name == null || name.length() == 0)
                continue;
            Set<String> emails = namesToEmails.get(name);
            if (emails == null) {
                emails = new HashSet<String>(2);
                namesToEmails.put(name, emails);
            }
            String email = person.getEmailAddress();
            if (email != null && email.length() > 0)
                emails.add(email);
        }
        return namesToEmails;
    }

    /**
     * Map e-mail addresses to names for all given {@link PersonIdent} instances
     * <p>
     * {@link PersonIdent} entries with a null or empty e-mail address will be
     * ignored.
     *
     * @see PersonIdent#getName()
     * @see PersonIdent#getEmailAddress()
     * @param persons
     * @return non-null but possibly empty map of e-mail addresses to names
     */
    public static Map<String, Set<String>> mapEmailsToNames(final Collection<PersonIdent> persons) {
        if (persons == null || persons.isEmpty())
            return Collections.emptyMap();

        final Map<String, Set<String>> emailsToNames = new HashMap<String, Set<String>>(persons.size());
        for (PersonIdent person : persons) {
            String email = person.getEmailAddress();
            if (email == null || email.length() == 0)
                continue;
            Set<String> names = emailsToNames.get(email);
            if (names == null) {
                names = new HashSet<String>(2);
                emailsToNames.put(email, names);
            }
            String name = person.getName();
            if (name != null && name.length() > 0)
                names.add(name);
        }
        return emailsToNames;
    }
}