/****************************************************************************** * Copyright (c) 2011 GitHub Inc. * 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: * Kevin Sawicki (GitHub Inc.) - initial API and implementation *****************************************************************************/ package org.eclipse.mylyn.internal.github.core.pr; import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import org.eclipse.egit.core.Activator; import org.eclipse.egit.core.RepositoryCache; import org.eclipse.egit.github.core.PullRequest; import org.eclipse.egit.github.core.PullRequestMarker; import org.eclipse.egit.github.core.User; import org.eclipse.egit.github.core.util.UrlUtils; 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; import org.eclipse.mylyn.internal.github.core.GitHub; /** * Pull request utilities */ public abstract class PullRequestUtils { /** * HEAD_SOURCE */ public static final String HEAD_SOURCE = '+' + Constants.R_HEADS + '*'; /** * Get destination ref spec * * @param remote * @return ref spec */ public static String getDesintationRef(RemoteConfig remote) { return Constants.R_REMOTES + remote.getName() + "/*"; //$NON-NLS-1$ } /** * Get branch name for pull request * * @param request * @return non-null/non-empty branch name */ public static String getBranchName(PullRequest request) { return "pull-request-" + request.getNumber(); //$NON-NLS-1$ } /** * Get Git repository for pull request * * @param request * @return repository or null if none found */ public static Repository getRepository(PullRequest request) { org.eclipse.egit.github.core.Repository remoteRepo = request.getBase() .getRepo(); String id = remoteRepo.getOwner().getLogin() + '/' + remoteRepo.getName() + Constants.DOT_GIT; RepositoryCache cache = Activator.getDefault().getRepositoryCache(); for (String path : Activator.getDefault().getRepositoryUtil() .getConfiguredRepositories()) try { Repository repo = cache.lookupRepository(new File(path)); RemoteConfig rc = new RemoteConfig(repo.getConfig(), Constants.DEFAULT_REMOTE_NAME); for (URIish uri : rc.getURIs()) if (uri.toString().endsWith(id)) return repo; } catch (IOException e) { GitHub.logError(e); continue; } catch (URISyntaxException e) { GitHub.logError(e); continue; } return null; } /** * Configure pull request topic branch to use head remote * * @param repo * @param request * @throws IOException */ public static void configureTopicBranch(Repository repo, PullRequest request) throws IOException { String branch = getBranchName(request); String remote = request.getHead().getRepo().getOwner().getLogin(); StoredConfig config = repo.getConfig(); config.setString(ConfigConstants.CONFIG_BRANCH_SECTION, branch, ConfigConstants.CONFIG_KEY_MERGE, getHeadBranch(request)); config.setString(ConfigConstants.CONFIG_BRANCH_SECTION, branch, ConfigConstants.CONFIG_KEY_REMOTE, remote); config.save(); } /** * Get owner of marker * * @param marker * @return owner login name, may be null */ public static String getOwner(PullRequestMarker marker) { if (marker == null) return null; org.eclipse.egit.github.core.Repository repo = marker.getRepo(); if (repo == null) return null; User owner = repo.getOwner(); return owner != null ? owner.getLogin() : null; } /** * Are the given pull request's source and destination repositories the * same? * * @param request * @return true if same, false otherwise */ public static boolean isFromSameRepository(PullRequest request) { if (request == null) return false; String headLogin = getOwner(request.getHead()); if (headLogin == null) return false; return headLogin.equals(getOwner(request.getBase())); } /** * Get remote for given pull request * * @param repo * @param request * @return remote config * @throws URISyntaxException */ public static RemoteConfig getRemote(Repository repo, PullRequest request) throws URISyntaxException { if (isFromSameRepository(request)) return getRemoteConfig(repo, Constants.DEFAULT_REMOTE_NAME); else return getRemoteConfig(repo, getOwner(request.getHead())); } /** * Get remote config with given name * * @param repo * @param name * @return remote config * @throws URISyntaxException */ public static RemoteConfig getRemoteConfig(Repository repo, String name) throws URISyntaxException { for (RemoteConfig candidate : RemoteConfig.getAllRemoteConfigs(repo .getConfig())) if (name.equals(candidate.getName())) return candidate; return null; } /** * Add remote for the head of a pull request if it doesn't exist * * @param repo * @param request * @return remote configuration * @throws IOException * @throws URISyntaxException */ public static RemoteConfig addRemote(Repository repo, PullRequest request) throws IOException, URISyntaxException { RemoteConfig remote = getRemote(repo, request); if (remote != null) return remote; StoredConfig config = repo.getConfig(); org.eclipse.egit.github.core.Repository head = request.getHead() .getRepo(); remote = new RemoteConfig(config, head.getOwner().getLogin()); if (head.isPrivate()) remote.addURI(new URIish(UrlUtils.createRemoteSshUrl(head))); else remote.addURI(new URIish(UrlUtils.createRemoteReadOnlyUrl(head))); remote.addFetchRefSpec(new RefSpec(HEAD_SOURCE + ":" + getDesintationRef(remote))); //$NON-NLS-1$ remote.update(config); config.save(); return remote; } /** * Is given branch name the currently checked out branch? * * @param name * @param repo * @return true if checked out branch, false otherwise */ public static boolean isCurrentBranch(String name, Repository repo) { try { return name.equals(Repository.shortenRefName(repo.getFullBranch())); } catch (IOException e) { return false; } } /** * Get head branch ref for outside repository pull requests * * @param request * @return remote head branch ref name */ public static String getHeadBranch(PullRequest request) { PullRequestMarker head = request.getHead(); return Constants.R_REMOTES + head.getRepo().getOwner().getLogin() + "/" + head.getRef(); } }