org.eclipse.egit.core.internal.gerrit.GerritUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.egit.core.internal.gerrit.GerritUtil.java

Source

/*******************************************************************************
 * Copyright (c) 2013, 2016 Robin Stocker <robin@nibor.org> and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Thomas Wolf <thomas.wolf@paranor.ch> - Bug 493352
 *******************************************************************************/
package org.eclipse.egit.core.internal.gerrit;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.egit.core.Activator;
import org.eclipse.egit.core.internal.CoreText;
import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.transport.URIish;

/**
 * Gerrit utilities
 */
public class GerritUtil {

    /**
     * The Gerrit magic push prefix {@value} .
     */
    public static final String REFS_FOR = "refs/for/"; //$NON-NLS-1$

    /**
     * The Gerrit magic push prefix {@value}
     */
    public static final String REFS_PUBLISH = "refs/publish/"; //$NON-NLS-1$

    /**
     * The Gerrit magic push prefix {@value}
     */
    public static final String REFS_DRAFTS = "refs/drafts/"; //$NON-NLS-1$

    /**
     * @param config
     * @return true if there if "create change ID" is configured
     */
    public static boolean getCreateChangeId(Config config) {
        return config.getBoolean(ConfigConstants.CONFIG_GERRIT_SECTION, ConfigConstants.CONFIG_KEY_CREATECHANGEID,
                false);
    }

    /**
     * Set the "create change ID" configuration
     *
     * @param config
     */
    public static void setCreateChangeId(Config config) {
        config.setBoolean(ConfigConstants.CONFIG_GERRIT_SECTION, null, ConfigConstants.CONFIG_KEY_CREATECHANGEID,
                true);
    }

    /**
     * Find the remote config for the given remote name
     *
     * @param config
     *            the configuration containing the remote config
     * @param remoteName
     *            the name of the remote to find
     * @return the found remoteConfig or {@code null}
     * @throws URISyntaxException
     *             if the configuration contains an illegal URI
     */
    public static RemoteConfig findRemoteConfig(Config config, String remoteName) throws URISyntaxException {
        RemoteConfig remoteConfig = null;
        List<RemoteConfig> allRemoteConfigs = RemoteConfig.getAllRemoteConfigs(config);
        for (RemoteConfig rc : allRemoteConfigs) {
            if (rc.getName().equals(remoteName)) {
                remoteConfig = rc;
                break;
            }
        }
        return remoteConfig;
    }

    /**
     * Configure the pushURI for Gerrit
     *
     * @param remoteConfig
     *            the remote configuration to add this to
     * @param pushURI
     *            the pushURI to configure
     */
    public static void configurePushURI(RemoteConfig remoteConfig, URIish pushURI) {
        List<URIish> pushURIs = new ArrayList<URIish>(remoteConfig.getPushURIs());
        for (URIish urIish : pushURIs) {
            remoteConfig.removePushURI(urIish);
        }
        remoteConfig.addPushURI(pushURI);
    }

    /**
     * Configure the gerrit push refspec HEAD:refs/for/<gerritBranch>
     *
     * @param remoteConfig
     *            the remote configuration to configure this in
     * @param gerritBranch
     *            the branch to push to review for
     */
    public static void configurePushRefSpec(RemoteConfig remoteConfig, String gerritBranch) {
        List<RefSpec> pushRefSpecs = new ArrayList<RefSpec>(remoteConfig.getPushRefSpecs());
        for (RefSpec refSpec : pushRefSpecs) {
            remoteConfig.removePushRefSpec(refSpec);
        }
        remoteConfig.addPushRefSpec(new RefSpec("HEAD:" + GerritUtil.REFS_FOR + gerritBranch)); //$NON-NLS-1$
    }

