Ignore .DS_Store files on macOS
Finder creates these files if you browse a directory there. These files are really annoying, but it's an incredible pain for users that these files are created unbeknownst to them, and then they get in the way of Elasticsearch starting. This commit adds leniency on macOS only to skip these files. Relates #27108
This commit is contained in:
parent
149e558dd5
commit
6722b9c4a2
|
@ -21,6 +21,7 @@ package org.elasticsearch.bootstrap;
|
|||
|
||||
import org.apache.lucene.util.Constants;
|
||||
import org.apache.lucene.util.IOUtils;
|
||||
import org.elasticsearch.common.io.FileSystemUtils;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.plugins.Platforms;
|
||||
import org.elasticsearch.plugins.PluginInfo;
|
||||
|
@ -73,6 +74,9 @@ final class Spawner implements Closeable {
|
|||
*/
|
||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(pluginsFile)) {
|
||||
for (final Path plugin : stream) {
|
||||
if (FileSystemUtils.isDesktopServicesStore(plugin)) {
|
||||
continue;
|
||||
}
|
||||
final PluginInfo info = PluginInfo.readFromProperties(plugin);
|
||||
final Path spawnPath = Platforms.nativeControllerPath(plugin);
|
||||
if (!Files.isRegularFile(spawnPath)) {
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package org.elasticsearch.common.io;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.lucene.util.Constants;
|
||||
import org.apache.lucene.util.IOUtils;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.SuppressForbidden;
|
||||
|
@ -65,6 +66,16 @@ public final class FileSystemUtils {
|
|||
return fileName.toString().startsWith(".");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the file denoted by the given path is a desktop services store created by Finder on macOS.
|
||||
*
|
||||
* @param path the path
|
||||
* @return true if the current system is macOS and the specified file appears to be a desktop services store file
|
||||
*/
|
||||
public static boolean isDesktopServicesStore(final Path path) {
|
||||
return Constants.MAC_OS_X && Files.isRegularFile(path) && ".DS_Store".equals(path.getFileName().toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the path to the given base and strips N elements off the path if strip is > 0.
|
||||
*/
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.elasticsearch.common.collect.Tuple;
|
|||
import org.elasticsearch.common.component.AbstractComponent;
|
||||
import org.elasticsearch.common.component.LifecycleComponent;
|
||||
import org.elasticsearch.common.inject.Module;
|
||||
import org.elasticsearch.common.io.FileSystemUtils;
|
||||
import org.elasticsearch.common.logging.Loggers;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Setting.Property;
|
||||
|
@ -326,6 +327,9 @@ public class PluginsService extends AbstractComponent {
|
|||
|
||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(pluginsDirectory)) {
|
||||
for (Path plugin : stream) {
|
||||
if (FileSystemUtils.isDesktopServicesStore(plugin)) {
|
||||
continue;
|
||||
}
|
||||
logger.trace("--- adding plugin [{}]", plugin.toAbsolutePath());
|
||||
final PluginInfo info;
|
||||
try {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.elasticsearch.common.io;
|
||||
|
||||
import org.apache.lucene.util.Constants;
|
||||
import org.apache.lucene.util.LuceneTestCase.SuppressFileSystems;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.junit.Before;
|
||||
|
@ -34,6 +35,8 @@ import java.nio.file.Path;
|
|||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link org.elasticsearch.common.io.FileSystemUtils}.
|
||||
*/
|
||||
|
@ -137,4 +140,16 @@ public class FileSystemUtilsTests extends ESTestCase {
|
|||
assertArrayEquals(expectedBytes, actualBytes);
|
||||
}
|
||||
}
|
||||
|
||||
public void testIsDesktopServicesStoreFile() throws IOException {
|
||||
final Path path = createTempDir();
|
||||
final Path desktopServicesStore = path.resolve(".DS_Store");
|
||||
Files.createFile(desktopServicesStore);
|
||||
assertThat(FileSystemUtils.isDesktopServicesStore(desktopServicesStore), equalTo(Constants.MAC_OS_X));
|
||||
|
||||
Files.delete(desktopServicesStore);
|
||||
Files.createDirectory(desktopServicesStore);
|
||||
assertFalse(FileSystemUtils.isDesktopServicesStore(desktopServicesStore));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.elasticsearch.plugins;
|
||||
|
||||
import org.apache.lucene.util.Constants;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
|
@ -27,6 +28,7 @@ import org.elasticsearch.index.IndexModule;
|
|||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileSystemException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
|
@ -36,6 +38,7 @@ import java.util.Locale;
|
|||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.hasToString;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
|
||||
@LuceneTestCase.SuppressFileSystems(value = "ExtrasFS")
|
||||
public class PluginsServiceTests extends ESTestCase {
|
||||
|
@ -124,6 +127,28 @@ public class PluginsServiceTests extends ESTestCase {
|
|||
assertThat(e, hasToString(containsString(expected)));
|
||||
}
|
||||
|
||||
public void testDesktopServicesStoreFiles() throws IOException {
|
||||
final Path home = createTempDir();
|
||||
final Settings settings =
|
||||
Settings.builder()
|
||||
.put(Environment.PATH_HOME_SETTING.getKey(), home)
|
||||
.build();
|
||||
final Path plugins = home.resolve("plugins");
|
||||
Files.createDirectories(plugins);
|
||||
final Path desktopServicesStore = plugins.resolve(".DS_Store");
|
||||
Files.createFile(desktopServicesStore);
|
||||
if (Constants.MAC_OS_X) {
|
||||
@SuppressWarnings("unchecked") final PluginsService pluginsService = newPluginsService(settings);
|
||||
assertNotNull(pluginsService);
|
||||
} else {
|
||||
final IllegalStateException e = expectThrows(IllegalStateException.class, () -> newPluginsService(settings));
|
||||
assertThat(e, hasToString(containsString("Could not load plugin descriptor for existing plugin [.DS_Store]")));
|
||||
assertNotNull(e.getCause());
|
||||
assertThat(e.getCause(), instanceOf(FileSystemException.class));
|
||||
assertThat(e.getCause(), hasToString(containsString("Not a directory")));
|
||||
}
|
||||
}
|
||||
|
||||
public void testStartupWithRemovingMarker() throws IOException {
|
||||
final Path home = createTempDir();
|
||||
final Settings settings =
|
||||
|
|
|
@ -31,6 +31,7 @@ import java.io.BufferedReader;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.FileSystemException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.attribute.PosixFileAttributeView;
|
||||
|
@ -40,8 +41,10 @@ import java.util.List;
|
|||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.hasToString;
|
||||
|
||||
/**
|
||||
* Create a simple "daemon controller", put it in the right place and check that it runs.
|
||||
|
@ -189,6 +192,29 @@ public class SpawnerNoBootstrapTests extends LuceneTestCase {
|
|||
equalTo("plugin [test_plugin] does not have permission to fork native controller"));
|
||||
}
|
||||
|
||||
public void testSpawnerHandlingOfDesktopServicesStoreFiles() throws IOException {
|
||||
final Path esHome = createTempDir().resolve("home");
|
||||
final Settings settings = Settings.builder().put(Environment.PATH_HOME_SETTING.getKey(), esHome.toString()).build();
|
||||
|
||||
final Environment environment = new Environment(settings);
|
||||
|
||||
Files.createDirectories(environment.pluginsFile());
|
||||
|
||||
final Path desktopServicesStore = environment.pluginsFile().resolve(".DS_Store");
|
||||
Files.createFile(desktopServicesStore);
|
||||
|
||||
final Spawner spawner = new Spawner();
|
||||
if (Constants.MAC_OS_X) {
|
||||
// if the spawner were not skipping the Desktop Services Store files on macOS this would explode
|
||||
spawner.spawnNativePluginControllers(environment);
|
||||
} else {
|
||||
// we do not ignore these files on non-macOS systems
|
||||
final FileSystemException e =
|
||||
expectThrows(FileSystemException.class, () -> spawner.spawnNativePluginControllers(environment));
|
||||
assertThat(e, hasToString(containsString("Not a directory")));
|
||||
}
|
||||
}
|
||||
|
||||
private void createControllerProgram(final Path outputFile) throws IOException {
|
||||
final Path outputDir = outputFile.getParent();
|
||||
Files.createDirectories(outputDir);
|
||||
|
|
Loading…
Reference in New Issue