Skip to content

Commit

Permalink
Modernize to Jenkins 2.479 and Jakarta EE 9
Browse files Browse the repository at this point in the history
* Adapter methods are added for old overrides.
* Switch to JUnit 5 for tests
  • Loading branch information
mtughan committed Nov 21, 2024
1 parent 9fa1b09 commit ba97a8c
Show file tree
Hide file tree
Showing 12 changed files with 161 additions and 148 deletions.
10 changes: 5 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>4.86</version>
<relativePath/>
<version>5.3</version>
</parent>

<artifactId>git-server</artifactId>
Expand All @@ -17,7 +16,8 @@

<properties>
<changelist>999999-SNAPSHOT</changelist>
<jenkins.version>2.440.3</jenkins.version>
<jenkins.baseline>2.479</jenkins.baseline>
<jenkins.version>${jenkins.baseline}.1</jenkins.version>
<gitHubRepo>jenkinsci/${project.artifactId}-plugin</gitHubRepo>
</properties>

Expand All @@ -40,8 +40,8 @@
<dependencies>
<dependency>
<groupId>io.jenkins.tools.bom</groupId>
<artifactId>bom-2.440.x</artifactId>
<version>3234.v5ca_5154341ef</version>
<artifactId>bom-${jenkins.baseline}.x</artifactId>
<version>3696.vb_b_4e2d1a_0542</version>
<scope>import</scope>
<type>pom</type>
</dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,17 @@
import hudson.Extension;
import hudson.security.csrf.CrumbExclusion;

import javax.servlet.FilterChain;
import javax.servlet.ReadListener;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ReadListener;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Map;
import java.util.Vector;

/**
* CSRF exclusion for git-upload-pack.
Expand All @@ -24,9 +23,10 @@
* because of the dynamic nature of the URL structure, this doesn't guarantee
* that we have no leak.
*
* <p>
* So to further protect Jenkins, we pass through a fake {@link HttpServletRequest}
* that masks the values of the submission.
*
*
* <p>
* If the fake request is routed to {@link HttpGitRepository}, which is
* the only legitimate destination of the request, we'll unwrap this fake request
Expand Down Expand Up @@ -61,13 +61,13 @@ public String getParameter(String name) {
}

@Override
public Map getParameterMap() {
public Map<String, String[]> getParameterMap() {
return Collections.emptyMap();
}

@Override
public Enumeration getParameterNames() {
return new Vector().elements();
public Enumeration<String> getParameterNames() {
return Collections.emptyEnumeration();

Check warning on line 70 in src/main/java/org/jenkinsci/plugins/gitserver/CSRFExclusionImpl.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 70 is not covered by tests
}

@Override
Expand All @@ -81,7 +81,7 @@ public String getMethod() {
}

@Override
public ServletInputStream getInputStream() throws IOException {
public ServletInputStream getInputStream() {
return new ServletInputStream() {
@Override
public boolean isFinished() {
Expand All @@ -94,7 +94,7 @@ public boolean isReady() {
}

@Override
public int read() throws IOException {
public int read() {
return -1;
}

Expand All @@ -106,7 +106,7 @@ public void setReadListener(ReadListener readListener) {
}
};
w.setAttribute(ORIGINAL_REQUEST,request);

chain.doFilter(w,response);
return true;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.jenkinsci.plugins.gitserver;

import hudson.FilePath;
import hudson.FilePath.FileCallable;
import hudson.remoting.Pipe;
import hudson.remoting.VirtualChannel;
import jenkins.MasterToSlaveFileCallable;
Expand Down Expand Up @@ -56,6 +55,7 @@ public FetchConnection openFetch() throws NotSupportedException, TransportExcept
} catch (IOException e) {
throw new TransportException("Failed to open a fetch connection",e);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new TransportException("Failed to open a fetch connection",e);
}

Expand Down Expand Up @@ -99,15 +99,13 @@ public GitFetchTask(Pipe l2r, Pipe r2l) {
}

public Void invoke(File f, VirtualChannel channel) throws IOException, InterruptedException {
Repository repo = new FileRepositoryBuilder().setWorkTree(f).build();
try {
try (Repository repo = new FileRepositoryBuilder().setWorkTree(f).build()) {
final UploadPack rp = new UploadPack(repo);
rp.upload(new BufferedInputStream(l2r.getIn()), new BufferedOutputStream(r2l.getOut()), null);
return null;
} finally {
IOUtils.closeQuietly(l2r.getIn());
IOUtils.closeQuietly(r2l.getOut());
repo.close();
}
}
}
Expand All @@ -122,15 +120,13 @@ public GitPushTask(Pipe l2r, Pipe r2l) {
}

public Void invoke(File f, VirtualChannel channel) throws IOException, InterruptedException {
Repository repo = new FileRepositoryBuilder().setWorkTree(f).build();
try {
try (Repository repo = new FileRepositoryBuilder().setWorkTree(f).build()) {

Check warning on line 123 in src/main/java/org/jenkinsci/plugins/gitserver/ChannelTransport.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 58-123 are not covered by tests
final ReceivePack rp = new ReceivePack(repo);
rp.receive(new BufferedInputStream(l2r.getIn()), new BufferedOutputStream(r2l.getOut()), null);
return null;
} finally {
IOUtils.closeQuietly(l2r.getIn());
IOUtils.closeQuietly(r2l.getOut());
repo.close();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.jenkinsci.plugins.gitserver;

import jakarta.servlet.http.HttpServletRequest;
import jenkins.model.Jenkins;
import org.acegisecurity.Authentication;
import org.eclipse.jgit.api.AddCommand;
import org.eclipse.jgit.api.CommitCommand;
import org.eclipse.jgit.api.Git;
Expand All @@ -11,19 +11,16 @@
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.transport.PostReceiveHook;
import org.eclipse.jgit.transport.ReceiveCommand;
import org.eclipse.jgit.transport.ReceivePack;
import org.eclipse.jgit.transport.UploadPack;
import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
import org.springframework.security.core.Authentication;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Collection;
import java.util.logging.Level;
import java.util.logging.Logger;

Expand Down Expand Up @@ -63,6 +60,7 @@ public Repository openRepository() throws IOException {
/**
* Called when there's no .git directory to create one.
*
* <p>
* This implementation also imports whatever currently in there into the repository.
*/
protected void createInitialRepository(Repository r) throws IOException {
Expand All @@ -80,14 +78,15 @@ protected void createInitialRepository(Repository r) throws IOException {
co.setMessage("Initial import of the existing contents");
co.call();
} catch (GitAPIException e) {
LOGGER.log(Level.WARNING, "Initial import of "+workspace+" into Git repository failed",e);
LOGGER.log(Level.WARNING, e, () -> "Initial import of "+workspace+" into Git repository failed");
}
}

