Merge branch 'stable-3.0' into stable-3.1
* stable-3.0: ChangeEditModifier: Reject invalid file paths as '400 Bad Request' Remove orphan library downloader facility Fix a bug where _moreChanges is set to the wrong value Don't check conflicting ref names when deleting refs Change-Id: Ic18373c4b4024de7bb9a50a8ac22651435e3b9cf
This commit is contained in:
@@ -150,6 +150,7 @@ public class RefUpdateUtil {
|
||||
public static void deleteChecked(Repository repo, String refName) throws IOException {
|
||||
RefUpdate ru = repo.updateRef(refName);
|
||||
ru.setForceUpdate(true);
|
||||
ru.setCheckConflicting(false);
|
||||
switch (ru.delete()) {
|
||||
case FORCED:
|
||||
// Ref was deleted.
|
||||
|
||||
@@ -34,8 +34,6 @@ public class InitModule extends FactoryModule {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(SitePaths.class);
|
||||
bind(Libraries.class);
|
||||
bind(LibraryDownloader.class);
|
||||
factory(Section.Factory.class);
|
||||
factory(VersionedAuthorizedKeysOnInit.Factory.class);
|
||||
|
||||
|
||||
@@ -1,141 +0,0 @@
|
||||
// Copyright (C) 2009 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.pgm.init;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.gerrit.pgm.init.api.LibraryDownload;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.List;
|
||||
import org.eclipse.jgit.errors.ConfigInvalidException;
|
||||
import org.eclipse.jgit.lib.Config;
|
||||
|
||||
/** Standard {@link LibraryDownloader} instances derived from configuration. */
|
||||
@Singleton
|
||||
class Libraries {
|
||||
private static final String RESOURCE_FILE = "com/google/gerrit/pgm/init/libraries.config";
|
||||
|
||||
private final Provider<LibraryDownloader> downloadProvider;
|
||||
private final List<String> skippedDownloads;
|
||||
private final boolean skipAllDownloads;
|
||||
|
||||
/* final */ LibraryDownloader db2Driver;
|
||||
/* final */ LibraryDownloader db2DriverLicense;
|
||||
/* final */ LibraryDownloader hanaDriver;
|
||||
/* final */ LibraryDownloader mariadbDriver;
|
||||
/* final */ LibraryDownloader mysqlDriver;
|
||||
/* final */ LibraryDownloader oracleDriver;
|
||||
|
||||
@Inject
|
||||
Libraries(
|
||||
final Provider<LibraryDownloader> downloadProvider,
|
||||
@LibraryDownload List<String> skippedDownloads,
|
||||
@LibraryDownload Boolean skipAllDownloads) {
|
||||
this.downloadProvider = downloadProvider;
|
||||
this.skippedDownloads = skippedDownloads;
|
||||
this.skipAllDownloads = skipAllDownloads;
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
final Config cfg = new Config();
|
||||
try {
|
||||
cfg.fromText(read(RESOURCE_FILE));
|
||||
} catch (IOException | ConfigInvalidException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
for (Field f : Libraries.class.getDeclaredFields()) {
|
||||
if ((f.getModifiers() & Modifier.STATIC) == 0 && f.getType() == LibraryDownloader.class) {
|
||||
try {
|
||||
f.set(this, downloadProvider.get());
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
throw new IllegalStateException("Cannot initialize " + f.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Field f : Libraries.class.getDeclaredFields()) {
|
||||
if ((f.getModifiers() & Modifier.STATIC) == 0 && f.getType() == LibraryDownloader.class) {
|
||||
try {
|
||||
init(f, cfg);
|
||||
} catch (IllegalArgumentException
|
||||
| IllegalAccessException
|
||||
| NoSuchFieldException
|
||||
| SecurityException e) {
|
||||
throw new IllegalStateException("Cannot configure " + f.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void init(Field field, Config cfg)
|
||||
throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException,
|
||||
SecurityException {
|
||||
String n = field.getName();
|
||||
LibraryDownloader dl = (LibraryDownloader) field.get(this);
|
||||
dl.setName(get(cfg, n, "name"));
|
||||
dl.setJarUrl(get(cfg, n, "url"));
|
||||
dl.setSHA1(getOptional(cfg, n, "sha1"));
|
||||
dl.setRemove(get(cfg, n, "remove"));
|
||||
for (String d : cfg.getStringList("library", n, "needs")) {
|
||||
dl.addNeeds((LibraryDownloader) getClass().getDeclaredField(d).get(this));
|
||||
}
|
||||
dl.setSkipDownload(skipAllDownloads || skippedDownloads.contains(n));
|
||||
}
|
||||
|
||||
private static String getOptional(Config cfg, String name, String key) {
|
||||
return doGet(cfg, name, key, false);
|
||||
}
|
||||
|
||||
private static String get(Config cfg, String name, String key) {
|
||||
return doGet(cfg, name, key, true);
|
||||
}
|
||||
|
||||
private static String doGet(Config cfg, String name, String key, boolean required) {
|
||||
String val = cfg.getString("library", name, key);
|
||||
if ((val == null || val.isEmpty()) && required) {
|
||||
throw new IllegalStateException(
|
||||
"Variable library." + name + "." + key + " is required within " + RESOURCE_FILE);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
private static String read(String p) throws IOException {
|
||||
try (InputStream in = Libraries.class.getClassLoader().getResourceAsStream(p)) {
|
||||
if (in == null) {
|
||||
throw new FileNotFoundException("Cannot load resource " + p);
|
||||
}
|
||||
try (Reader r = new InputStreamReader(in, UTF_8)) {
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
final char[] tmp = new char[512];
|
||||
int n;
|
||||
while (0 < (n = r.read(tmp))) {
|
||||
buf.append(tmp, 0, n);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,316 +0,0 @@
|
||||
// Copyright (C) 2009 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.pgm.init;
|
||||
|
||||
import com.google.common.hash.Funnels;
|
||||
import com.google.common.hash.Hasher;
|
||||
import com.google.common.hash.Hashing;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.google.gerrit.common.Die;
|
||||
import com.google.gerrit.common.IoUtil;
|
||||
import com.google.gerrit.pgm.init.api.ConsoleUI;
|
||||
import com.google.gerrit.server.config.SitePaths;
|
||||
import com.google.inject.Inject;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.Proxy;
|
||||
import java.net.ProxySelector;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.eclipse.jgit.util.HttpSupport;
|
||||
|
||||
/** Get optional or required 3rd party library files into $site_path/lib. */
|
||||
class LibraryDownloader {
|
||||
private final ConsoleUI ui;
|
||||
private final Path lib_dir;
|
||||
private final StaleLibraryRemover remover;
|
||||
|
||||
private boolean required;
|
||||
private String name;
|
||||
private String jarUrl;
|
||||
private String sha1;
|
||||
private String remove;
|
||||
private List<LibraryDownloader> needs;
|
||||
private LibraryDownloader neededBy;
|
||||
private Path dst;
|
||||
private boolean download; // download or copy
|
||||
private boolean exists;
|
||||
private boolean skipDownload;
|
||||
|
||||
@Inject
|
||||
LibraryDownloader(ConsoleUI ui, SitePaths site, StaleLibraryRemover remover) {
|
||||
this.ui = ui;
|
||||
this.lib_dir = site.lib_dir;
|
||||
this.remover = remover;
|
||||
this.needs = new ArrayList<>(2);
|
||||
}
|
||||
|
||||
void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
void setJarUrl(String url) {
|
||||
this.jarUrl = url;
|
||||
download = jarUrl.startsWith("http");
|
||||
}
|
||||
|
||||
void setSHA1(String sha1) {
|
||||
this.sha1 = sha1;
|
||||
}
|
||||
|
||||
void setRemove(String remove) {
|
||||
this.remove = remove;
|
||||
}
|
||||
|
||||
void addNeeds(LibraryDownloader lib) {
|
||||
needs.add(lib);
|
||||
}
|
||||
|
||||
void setSkipDownload(boolean skipDownload) {
|
||||
this.skipDownload = skipDownload;
|
||||
}
|
||||
|
||||
void downloadRequired() {
|
||||
setRequired(true);
|
||||
download();
|
||||
}
|
||||
|
||||
void downloadOptional() {
|
||||
required = false;
|
||||
download();
|
||||
}
|
||||
|
||||
private void setRequired(boolean r) {
|
||||
required = r;
|
||||
for (LibraryDownloader d : needs) {
|
||||
d.setRequired(r);
|
||||
}
|
||||
}
|
||||
|
||||
private void download() {
|
||||
if (skipDownload) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (jarUrl == null || !jarUrl.contains("/")) {
|
||||
throw new IllegalStateException("Invalid JarUrl for " + name);
|
||||
}
|
||||
|
||||
final String jarName = jarUrl.substring(jarUrl.lastIndexOf('/') + 1);
|
||||
if (jarName.contains("/") || jarName.contains("\\")) {
|
||||
throw new IllegalStateException("Invalid JarUrl: " + jarUrl);
|
||||
}
|
||||
|
||||
if (name == null) {
|
||||
name = jarName;
|
||||
}
|
||||
|
||||
dst = lib_dir.resolve(jarName);
|
||||
if (Files.exists(dst)) {
|
||||
exists = true;
|
||||
} else if (shouldGet()) {
|
||||
doGet();
|
||||
}
|
||||
|
||||
if (exists) {
|
||||
for (LibraryDownloader d : needs) {
|
||||
d.neededBy = this;
|
||||
d.downloadRequired();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldGet() {
|
||||
if (ui.isBatch()) {
|
||||
return required;
|
||||
}
|
||||
final StringBuilder msg = new StringBuilder();
|
||||
msg.append("\n");
|
||||
msg.append("Gerrit Code Review is not shipped with %s\n");
|
||||
if (neededBy != null) {
|
||||
msg.append(String.format("** This library is required by %s. **\n", neededBy.name));
|
||||
} else if (required) {
|
||||
msg.append("** This library is required for your configuration. **\n");
|
||||
} else {
|
||||
msg.append(" If available, Gerrit can take advantage of features\n");
|
||||
msg.append(" in the library, but will also function without it.\n");
|
||||
}
|
||||
msg.append(String.format("%s and install it now", download ? "Download" : "Copy"));
|
||||
return ui.yesno(true, msg.toString(), name);
|
||||
}
|
||||
|
||||
private void doGet() {
|
||||
if (!Files.exists(lib_dir)) {
|
||||
try {
|
||||
Files.createDirectories(lib_dir);
|
||||
} catch (IOException e) {
|
||||
throw new Die("Cannot create " + lib_dir, e);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
remover.remove(remove);
|
||||
if (download) {
|
||||
doGetByHttp();
|
||||
} else {
|
||||
doGetByLocalCopy();
|
||||
}
|
||||
verifyFileChecksum();
|
||||
} catch (IOException err) {
|
||||
try {
|
||||
Files.delete(dst);
|
||||
} catch (IOException e) {
|
||||
// Delete failed; leave alone.
|
||||
}
|
||||
|
||||
if (ui.isBatch()) {
|
||||
throw new Die("error: Cannot get " + jarUrl, err);
|
||||
}
|
||||
|
||||
System.err.println();
|
||||
System.err.println();
|
||||
System.err.println("error: " + err.getMessage());
|
||||
System.err.println("Please download:");
|
||||
System.err.println();
|
||||
System.err.println(" " + jarUrl);
|
||||
System.err.println();
|
||||
System.err.println("and save as:");
|
||||
System.err.println();
|
||||
System.err.println(" " + dst.toAbsolutePath());
|
||||
System.err.println();
|
||||
System.err.flush();
|
||||
|
||||
ui.waitForUser();
|
||||
|
||||
if (Files.exists(dst)) {
|
||||
verifyFileChecksum();
|
||||
|
||||
} else if (!ui.yesno(!required, "Continue without this library")) {
|
||||
throw new Die("aborted by user");
|
||||
}
|
||||
}
|
||||
|
||||
if (Files.exists(dst)) {
|
||||
exists = true;
|
||||
IoUtil.loadJARs(dst);
|
||||
}
|
||||
}
|
||||
|
||||
private void doGetByLocalCopy() throws IOException {
|
||||
System.err.print("Copying " + jarUrl + " ...");
|
||||
Path p = url2file(jarUrl);
|
||||
if (!Files.exists(p)) {
|
||||
StringBuilder msg =
|
||||
new StringBuilder()
|
||||
.append("\n")
|
||||
.append("Can not find the %s at this location: %s\n")
|
||||
.append("Please provide alternative URL");
|
||||
p = url2file(ui.readString(null, msg.toString(), name, jarUrl));
|
||||
}
|
||||
Files.copy(p, dst);
|
||||
}
|
||||
|
||||
private static Path url2file(String urlString) throws IOException {
|
||||
final URL url = new URL(urlString);
|
||||
try {
|
||||
return Paths.get(url.toURI());
|
||||
} catch (URISyntaxException e) {
|
||||
return Paths.get(url.getPath());
|
||||
}
|
||||
}
|
||||
|
||||
private void doGetByHttp() throws IOException {
|
||||
System.err.print("Downloading " + jarUrl + " ...");
|
||||
System.err.flush();
|
||||
try (InputStream in = openHttpStream(jarUrl);
|
||||
OutputStream out = Files.newOutputStream(dst)) {
|
||||
ByteStreams.copy(in, out);
|
||||
System.err.println(" OK");
|
||||
System.err.flush();
|
||||
} catch (IOException err) {
|
||||
deleteDst();
|
||||
System.err.println(" !! FAIL !!");
|
||||
System.err.println(err);
|
||||
System.err.flush();
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
private static InputStream openHttpStream(String urlStr) throws IOException {
|
||||
ProxySelector proxySelector = ProxySelector.getDefault();
|
||||
URL url = new URL(urlStr);
|
||||
Proxy proxy = HttpSupport.proxyFor(proxySelector, url);
|
||||
HttpURLConnection c = (HttpURLConnection) url.openConnection(proxy);
|
||||
|
||||
switch (HttpSupport.response(c)) {
|
||||
case HttpURLConnection.HTTP_OK:
|
||||
return c.getInputStream();
|
||||
|
||||
case HttpURLConnection.HTTP_NOT_FOUND:
|
||||
throw new FileNotFoundException(url.toString());
|
||||
|
||||
default:
|
||||
throw new IOException(
|
||||
url.toString() + ": " + HttpSupport.response(c) + " " + c.getResponseMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation") // Use Hashing.sha1 for compatibility.
|
||||
private void verifyFileChecksum() {
|
||||
if (sha1 == null) {
|
||||
System.err.println();
|
||||
System.err.flush();
|
||||
return;
|
||||
}
|
||||
Hasher h = Hashing.sha1().newHasher();
|
||||
try (InputStream in = Files.newInputStream(dst);
|
||||
OutputStream out = Funnels.asOutputStream(h)) {
|
||||
ByteStreams.copy(in, out);
|
||||
} catch (IOException e) {
|
||||
deleteDst();
|
||||
throw new Die("cannot checksum " + dst, e);
|
||||
}
|
||||
if (sha1.equals(h.hash().toString())) {
|
||||
System.err.println("Checksum " + dst.getFileName() + " OK");
|
||||
System.err.flush();
|
||||
} else if (ui.isBatch()) {
|
||||
deleteDst();
|
||||
throw new Die(dst + " SHA-1 checksum does not match");
|
||||
|
||||
} else if (!ui.yesno(
|
||||
null /* force an answer */,
|
||||
"error: SHA-1 checksum does not match\nUse %s anyway", //
|
||||
dst.getFileName())) {
|
||||
deleteDst();
|
||||
throw new Die("aborted by user");
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteDst() {
|
||||
try {
|
||||
Files.delete(dst);
|
||||
} catch (IOException e) {
|
||||
System.err.println(" Failed to clean up lib: " + dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,6 +51,7 @@ import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.TimeZone;
|
||||
import org.eclipse.jgit.dircache.InvalidPathException;
|
||||
import org.eclipse.jgit.lib.BatchRefUpdate;
|
||||
import org.eclipse.jgit.lib.CommitBuilder;
|
||||
import org.eclipse.jgit.lib.NullProgressMonitor;
|
||||
@@ -243,13 +244,14 @@ public class ChangeEditModifier {
|
||||
* @param filePath the path of the file whose contents should be modified
|
||||
* @param newContent the new file content
|
||||
* @throws AuthException if the user isn't authenticated or not allowed to use change edits
|
||||
* @throws BadRequestException if the user provided bad input (e.g. invalid file paths)
|
||||
* @throws InvalidChangeOperationException if the file already had the specified content
|
||||
* @throws PermissionBackendException
|
||||
* @throws ResourceConflictException if the project state does not permit the operation
|
||||
*/
|
||||
public void modifyFile(
|
||||
Repository repository, ChangeNotes notes, String filePath, RawInput newContent)
|
||||
throws AuthException, InvalidChangeOperationException, IOException,
|
||||
throws AuthException, BadRequestException, InvalidChangeOperationException, IOException,
|
||||
PermissionBackendException, ResourceConflictException {
|
||||
modifyTree(repository, notes, new ChangeFileContentModification(filePath, newContent));
|
||||
}
|
||||
@@ -262,12 +264,13 @@ public class ChangeEditModifier {
|
||||
* @param notes the {@link ChangeNotes} of the change whose change edit should be modified
|
||||
* @param file path of the file which should be deleted
|
||||
* @throws AuthException if the user isn't authenticated or not allowed to use change edits
|
||||
* @throws BadRequestException if the user provided bad input (e.g. invalid file paths)
|
||||
* @throws InvalidChangeOperationException if the file does not exist
|
||||
* @throws PermissionBackendException
|
||||
* @throws ResourceConflictException if the project state does not permit the operation
|
||||
*/
|
||||
public void deleteFile(Repository repository, ChangeNotes notes, String file)
|
||||
throws AuthException, InvalidChangeOperationException, IOException,
|
||||
throws AuthException, BadRequestException, InvalidChangeOperationException, IOException,
|
||||
PermissionBackendException, ResourceConflictException {
|
||||
modifyTree(repository, notes, new DeleteFileModification(file));
|
||||
}
|
||||
@@ -281,6 +284,7 @@ public class ChangeEditModifier {
|
||||
* @param currentFilePath the current path/name of the file
|
||||
* @param newFilePath the desired path/name of the file
|
||||
* @throws AuthException if the user isn't authenticated or not allowed to use change edits
|
||||
* @throws BadRequestException if the user provided bad input (e.g. invalid file paths)
|
||||
* @throws InvalidChangeOperationException if the file was already renamed to the specified new
|
||||
* name
|
||||
* @throws PermissionBackendException
|
||||
@@ -288,7 +292,7 @@ public class ChangeEditModifier {
|
||||
*/
|
||||
public void renameFile(
|
||||
Repository repository, ChangeNotes notes, String currentFilePath, String newFilePath)
|
||||
throws AuthException, InvalidChangeOperationException, IOException,
|
||||
throws AuthException, BadRequestException, InvalidChangeOperationException, IOException,
|
||||
PermissionBackendException, ResourceConflictException {
|
||||
modifyTree(repository, notes, new RenameFileModification(currentFilePath, newFilePath));
|
||||
}
|
||||
@@ -306,14 +310,14 @@ public class ChangeEditModifier {
|
||||
* @throws PermissionBackendException
|
||||
*/
|
||||
public void restoreFile(Repository repository, ChangeNotes notes, String file)
|
||||
throws AuthException, InvalidChangeOperationException, IOException,
|
||||
throws AuthException, BadRequestException, InvalidChangeOperationException, IOException,
|
||||
PermissionBackendException, ResourceConflictException {
|
||||
modifyTree(repository, notes, new RestoreFileModification(file));
|
||||
}
|
||||
|
||||
private void modifyTree(
|
||||
Repository repository, ChangeNotes notes, TreeModification treeModification)
|
||||
throws AuthException, IOException, InvalidChangeOperationException,
|
||||
throws AuthException, BadRequestException, IOException, InvalidChangeOperationException,
|
||||
PermissionBackendException, ResourceConflictException {
|
||||
assertCanEdit(notes);
|
||||
|
||||
@@ -358,8 +362,8 @@ public class ChangeEditModifier {
|
||||
ChangeNotes notes,
|
||||
PatchSet patchSet,
|
||||
List<TreeModification> treeModifications)
|
||||
throws AuthException, IOException, InvalidChangeOperationException, MergeConflictException,
|
||||
PermissionBackendException, ResourceConflictException {
|
||||
throws AuthException, BadRequestException, IOException, InvalidChangeOperationException,
|
||||
MergeConflictException, PermissionBackendException, ResourceConflictException {
|
||||
assertCanEdit(notes);
|
||||
|
||||
Optional<ChangeEdit> optionalChangeEdit = lookupChangeEdit(notes);
|
||||
@@ -469,10 +473,15 @@ public class ChangeEditModifier {
|
||||
|
||||
private static ObjectId createNewTree(
|
||||
Repository repository, RevCommit baseCommit, List<TreeModification> treeModifications)
|
||||
throws IOException, InvalidChangeOperationException {
|
||||
TreeCreator treeCreator = new TreeCreator(baseCommit);
|
||||
treeCreator.addTreeModifications(treeModifications);
|
||||
ObjectId newTreeId = treeCreator.createNewTreeAndGetId(repository);
|
||||
throws BadRequestException, IOException, InvalidChangeOperationException {
|
||||
ObjectId newTreeId;
|
||||
try {
|
||||
TreeCreator treeCreator = new TreeCreator(baseCommit);
|
||||
treeCreator.addTreeModifications(treeModifications);
|
||||
newTreeId = treeCreator.createNewTreeAndGetId(repository);
|
||||
} catch (InvalidPathException e) {
|
||||
throw new BadRequestException(e.getMessage());
|
||||
}
|
||||
|
||||
if (ObjectId.isEqual(newTreeId, baseCommit.getTree())) {
|
||||
throw new InvalidChangeOperationException("no changes were made");
|
||||
|
||||
@@ -18,6 +18,7 @@ import com.google.gerrit.entities.PatchSet;
|
||||
import com.google.gerrit.entities.Project;
|
||||
import com.google.gerrit.extensions.common.EditInfo;
|
||||
import com.google.gerrit.extensions.restapi.AuthException;
|
||||
import com.google.gerrit.extensions.restapi.BadRequestException;
|
||||
import com.google.gerrit.extensions.restapi.ResourceConflictException;
|
||||
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
||||
import com.google.gerrit.extensions.restapi.Response;
|
||||
@@ -65,8 +66,8 @@ public class ApplyFix implements RestModifyView<FixResource, Void> {
|
||||
|
||||
@Override
|
||||
public Response<EditInfo> apply(FixResource fixResource, Void nothing)
|
||||
throws AuthException, ResourceConflictException, IOException, ResourceNotFoundException,
|
||||
PermissionBackendException {
|
||||
throws AuthException, BadRequestException, ResourceConflictException, IOException,
|
||||
ResourceNotFoundException, PermissionBackendException {
|
||||
RevisionResource revisionResource = fixResource.getRevisionResource();
|
||||
Project.NameKey project = revisionResource.getProject();
|
||||
ProjectState projectState = projectCache.checkedGet(project);
|
||||
|
||||
@@ -118,7 +118,8 @@ public class ChangeEdits implements ChildCollection<ChangeResource, ChangeEditRe
|
||||
|
||||
@Override
|
||||
public Response<?> apply(ChangeResource resource, IdString id, Put.Input input)
|
||||
throws AuthException, ResourceConflictException, IOException, PermissionBackendException {
|
||||
throws AuthException, ResourceConflictException, BadRequestException, IOException,
|
||||
PermissionBackendException {
|
||||
putEdit.apply(resource, id.get(), input.content);
|
||||
return Response.none();
|
||||
}
|
||||
@@ -135,7 +136,8 @@ public class ChangeEdits implements ChildCollection<ChangeResource, ChangeEditRe
|
||||
|
||||
@Override
|
||||
public Response<?> apply(ChangeResource rsrc, IdString id, Input in)
|
||||
throws IOException, AuthException, ResourceConflictException, PermissionBackendException {
|
||||
throws IOException, AuthException, BadRequestException, ResourceConflictException,
|
||||
PermissionBackendException {
|
||||
return deleteContent.apply(rsrc, id.get());
|
||||
}
|
||||
}
|
||||
@@ -236,7 +238,8 @@ public class ChangeEdits implements ChildCollection<ChangeResource, ChangeEditRe
|
||||
|
||||
@Override
|
||||
public Response<?> apply(ChangeResource resource, Post.Input input)
|
||||
throws AuthException, IOException, ResourceConflictException, PermissionBackendException {
|
||||
throws AuthException, BadRequestException, IOException, ResourceConflictException,
|
||||
PermissionBackendException {
|
||||
Project.NameKey project = resource.getProject();
|
||||
try (Repository repository = repositoryManager.openRepository(project)) {
|
||||
if (isRestoreFile(input)) {
|
||||
@@ -281,12 +284,14 @@ public class ChangeEdits implements ChildCollection<ChangeResource, ChangeEditRe
|
||||
|
||||
@Override
|
||||
public Response<?> apply(ChangeEditResource rsrc, Input input)
|
||||
throws AuthException, ResourceConflictException, IOException, PermissionBackendException {
|
||||
throws AuthException, ResourceConflictException, BadRequestException, IOException,
|
||||
PermissionBackendException {
|
||||
return apply(rsrc.getChangeResource(), rsrc.getPath(), input.content);
|
||||
}
|
||||
|
||||
public Response<?> apply(ChangeResource rsrc, String path, RawInput newContent)
|
||||
throws ResourceConflictException, AuthException, IOException, PermissionBackendException {
|
||||
throws ResourceConflictException, AuthException, BadRequestException, IOException,
|
||||
PermissionBackendException {
|
||||
if (Strings.isNullOrEmpty(path) || path.charAt(0) == '/') {
|
||||
throw new ResourceConflictException("Invalid path: " + path);
|
||||
}
|
||||
@@ -320,12 +325,14 @@ public class ChangeEdits implements ChildCollection<ChangeResource, ChangeEditRe
|
||||
|
||||
@Override
|
||||
public Response<?> apply(ChangeEditResource rsrc, Input input)
|
||||
throws AuthException, ResourceConflictException, IOException, PermissionBackendException {
|
||||
throws AuthException, BadRequestException, ResourceConflictException, IOException,
|
||||
PermissionBackendException {
|
||||
return apply(rsrc.getChangeResource(), rsrc.getPath());
|
||||
}
|
||||
|
||||
public Response<?> apply(ChangeResource rsrc, String filePath)
|
||||
throws AuthException, IOException, ResourceConflictException, PermissionBackendException {
|
||||
throws AuthException, BadRequestException, IOException, ResourceConflictException,
|
||||
PermissionBackendException {
|
||||
try (Repository repository = repositoryManager.openRepository(rsrc.getProject())) {
|
||||
editModifier.deleteFile(repository, rsrc.getNotes(), filePath);
|
||||
} catch (InvalidChangeOperationException e) {
|
||||
|
||||
@@ -58,6 +58,7 @@ import com.google.gerrit.extensions.common.DiffInfo;
|
||||
import com.google.gerrit.extensions.common.EditInfo;
|
||||
import com.google.gerrit.extensions.common.FileInfo;
|
||||
import com.google.gerrit.extensions.restapi.AuthException;
|
||||
import com.google.gerrit.extensions.restapi.BadRequestException;
|
||||
import com.google.gerrit.extensions.restapi.BinaryResult;
|
||||
import com.google.gerrit.extensions.restapi.ResourceConflictException;
|
||||
import com.google.gerrit.server.ChangeMessagesUtil;
|
||||
@@ -435,6 +436,16 @@ public class ChangeEditIT extends AbstractDaemonTest {
|
||||
assertThat(getFileContentOfEdit(changeId, FILE_NAME)).isAbsent();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void renameExistingFileToInvalidPath() throws Exception {
|
||||
createEmptyEditFor(changeId);
|
||||
BadRequestException badRequest =
|
||||
assertThrows(
|
||||
BadRequestException.class,
|
||||
() -> gApi.changes().id(changeId).edit().renameFile(FILE_NAME, "invalid/path/"));
|
||||
assertThat(badRequest.getMessage()).isEqualTo("Invalid path: invalid/path/");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createEditByDeletingExistingFileRest() throws Exception {
|
||||
adminRestSession.delete(urlEditFile(changeId, FILE_NAME)).assertNoContent();
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
// Copyright (C) 2009 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.pgm.init;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
|
||||
import com.google.gerrit.pgm.init.api.ConsoleUI;
|
||||
import com.google.gerrit.server.config.SitePaths;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collections;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class LibrariesTest {
|
||||
@Mock ConsoleUI ui;
|
||||
@Mock StaleLibraryRemover remover;
|
||||
|
||||
@Test
|
||||
public void create() throws Exception {
|
||||
final SitePaths site = new SitePaths(Paths.get("."));
|
||||
|
||||
Libraries lib =
|
||||
new Libraries(
|
||||
() -> new LibraryDownloader(ui, site, remover), Collections.emptyList(), false);
|
||||
|
||||
assertNotNull(lib.mysqlDriver);
|
||||
verifyZeroInteractions(ui);
|
||||
verifyZeroInteractions(remover);
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
# Copyright (C) 2009 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.
|
||||
|
||||
[library "mysqlDriver"]
|
||||
name = MySQL Connector/J 5.1.43
|
||||
url = https://repo1.maven.org/maven2/mysql/mysql-connector-java/5.1.43/mysql-connector-java-5.1.43.jar
|
||||
sha1 = dee9103eec0d877f3a21c82d4d9e9f4fbd2d6e0a
|
||||
remove = mysql-connector-java-.*[.]jar
|
||||
|
||||
[library "mariadbDriver"]
|
||||
name = MariaDB Connector/J 2.3.0
|
||||
url = https://repo1.maven.org/maven2/org/mariadb/jdbc/mariadb-java-client/2.3.0/mariadb-java-client-2.3.0.jar
|
||||
sha1 = c2b1a6002a169757d0649449288e9b3b776af76b
|
||||
remove = mariadb-java-client-.*[.]jar
|
||||
|
||||
[library "oracleDriver"]
|
||||
name = Oracle JDBC driver 11g Release 2 (11.2.0)
|
||||
url = file:///u01/app/oracle/product/11.2.0/xe/jdbc/lib/ojdbc6.jar
|
||||
sha1 = 2f89cd9176772c3a6c261ce6a8e3d0d4425f5679
|
||||
remove = ojdbc6.jar
|
||||
|
||||
[library "db2Driver"]
|
||||
name = DB2 Type 4 JDBC driver (10.5)
|
||||
url = file:///opt/ibm/db2/V10.5/java/db2jcc4.jar
|
||||
sha1 = 9344d4fd41d6511f2d1d1deb7759056495b3a39b
|
||||
needs = db2DriverLicense
|
||||
remove = db2jcc4.jar
|
||||
|
||||
# Omit SHA-1 for license JAR as it's not stable and depends on the product
|
||||
# the customer has purchased.
|
||||
[library "db2DriverLicense"]
|
||||
name = DB2 Type 4 JDBC driver license (10.5)
|
||||
url = file:///opt/ibm/db2/V10.5/java/db2jcc_license_cu.jar
|
||||
remove = db2jcc_license_cu.jar
|
||||
|
||||
[library "hanaDriver"]
|
||||
name = HANA JDBC driver
|
||||
url = file:///usr/sap/hdbclient/ngdbc.jar
|
||||
remove = ngdbc.jar
|
||||
Reference in New Issue
Block a user