Ignore empty folders and hidden files/folders in the library

Hide ".gameyfin" folder on DOS systems (UNIX already worked)
This commit is contained in:
Simon Grimme
2022-10-12 13:23:39 +02:00
parent af1fd42325
commit fdb1682273
7 changed files with 57 additions and 10 deletions
+2 -2
View File
@@ -7,7 +7,7 @@
<parent>
<artifactId>gameyfin</artifactId>
<groupId>de.grimsi</groupId>
<version>1.2.1</version>
<version>1.2.2-SNAPSHOT</version>
</parent>
<artifactId>gameyfin-backend</artifactId>
@@ -17,7 +17,7 @@
<properties>
<java.version>18</java.version>
<springdoc-openapi-ui.version>1.6.9</springdoc-openapi-ui.version>
<springdoc-openapi-ui.version>1.6.11</springdoc-openapi-ui.version>
<resilience4j.version>1.7.1</resilience4j.version>
<commons-io.version>2.11.0</commons-io.version>
<commons-compress.version>1.21</commons-compress.version>
@@ -2,16 +2,25 @@ package de.grimsi.gameyfin.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.event.EventListener;
import org.springframework.core.env.*;
import org.springframework.util.PropertyPlaceholderHelper;
import org.springframework.util.StringUtils;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Properties;
import java.util.stream.StreamSupport;
@@ -19,6 +28,8 @@ import java.util.stream.StreamSupport;
@Configuration
public class FilesystemConfig {
private static final String INTERNAL_FOLDER_NAME = ".gameyfin";
@Value("#{'${gameyfin.sources}'.split(',')[0]}")
private String firstLibraryPath;
@@ -31,16 +42,29 @@ public class FilesystemConfig {
@Autowired
Environment env;
/**
* This will make sure that the internal folder (".gameyfin") is marked as hidden on DOS/Windows-based systems.
* On UNIX-based systems files and folders starting with a dot are hidden
*/
@EventListener(ApplicationReadyEvent.class)
public void hideInternalFolderOnDOS() throws IOException {
Path internalFolder = Paths.get("%s/%s".formatted(firstLibraryPath, INTERNAL_FOLDER_NAME));
if(!Files.exists(internalFolder) || !Files.isDirectory(internalFolder)) return;
Files.setAttribute(internalFolder, "dos:hidden", Boolean.TRUE, LinkOption.NOFOLLOW_LINKS);
}
@Autowired
public void setConfigurableEnvironment(ConfigurableEnvironment env) {
Properties props = new Properties();
if(!StringUtils.hasText(dbPath)) {
props.setProperty("gameyfin.db", "%s/.gameyfin/db".formatted(firstLibraryPath));
props.setProperty("gameyfin.db", "%s/%s/db".formatted(firstLibraryPath, INTERNAL_FOLDER_NAME));
}
if(!StringUtils.hasText(cachePath)) {
props.setProperty("gameyfin.cache", "%s/.gameyfin/cache".formatted(firstLibraryPath));
props.setProperty("gameyfin.cache", "%s/%s/cache".formatted(firstLibraryPath, INTERNAL_FOLDER_NAME));
}
env.getPropertySources().addFirst(new PropertiesPropertySource("gameyfinFilesystemProperties", props));
@@ -16,8 +16,10 @@ import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
@@ -46,7 +48,28 @@ public class LibraryService {
folder -> {
try (Stream<Path> stream = Files.list(folder)) {
// return all sub-folders (non-recursive) and files that have an extension that indicates that they are a downloadable file
List<Path> gameFilesFromThisFolder = stream.filter(p -> Files.isDirectory(p) || hasGameArchiveExtension(p)).toList();
List<Path> gameFilesFromThisFolder = stream
.filter(p -> Files.isDirectory(p) || hasGameArchiveExtension(p))
// filter out all hidden files and folders
.filter(p -> {
try {
return !(Files.isHidden(p));
} catch (IOException e) {
throw new RuntimeException("Error while checking if '%s' is hidden.".formatted(p), e);
}
})
// filter out all empty directories
.filter(p -> {
if(!Files.isDirectory(p)) return true;
try(DirectoryStream<Path> s = Files.newDirectoryStream(p)) {
return s.iterator().hasNext();
} catch(IOException e) {
throw new RuntimeException("Error while checking if folder '%s' is empty.".formatted(p), e);
}
})
.toList();
gamefiles.addAll(gameFilesFromThisFolder);
} catch (IOException e) {
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "frontend",
"version": "1.2.1",
"version": "1.2.2-SNAPSHOT",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "frontend",
"version": "1.2.1",
"version": "1.2.2-SNAPSHOT",
"dependencies": {
"@angular/animations": "^14.0.0",
"@angular/cdk": "^14.1.0",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "frontend",
"version": "1.2.1",
"version": "1.2.2-SNAPSHOT",
"scripts": {
"ng": "ng",
"start": "ng serve",
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>gameyfin</artifactId>
<groupId>de.grimsi</groupId>
<version>1.2.1</version>
<version>1.2.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -5,7 +5,7 @@
<groupId>de.grimsi</groupId>
<artifactId>gameyfin</artifactId>
<version>1.2.1</version>
<version>1.2.2-SNAPSHOT</version>
<name>gameyfin</name>
<description>gameyfin</description>