Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 6853c5dc8ea0358b16906f72d551c4051c874c5b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
/******************************************************************************
 *  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 2.0
 *  which accompanies this distribution, and is available at
 *  https://www.eclipse.org/legal/epl-2.0/
 *
 *  SPDX-License-Identifier: EPL-2.0
 *
 *  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();
	}
}

Back to the top