Merge branch 'stable-2.15'
* stable-2.15:
Fix access path propagation on git/ssh protocol
Fix support for setting owner of group to a single user
Set version to 2.15.5
Set version to 2.14.15
Add tests for .gitmodules validation
Remove occurrence of "is="gr-select"" in gr-create-project-dialog
Add support for "max_object_size_limit" effective value
Update JGit to 4.7.5.201810051826-r
Update JGit to 4.9.6.201810051924-r
ElasticContainer: Use Elasticsearch 6.4.2 for V6_4 tests
Upgrade elasticsearch-rest-client to 6.4.2
Upgrade jackson-core to 2.9.7
This merge partially reverts change I27fc60caf ("Upgrade jackson-core to
2.9.7") which limited the visibility of jackson-core to Elasticsearch.
Since change If4d62922f, jackson-core is exported in the plugin API
and thus its visibility cannot be restricted.
Change-Id: I69847856636ad3084d78686a02414b771cf38033
This commit is contained in:
@@ -1085,12 +1085,12 @@ maven_jar(
|
|||||||
sha1 = "a2baf2d4fdf03f31fbd39351a32bee25fcdfa1cf",
|
sha1 = "a2baf2d4fdf03f31fbd39351a32bee25fcdfa1cf",
|
||||||
)
|
)
|
||||||
|
|
||||||
JACKSON_VERSION = "2.8.9"
|
JACKSON_VERSION = "2.9.7"
|
||||||
|
|
||||||
maven_jar(
|
maven_jar(
|
||||||
name = "jackson-core",
|
name = "jackson-core",
|
||||||
artifact = "com.fasterxml.jackson.core:jackson-core:" + JACKSON_VERSION,
|
artifact = "com.fasterxml.jackson.core:jackson-core:" + JACKSON_VERSION,
|
||||||
sha1 = "569b1752705da98f49aabe2911cc956ff7d8ed9d",
|
sha1 = "4b7f0e0dc527fab032e9800ed231080fdc3ac015",
|
||||||
)
|
)
|
||||||
|
|
||||||
maven_jar(
|
maven_jar(
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
// Copyright (C) 2018 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package com.google.gerrit.acceptance.git;
|
||||||
|
|
||||||
|
import com.google.gerrit.acceptance.AbstractDaemonTest;
|
||||||
|
import org.eclipse.jgit.api.errors.TransportException;
|
||||||
|
import org.eclipse.jgit.junit.TestRepository;
|
||||||
|
import org.eclipse.jgit.lib.Config;
|
||||||
|
import org.eclipse.jgit.transport.RefSpec;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class GitmodulesIT extends AbstractDaemonTest {
|
||||||
|
@Test
|
||||||
|
public void invalidSubmoduleURLIsRejected() throws Exception {
|
||||||
|
pushGitmodules("name", "-invalid-url", "path", "Invalid submodule URL");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void invalidSubmodulePathIsRejected() throws Exception {
|
||||||
|
pushGitmodules("name", "http://somewhere", "-invalid-path", "Invalid submodule path");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void invalidSubmoduleNameIsRejected() throws Exception {
|
||||||
|
pushGitmodules("-invalid-name", "http://somewhere", "path", "Invalid submodule name");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void pushGitmodules(String name, String url, String path, String expectedErrorMessage)
|
||||||
|
throws Exception {
|
||||||
|
Config config = new Config();
|
||||||
|
config.setString("submodule", name, "url", url);
|
||||||
|
config.setString("submodule", name, "path", path);
|
||||||
|
TestRepository<?> repo = cloneProject(project);
|
||||||
|
repo.branch("HEAD")
|
||||||
|
.commit()
|
||||||
|
.insertChangeId()
|
||||||
|
.message("subject: adding new subscription")
|
||||||
|
.add(".gitmodules", config.toText().toString())
|
||||||
|
.create();
|
||||||
|
|
||||||
|
exception.expectMessage(expectedErrorMessage);
|
||||||
|
exception.expect(TransportException.class);
|
||||||
|
repo.git().push().setRemote("origin").setRefSpecs(new RefSpec("HEAD:refs/for/master")).call();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -32,8 +32,6 @@ public abstract class AbstractGitCommand extends BaseCommand {
|
|||||||
@Argument(index = 0, metaVar = "PROJECT.git", required = true, usage = "project name")
|
@Argument(index = 0, metaVar = "PROJECT.git", required = true, usage = "project name")
|
||||||
protected ProjectState projectState;
|
protected ProjectState projectState;
|
||||||
|
|
||||||
@Inject private SshScope sshScope;
|
|
||||||
|
|
||||||
@Inject private GitRepositoryManager repoManager;
|
@Inject private GitRepositoryManager repoManager;
|
||||||
|
|
||||||
@Inject private SshSession session;
|
@Inject private SshSession session;
|
||||||
@@ -49,28 +47,24 @@ public abstract class AbstractGitCommand extends BaseCommand {
|
|||||||
@Override
|
@Override
|
||||||
public void start(Environment env) {
|
public void start(Environment env) {
|
||||||
Context ctx = context.subContext(newSession(), context.getCommandLine());
|
Context ctx = context.subContext(newSession(), context.getCommandLine());
|
||||||
final Context old = sshScope.set(ctx);
|
startThreadWithContext(
|
||||||
try {
|
ctx,
|
||||||
startThread(
|
new ProjectCommandRunnable() {
|
||||||
new ProjectCommandRunnable() {
|
@Override
|
||||||
@Override
|
public void executeParseCommand() throws Exception {
|
||||||
public void executeParseCommand() throws Exception {
|
parseCommandLine();
|
||||||
parseCommandLine();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() throws Exception {
|
public void run() throws Exception {
|
||||||
AbstractGitCommand.this.service();
|
AbstractGitCommand.this.service();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Project.NameKey getProjectName() {
|
public Project.NameKey getProjectName() {
|
||||||
return projectState.getNameKey();
|
return projectState.getNameKey();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} finally {
|
|
||||||
sshScope.set(old);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private SshSession newSession() {
|
private SshSession newSession() {
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ import java.io.OutputStreamWriter;
|
|||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
@@ -260,6 +261,38 @@ public abstract class BaseCommand implements Command {
|
|||||||
return cmdLineParserFactory.create(options);
|
return cmdLineParserFactory.create(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spawn a function into its own thread with the provided context.
|
||||||
|
*
|
||||||
|
* <p>Typically this should be invoked within {@link Command#start(Environment)}, such as:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* startThreadWithContext(SshScope.Context context, new CommandRunnable() {
|
||||||
|
* public void run() throws Exception {
|
||||||
|
* runImp();
|
||||||
|
* }
|
||||||
|
* });
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* <p>If the function throws an exception, it is translated to a simple message for the client, a
|
||||||
|
* non-zero exit code, and the stack trace is logged.
|
||||||
|
*
|
||||||
|
* @param thunk the runnable to execute on the thread, performing the command's logic.
|
||||||
|
*/
|
||||||
|
protected void startThreadWithContext(SshScope.Context context, CommandRunnable thunk) {
|
||||||
|
final TaskThunk tt = new TaskThunk(thunk, Optional.ofNullable(context));
|
||||||
|
|
||||||
|
if (isAdminHighPriorityCommand()) {
|
||||||
|
// Admin commands should not block the main work threads (there
|
||||||
|
// might be an interactive shell there), nor should they wait
|
||||||
|
// for the main work threads.
|
||||||
|
//
|
||||||
|
new Thread(tt, tt.toString()).start();
|
||||||
|
} else {
|
||||||
|
task.set(executor.submit(tt));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spawn a function into its own thread.
|
* Spawn a function into its own thread.
|
||||||
*
|
*
|
||||||
@@ -278,18 +311,8 @@ public abstract class BaseCommand implements Command {
|
|||||||
*
|
*
|
||||||
* @param thunk the runnable to execute on the thread, performing the command's logic.
|
* @param thunk the runnable to execute on the thread, performing the command's logic.
|
||||||
*/
|
*/
|
||||||
protected void startThread(CommandRunnable thunk) {
|
protected void startThread(final CommandRunnable thunk) {
|
||||||
final TaskThunk tt = new TaskThunk(thunk);
|
startThreadWithContext(null, thunk);
|
||||||
|
|
||||||
if (isAdminHighPriorityCommand()) {
|
|
||||||
// Admin commands should not block the main work threads (there
|
|
||||||
// might be an interactive shell there), nor should they wait
|
|
||||||
// for the main work threads.
|
|
||||||
//
|
|
||||||
new Thread(tt, tt.toString()).start();
|
|
||||||
} else {
|
|
||||||
task.set(executor.submit(tt));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isAdminHighPriorityCommand() {
|
private boolean isAdminHighPriorityCommand() {
|
||||||
@@ -416,18 +439,21 @@ public abstract class BaseCommand implements Command {
|
|||||||
|
|
||||||
private final class TaskThunk implements CancelableRunnable, ProjectRunnable {
|
private final class TaskThunk implements CancelableRunnable, ProjectRunnable {
|
||||||
private final CommandRunnable thunk;
|
private final CommandRunnable thunk;
|
||||||
|
private final Context taskContext;
|
||||||
private final String taskName;
|
private final String taskName;
|
||||||
|
|
||||||
private Project.NameKey projectName;
|
private Project.NameKey projectName;
|
||||||
|
|
||||||
private TaskThunk(CommandRunnable thunk) {
|
private TaskThunk(CommandRunnable thunk, Optional<Context> oneOffContext) {
|
||||||
this.thunk = thunk;
|
this.thunk = thunk;
|
||||||
this.taskName = getTaskName();
|
this.taskName = getTaskName();
|
||||||
|
this.taskContext = oneOffContext.orElse(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cancel() {
|
public void cancel() {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
final Context old = sshScope.set(context);
|
final Context old = sshScope.set(taskContext);
|
||||||
try {
|
try {
|
||||||
onExit(STATUS_CANCEL);
|
onExit(STATUS_CANCEL);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -442,7 +468,7 @@ public abstract class BaseCommand implements Command {
|
|||||||
final Thread thisThread = Thread.currentThread();
|
final Thread thisThread = Thread.currentThread();
|
||||||
final String thisName = thisThread.getName();
|
final String thisName = thisThread.getName();
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
final Context old = sshScope.set(context);
|
final Context old = sshScope.set(taskContext);
|
||||||
try {
|
try {
|
||||||
context.started = TimeUtil.nowMs();
|
context.started = TimeUtil.nowMs();
|
||||||
thisThread.setName("SSH " + taskName);
|
thisThread.setName("SSH " + taskName);
|
||||||
|
|||||||
Reference in New Issue
Block a user