/**
* This default implementation allows read access to anyone
* who can access the HTTP URL this repository is bound to.
*
* <p>
* For example, if this object is used as a project action,
* and the project isn't readable to Alice, then Alice won't be
* able to pull from this repository (think of a POSIX file system
Expand All @@ -103,7 +102,7 @@ public UploadPack createUploadPack(HttpServletRequest context, Repository db) th
*/
@Override
public ReceivePack createReceivePack(HttpServletRequest context, Repository db) throws ServiceNotEnabledException, ServiceNotAuthorizedException {
Authentication a = Jenkins.getAuthentication();
Authentication a = Jenkins.getAuthentication2();

ReceivePack rp = createReceivePack(db);

Expand All @@ -118,15 +117,13 @@ public ReceivePack createReceivePack(Repository db) {
ReceivePack rp = new ReceivePack(db);

// update userContent after the push
rp.setPostReceiveHook(new PostReceiveHook() {
public void onPostReceive(ReceivePack rp, Collection<ReceiveCommand> commands) {
try {
updateWorkspace(rp.getRepository());
} catch (Exception e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
rp.sendMessage("Failed to update workspace: "+sw);
}
rp.setPostReceiveHook((rp1, commands) -> {
try {
updateWorkspace(rp1.getRepository());
} catch (Exception e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
rp1.sendMessage("Failed to update workspace: "+sw);

Check warning on line 126 in src/main/java/org/jenkinsci/plugins/gitserver/FileBackedHttpGitRepository.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 81-126 are not covered by tests
}
});
return rp;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
package org.jenkinsci.plugins.gitserver;

import hudson.Util;
import hudson.model.Action;
import io.jenkins.servlet.http.HttpServletRequestWrapper;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jenkins.model.Jenkins;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.http.server.GitServlet;
Expand All @@ -12,16 +18,12 @@
import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
import org.eclipse.jgit.transport.resolver.UploadPackFactory;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.StaplerRequest2;
import org.kohsuke.stapler.StaplerResponse2;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

Expand All @@ -38,7 +40,7 @@ public abstract class HttpGitRepository {
private GitServlet g;
private Exception causeOfDeath;

public HttpGitRepository() {
protected HttpGitRepository() {
}

/**
Expand All @@ -49,6 +51,7 @@ public HttpGitRepository() {
/**
* Returns the {@link ReceivePack} that handles "git push" from client.
*
* <p>
* The most basic implementation is the following, which allows anyone to push to this repository,
* so normally you want some kind of access check before that. {@link DefaultReceivePackFactory} isn't suitable
* here because it requires that the user has non-empty name, which isn't necessarily true in Jenkins
Expand All @@ -60,11 +63,27 @@ public HttpGitRepository() {
*
* @see ReceivePackFactory#create(Object, Repository)
*/
public abstract ReceivePack createReceivePack(HttpServletRequest context, Repository db) throws ServiceNotEnabledException, ServiceNotAuthorizedException;
@SuppressWarnings({"deprecated", "java:S1874"})
public ReceivePack createReceivePack(HttpServletRequest context, Repository db) throws ServiceNotEnabledException, ServiceNotAuthorizedException {
return createReceivePack(HttpServletRequestWrapper.fromJakartaHttpServletRequest(context), db);
}

/**
* @deprecated Override {@link #createReceivePack(HttpServletRequest, Repository)} instead.
*/
@Deprecated(since = "132")
public ReceivePack createReceivePack(javax.servlet.http.HttpServletRequest context, Repository db) throws ServiceNotEnabledException, ServiceNotAuthorizedException {
if (Util.isOverridden(HttpGitRepository.class, getClass(), "createReceivePack", HttpServletRequest.class, Repository.class)) {
return createReceivePack(HttpServletRequestWrapper.toJakartaHttpServletRequest(context), db);
}
throw new AbstractMethodError("Implementing class '" + this.getClass().getName() + "' does not override " +
"either overload of the createReceivePack method.");
}

/**
* Returns the {@link UploadPack} that handles "git fetch" from client.
*
* <p>
* The most basic implementation is the following, which exposes this repository to everyone.
*
* <pre>
Expand All @@ -73,13 +92,28 @@ public HttpGitRepository() {
*
* @see UploadPackFactory#create(Object, Repository)
*/
public abstract UploadPack createUploadPack(HttpServletRequest context, Repository db) throws ServiceNotEnabledException, ServiceNotAuthorizedException;
@SuppressWarnings({"deprecated", "java:S1874"})
public UploadPack createUploadPack(HttpServletRequest context, Repository db) throws ServiceNotEnabledException, ServiceNotAuthorizedException {
return createUploadPack(HttpServletRequestWrapper.fromJakartaHttpServletRequest(context), db);
}

/**
* @deprecated Override {@link #createUploadPack(HttpServletRequest, Repository)} instead.
*/
@Deprecated(since = "132")
public UploadPack createUploadPack(javax.servlet.http.HttpServletRequest context, Repository db) throws ServiceNotEnabledException, ServiceNotAuthorizedException {
if (Util.isOverridden(HttpGitRepository.class, getClass(), "createUploadPack", HttpServletRequest.class, Repository.class)) {
return createUploadPack(HttpServletRequestWrapper.toJakartaHttpServletRequest(context), db);
}
throw new AbstractMethodError("Implementing class '" + this.getClass().getName() + "' does not override " +

Check warning on line 108 in src/main/java/org/jenkinsci/plugins/gitserver/HttpGitRepository.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 68-108 are not covered by tests
"either overload of the createUploadPack method.");
}

/**
* to make sure the user has the permission to pull.
*/
public void checkPullPermission() {
Jenkins.getInstance().checkPermission(Jenkins.READ);
Jenkins.get().checkPermission(Jenkins.READ);
}

protected GitServlet init() {
Expand Down Expand Up @@ -114,23 +148,19 @@ public String getServletName() {
}

public ServletContext getServletContext() throws IllegalStateException {
Jenkins j = Jenkins.getInstance();
if (j == null) {
throw new IllegalStateException();
}
return j.servletContext;
return Jenkins.get().getServletContext();
}

public String getInitParameter(String name) {
return null;
}

public Enumeration getInitParameterNames() {
return new Vector().elements();
public Enumeration<String> getInitParameterNames() {
return Collections.emptyEnumeration();
}
});
} catch (ServletException e) {
LOGGER.log(Level.WARNING,"Failed to initialize GitServlet for " + this,e);
LOGGER.log(Level.WARNING, e, () -> "Failed to initialize GitServlet for " + this);

Check warning on line 163 in src/main/java/org/jenkinsci/plugins/gitserver/HttpGitRepository.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 151-163 are not covered by tests
causeOfDeath = e;
}
return g;
Expand All @@ -139,7 +169,7 @@ public Enumeration getInitParameterNames() {
/**
* Handles git smart HTTP protocol.
*/
public void doDynamic(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
public void doDynamic(StaplerRequest2 req, StaplerResponse2 rsp) throws IOException, ServletException {
if (g==null)
g=init();

Expand Down
Loading

0 comments on commit ba97a8c

Please sign in to comment.