forked from jenkinsci/git-plugin
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGitStatus.java
More file actions
185 lines (160 loc) · 7.25 KB
/
Copy pathGitStatus.java
File metadata and controls
185 lines (160 loc) · 7.25 KB
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
package hudson.plugins.git;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import hudson.Extension;
import hudson.model.AbstractModelObject;
import hudson.model.AbstractProject;
import hudson.model.Hudson;
import hudson.model.UnprotectedRootAction;
import hudson.scm.SCM;
import hudson.security.ACL;
import hudson.triggers.SCMTrigger;
import jenkins.model.Jenkins;
import net.sf.json.JSONObject;
import org.acegisecurity.Authentication;
import org.acegisecurity.context.SecurityContextHolder;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.transport.URIish;
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.HttpResponses;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import javax.servlet.ServletException;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URISyntaxException;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;
import static javax.servlet.http.HttpServletResponse.*;
/**
* Information screen for the use of Git in Hudson.
*/
@Extension
public class GitStatus extends AbstractModelObject implements UnprotectedRootAction {
public String getDisplayName() {
return "Git";
}
public String getSearchUrl() {
return getUrlName();
}
public String getIconFileName() {
// TODO
return null;
}
public String getUrlName() {
return "git";
}
public HttpResponse doNotifyCommit(@QueryParameter(required=true) String url, @QueryParameter(required=false) String branches) throws ServletException, IOException {
// run in high privilege to see all the projects anonymous users don't see.
// this is safe because when we actually schedule a build, it's a build that can
// happen at some random time anyway.
Authentication old = SecurityContextHolder.getContext().getAuthentication();
SecurityContextHolder.getContext().setAuthentication(ACL.SYSTEM);
try {
URIish uri;
try {
uri = new URIish(url);
} catch (URISyntaxException e) {
return HttpResponses.error(SC_BAD_REQUEST, new Exception("Illegal URL: "+url,e));
}
if (branches == null) branches = "";
String[] branchesArray = branches.split(",");
final List<AbstractProject<?,?>> projects = Lists.newArrayList();
boolean scmFound = false,
triggerFound = false,
urlFound = false;
for (AbstractProject<?,?> project : Hudson.getInstance().getAllItems(AbstractProject.class)) {
Collection<GitSCM> projectSCMs = getProjectScms(project);
for (GitSCM git : projectSCMs) {
scmFound = true;
for (RemoteConfig repository : git.getRepositories()) {
boolean repositoryMatches = false,
branchMatches = false;
for (URIish remoteURL : repository.getURIs()) {
if (looselyMatches(uri, remoteURL)) {
repositoryMatches = true;
break;
}
}
if (!repositoryMatches || git.isIgnoreNotifyCommit()) continue;
if (branchesArray.length == 1 && branchesArray[0] == "") {
branchMatches = true;
} else {
for (BranchSpec branchSpec : git.getBranches()) {
for (int i=0; i < branchesArray.length; i++) {
if (branchSpec.matches(repository.getName() + "/" + branchesArray[i])) { branchMatches = true; break; }
}
if (branchMatches) break;
}
}
if (branchMatches) urlFound = true; else continue;
SCMTrigger trigger = project.getTrigger(SCMTrigger.class);
if (trigger!=null) triggerFound = true; else continue;
if (!project.isDisabled()) {
LOGGER.info("Triggering the polling of "+project.getFullDisplayName());
trigger.run();
projects.add(project);
}
break;
}
}
}
final String msg;
if (!scmFound) msg = "No git jobs found";
else if (!urlFound) msg = "No git jobs using repository: " + url + " and branches: " + branches;
else if (!triggerFound) msg = "Jobs found but they aren't configured for polling";
else msg = null;
return new HttpResponse() {
public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) throws IOException, ServletException {
rsp.setStatus(SC_OK);
rsp.setContentType("text/plain");
for (AbstractProject<?, ?> p : projects) {
rsp.addHeader("Triggered", p.getAbsoluteUrl());
}
PrintWriter w = rsp.getWriter();
for (AbstractProject<?, ?> p : projects) {
w.println("Scheduled polling of "+p.getFullDisplayName());
}
if (msg!=null)
w.println(msg);
}
};
} finally {
SecurityContextHolder.getContext().setAuthentication(old);
}
}
private Collection<GitSCM> getProjectScms(AbstractProject<?, ?> project) {
Set<GitSCM> projectScms = Sets.newHashSet();
if (Jenkins.getInstance().getPlugin("multiple-scms") != null) {
MultipleScmResolver multipleScmResolver = new MultipleScmResolver();
multipleScmResolver.resolveMultiScmIfConfigured(project, projectScms);
}
if (projectScms.isEmpty()) {
SCM scm = project.getScm();
if (scm instanceof GitSCM) {
projectScms.add(((GitSCM) scm));
}
}
return projectScms;
}
/**
* Used to test if what we have in the job configuration matches what was submitted to the notification endpoint.
* It is better to match loosely and wastes a few polling calls than to be pedantic and miss the push notification,
* especially given that Git tends to support multiple access protocols.
*/
protected boolean looselyMatches(URIish lhs, URIish rhs) {
return StringUtils.equals(lhs.getHost(),rhs.getHost())
&& StringUtils.equals(normalizePath(lhs.getPath()), normalizePath(rhs.getPath()));
}
private String normalizePath(String path) {
if (path.startsWith("/")) path=path.substring(1);
if (path.endsWith("/")) path=path.substring(0,path.length()-1);
if (path.endsWith(".git")) path=path.substring(0,path.length()-4);
return path;
}
private static final Logger LOGGER = Logger.getLogger(GitStatus.class.getName());
}