    /**
     * Configure fetching review summary notes
     *
     * @param remoteConfig
     *            the remote configuration to configure this in
     * @return {@code true} if the {@code remoteConfig} was changed,
     *         {@code false} otherwise.
     */
    public static boolean configureFetchNotes(RemoteConfig remoteConfig) {
        String notesRef = Constants.R_NOTES + "*"; //$NON-NLS-1$
        List<RefSpec> fetchRefSpecs = remoteConfig.getFetchRefSpecs();
        for (RefSpec refSpec : fetchRefSpecs) {
            if (refSpec.matchSource(notesRef)) {
                return false;
            }
        }
        remoteConfig.addFetchRefSpec(new RefSpec(notesRef + ':' + notesRef));
        return true;
    }

    /**
     * @param rc
     *            the remote configuration
     * @return {@code true} if the remote configuration is configured for
     *         pushing to Gerrit
     */
    public static boolean isGerritPush(RemoteConfig rc) {
        for (RefSpec pushSpec : rc.getPushRefSpecs()) {
            String destination = pushSpec.getDestination();
            if (destination == null) {
                continue;
            }
            if (destination.startsWith(GerritUtil.REFS_FOR) || destination.startsWith(GerritUtil.REFS_PUBLISH)
                    || destination.startsWith(GerritUtil.REFS_DRAFTS)) {
                return true;
            }
        }
        return false;
    }

    /**
     * @param rc
     *            the remote configuration
     * @return {@code true} if the remote configuration is configured for
     *         fetching from Gerrit
     */
    public static boolean isGerritFetch(RemoteConfig rc) {
        for (RefSpec fetchSpec : rc.getFetchRefSpecs()) {
            String source = fetchSpec.getSource();
            String destination = fetchSpec.getDestination();
            if (source == null || destination == null) {
                continue;
            }
            if (source.startsWith(Constants.R_NOTES) && destination.startsWith(Constants.R_NOTES)) {
                return true;
            }
        }
        return false;
    }

    /**
     * If the repository is not bare and looks like it might be a Gerrit
     * repository, try to configure it such that EGit's Gerrit support is
     * enabled.
     *
     * @param repository
     *            to try to configure
     */
    public static void tryToAutoConfigureForGerrit(@NonNull Repository repository) {
        if (repository.isBare()) {
            return;
        }
        StoredConfig config = repository.getConfig();
        boolean isGerrit = false;
        boolean changed = false;
        try {
            for (RemoteConfig remote : RemoteConfig.getAllRemoteConfigs(config)) {
                if (isGerritPush(remote)) {
                    isGerrit = true;
                    if (configureFetchNotes(remote)) {
                        changed = true;
                        remote.update(config);
                    }
                }
            }
        } catch (URISyntaxException ignored) {
            // Ignore it here -- we're just trying to set up Gerrit support.
        }
        if (isGerrit) {
            if (config.getString(ConfigConstants.CONFIG_GERRIT_SECTION, null,
                    ConfigConstants.CONFIG_KEY_CREATECHANGEID) != null) {
                // Already configured.
            } else {
                setCreateChangeId(config);
                changed = true;
            }
            if (changed) {
                try {
                    config.save();
                } catch (IOException e) {
                    Activator.logError(
                            MessageFormat.format(CoreText.GerritUtil_ConfigSaveError, repository.getDirectory()),
                            e);
                }
            }
        }
    }

    /**
     * If the repository is not bare and looks like it might be a Gerrit
     * repository, try to configure it such that EGit's Gerrit support is
     * enabled. Does nothing if the {@code repositoryDir} is {@code null} or the
     * repository cannot be configured.
     *
     * @param repositoryDir
     *            .git Directory of the repository to try to configure
     */
    public static void tryToAutoConfigureForGerrit(@Nullable File repositoryDir) {
        if (repositoryDir != null) {
            try {
                Repository repository = Activator.getDefault().getRepositoryCache().lookupRepository(repositoryDir);
                if (repository != null) {
                    tryToAutoConfigureForGerrit(repository);
                }
            } catch (IOException ignored) {
                // Ignore it here -- this is just a best-effort. If the repo
                // cannot be read, other places will report the problem.
            }
        }
    }

}