Issue 570
Issue 455 (570) Adds a settings option to ignore symlinks during the media scan. (4550 Adds a regular expression pattern to exclude in addition to the option of excluding symlinks.
This commit is contained in:
+18
@@ -41,6 +41,8 @@ public class MusicFolderSettingsCommand {
|
|||||||
private boolean organizeByFolderStructure;
|
private boolean organizeByFolderStructure;
|
||||||
private List<MusicFolderInfo> musicFolders;
|
private List<MusicFolderInfo> musicFolders;
|
||||||
private MusicFolderInfo newMusicFolder;
|
private MusicFolderInfo newMusicFolder;
|
||||||
|
private String excludePatternString;
|
||||||
|
private boolean ignoreSymLinks;
|
||||||
|
|
||||||
public String getInterval() {
|
public String getInterval() {
|
||||||
return interval;
|
return interval;
|
||||||
@@ -98,6 +100,22 @@ public class MusicFolderSettingsCommand {
|
|||||||
this.organizeByFolderStructure = organizeByFolderStructure;
|
this.organizeByFolderStructure = organizeByFolderStructure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getExcludePatternString() {
|
||||||
|
return excludePatternString;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExcludePatternString(String excludePatternString) {
|
||||||
|
this.excludePatternString = excludePatternString;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getIgnoreSymLinks() {
|
||||||
|
return ignoreSymLinks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIgnoreSymLinks(boolean ignoreSymLinks) {
|
||||||
|
this.ignoreSymLinks = ignoreSymLinks;
|
||||||
|
}
|
||||||
|
|
||||||
public static class MusicFolderInfo {
|
public static class MusicFolderInfo {
|
||||||
|
|
||||||
private Integer id;
|
private Integer id;
|
||||||
|
|||||||
+4
@@ -85,6 +85,8 @@ public class MusicFolderSettingsController {
|
|||||||
command.setScanning(mediaScannerService.isScanning());
|
command.setScanning(mediaScannerService.isScanning());
|
||||||
command.setMusicFolders(wrap(settingsService.getAllMusicFolders(true, true)));
|
command.setMusicFolders(wrap(settingsService.getAllMusicFolders(true, true)));
|
||||||
command.setNewMusicFolder(new MusicFolderSettingsCommand.MusicFolderInfo());
|
command.setNewMusicFolder(new MusicFolderSettingsCommand.MusicFolderInfo());
|
||||||
|
command.setExcludePatternString(settingsService.getExcludePatternString());
|
||||||
|
command.setIgnoreSymLinks(settingsService.getIgnoreSymLinks());
|
||||||
|
|
||||||
model.addAttribute("command",command);
|
model.addAttribute("command",command);
|
||||||
}
|
}
|
||||||
@@ -123,6 +125,8 @@ public class MusicFolderSettingsController {
|
|||||||
settingsService.setIndexCreationHour(Integer.parseInt(command.getHour()));
|
settingsService.setIndexCreationHour(Integer.parseInt(command.getHour()));
|
||||||
settingsService.setFastCacheEnabled(command.isFastCache());
|
settingsService.setFastCacheEnabled(command.isFastCache());
|
||||||
settingsService.setOrganizeByFolderStructure(command.isOrganizeByFolderStructure());
|
settingsService.setOrganizeByFolderStructure(command.isOrganizeByFolderStructure());
|
||||||
|
settingsService.setExcludePatternString(command.getExcludePatternString());
|
||||||
|
settingsService.setIgnoreSymLinks(command.getIgnoreSymLinks());
|
||||||
settingsService.save();
|
settingsService.save();
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import org.springframework.stereotype.Service;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -451,9 +452,17 @@ public class MediaFileService {
|
|||||||
* @return Whether the child file is excluded.
|
* @return Whether the child file is excluded.
|
||||||
*/
|
*/
|
||||||
private boolean isExcluded(File file) {
|
private boolean isExcluded(File file) {
|
||||||
|
if (settingsService.getIgnoreSymLinks() && Files.isSymbolicLink(file.toPath())) {
|
||||||
|
LOG.info("excluding symbolic link " + file.toPath());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
String name = file.getName();
|
||||||
|
if (settingsService.getExcludePattern() != null && settingsService.getExcludePattern().matcher(name).find()) {
|
||||||
|
LOG.info("excluding file which matches exclude pattern " + settingsService.getExcludePatternString() + ": " + file.toPath());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Exclude all hidden files starting with a single "." or "@eaDir" (thumbnail dir created on Synology devices).
|
// Exclude all hidden files starting with a single "." or "@eaDir" (thumbnail dir created on Synology devices).
|
||||||
String name = file.getName();
|
|
||||||
return (name.startsWith(".") && !name.startsWith("..")) || name.startsWith("@eaDir") || name.equals("Thumbs.db");
|
return (name.startsWith(".") && !name.startsWith("..")) || name.startsWith("@eaDir") || name.equals("Thumbs.db");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import java.io.InputStream;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -113,6 +114,8 @@ public class SettingsService {
|
|||||||
private static final String KEY_SMTP_PASSWORD = "SmtpPassword";
|
private static final String KEY_SMTP_PASSWORD = "SmtpPassword";
|
||||||
private static final String KEY_SMTP_FROM = "SmtpFrom";
|
private static final String KEY_SMTP_FROM = "SmtpFrom";
|
||||||
private static final String KEY_EXPORT_PLAYLIST_FORMAT = "PlaylistExportFormat";
|
private static final String KEY_EXPORT_PLAYLIST_FORMAT = "PlaylistExportFormat";
|
||||||
|
private static final String KEY_IGNORE_SYMLINKS = "IgnoreSymLinks";
|
||||||
|
private static final String KEY_EXCLUDE_PATTERN_STRING = "ExcludePattern";
|
||||||
|
|
||||||
// Database Settings
|
// Database Settings
|
||||||
private static final String KEY_DATABASE_CONFIG_TYPE = "DatabaseConfigType";
|
private static final String KEY_DATABASE_CONFIG_TYPE = "DatabaseConfigType";
|
||||||
@@ -180,6 +183,8 @@ public class SettingsService {
|
|||||||
private static final String DEFAULT_SONOS_SERVICE_NAME = "Airsonic";
|
private static final String DEFAULT_SONOS_SERVICE_NAME = "Airsonic";
|
||||||
private static final int DEFAULT_SONOS_SERVICE_ID = 242;
|
private static final int DEFAULT_SONOS_SERVICE_ID = 242;
|
||||||
private static final String DEFAULT_EXPORT_PLAYLIST_FORMAT = "m3u";
|
private static final String DEFAULT_EXPORT_PLAYLIST_FORMAT = "m3u";
|
||||||
|
private static final boolean DEFAULT_IGNORE_SYMLINKS = false;
|
||||||
|
private static final String DEFAULT_EXCLUDE_PATTERN_STRING = null;
|
||||||
|
|
||||||
private static final String DEFAULT_SMTP_SERVER = null;
|
private static final String DEFAULT_SMTP_SERVER = null;
|
||||||
private static final String DEFAULT_SMTP_ENCRYPTION = "None";
|
private static final String DEFAULT_SMTP_ENCRYPTION = "None";
|
||||||
@@ -233,6 +238,8 @@ public class SettingsService {
|
|||||||
private List<MusicFolder> cachedMusicFolders;
|
private List<MusicFolder> cachedMusicFolders;
|
||||||
private final ConcurrentMap<String, List<MusicFolder>> cachedMusicFoldersPerUser = new ConcurrentHashMap<>();
|
private final ConcurrentMap<String, List<MusicFolder>> cachedMusicFoldersPerUser = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private Pattern excludePattern;
|
||||||
|
|
||||||
private void removeObsoleteProperties() {
|
private void removeObsoleteProperties() {
|
||||||
|
|
||||||
OBSOLETE_KEYS.forEach( oKey -> {
|
OBSOLETE_KEYS.forEach( oKey -> {
|
||||||
@@ -729,6 +736,38 @@ public class SettingsService {
|
|||||||
setBoolean(KEY_SORT_ALBUMS_BY_YEAR, b);
|
setBoolean(KEY_SORT_ALBUMS_BY_YEAR, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getIgnoreSymLinks() {
|
||||||
|
return getBoolean(KEY_IGNORE_SYMLINKS, DEFAULT_IGNORE_SYMLINKS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIgnoreSymLinks(boolean b) {
|
||||||
|
setBoolean(KEY_IGNORE_SYMLINKS, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExcludePatternString() {
|
||||||
|
return getString(KEY_EXCLUDE_PATTERN_STRING, DEFAULT_EXCLUDE_PATTERN_STRING);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExcludePatternString(String s) {
|
||||||
|
setString(KEY_EXCLUDE_PATTERN_STRING, s);
|
||||||
|
compileExcludePattern();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void compileExcludePattern() {
|
||||||
|
if (getExcludePatternString() != null && getExcludePatternString().trim().length() > 0) {
|
||||||
|
excludePattern = Pattern.compile(getExcludePatternString());
|
||||||
|
} else {
|
||||||
|
excludePattern = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pattern getExcludePattern() {
|
||||||
|
if (excludePattern == null && getExcludePatternString() != null) {
|
||||||
|
compileExcludePattern();
|
||||||
|
}
|
||||||
|
return excludePattern;
|
||||||
|
}
|
||||||
|
|
||||||
public MediaLibraryStatistics getMediaLibraryStatistics() {
|
public MediaLibraryStatistics getMediaLibraryStatistics() {
|
||||||
return MediaLibraryStatistics.parse(getString(KEY_MEDIA_LIBRARY_STATISTICS, DEFAULT_MEDIA_LIBRARY_STATISTICS));
|
return MediaLibraryStatistics.parse(getString(KEY_MEDIA_LIBRARY_STATISTICS, DEFAULT_MEDIA_LIBRARY_STATISTICS));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -398,6 +398,8 @@ musicfoldersettings.nowscanning=The media folders are now being scanned. This op
|
|||||||
musicfoldersettings.scannow=Scan media folders now
|
musicfoldersettings.scannow=Scan media folders now
|
||||||
musicfoldersettings.access=Manage user access
|
musicfoldersettings.access=Manage user access
|
||||||
musicfoldersettings.access.description=Configure which folders each user is allowed to access.
|
musicfoldersettings.access.description=Configure which folders each user is allowed to access.
|
||||||
|
musicfoldersettings.ignoresymlinks=Ignore Symbolic Links
|
||||||
|
musicfoldersettings.excludepattern=Exclude pattern
|
||||||
musicfoldersettings.fastcache=Fast access mode
|
musicfoldersettings.fastcache=Fast access mode
|
||||||
musicfoldersettings.fastcache.description=Use this option to minimize disk access, for instance if your media files are located on a network disk. Note: Changed or added files will only be visible after your media folders are scanned.
|
musicfoldersettings.fastcache.description=Use this option to minimize disk access, for instance if your media files are located on a network disk. Note: Changed or added files will only be visible after your media folders are scanned.
|
||||||
musicfoldersettings.expunge=Clean-up database
|
musicfoldersettings.expunge=Clean-up database
|
||||||
@@ -660,6 +662,8 @@ helppopup.jndiname.title=Data Source JNDI Lookup Name
|
|||||||
helppopup.jndiname.text=A JNDI name to lookup a Data Source of type javax.sql.DataSource. This is something that iscreated in your application container (i.e. tomcat).
|
helppopup.jndiname.text=A JNDI name to lookup a Data Source of type javax.sql.DataSource. This is something that iscreated in your application container (i.e. tomcat).
|
||||||
helppopup.embeddriver.title=JDBC Driver Class
|
helppopup.embeddriver.title=JDBC Driver Class
|
||||||
helppopup.embeddriver.text=JDBC Driver dependent class name that implments java.sql.Driver. I.E. for postgres one would use org.postgresql.Driver. This class must be present on the classpath.
|
helppopup.embeddriver.text=JDBC Driver dependent class name that implments java.sql.Driver. I.E. for postgres one would use org.postgresql.Driver. This class must be present on the classpath.
|
||||||
|
helppopup.excludepattern.title=Exclude Pattern
|
||||||
|
helppopup.excludepattern.text=<p>Airsonic will not import any files which match this regular expression pattern.</p>
|
||||||
helppopup.playlistfolder.title=Import playlist from
|
helppopup.playlistfolder.title=Import playlist from
|
||||||
helppopup.playlistfolder.text=<p>Airsonic will regularly import playlists stored in this folder.</p>
|
helppopup.playlistfolder.text=<p>Airsonic will regularly import playlists stored in this folder.</p>
|
||||||
helppopup.musicmask.title=Music files
|
helppopup.musicmask.title=Music files
|
||||||
|
|||||||
@@ -69,6 +69,17 @@
|
|||||||
<fmt:message key="musicfoldersettings.access.description"/>
|
<fmt:message key="musicfoldersettings.access.description"/>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<fmt:message key="musicfoldersettings.excludepattern"/>
|
||||||
|
<form:input path="excludePatternString" size="70"/>
|
||||||
|
<c:import url="helpToolTip.jsp"><c:param name="topic" value="excludepattern"/></c:import>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<form:checkbox path="ignoreSymLinks" id="ignoreSymLinks"/>
|
||||||
|
<form:label path="ignoreSymLinks"><fmt:message key="musicfoldersettings.ignoresymlinks"/></form:label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div style="padding-top: 0.5em;padding-bottom: 0.3em">
|
<div style="padding-top: 0.5em;padding-bottom: 0.3em">
|
||||||
<span style="white-space: nowrap">
|
<span style="white-space: nowrap">
|
||||||
<fmt:message key="musicfoldersettings.scan"/>
|
<fmt:message key="musicfoldersettings.scan"/>
|
||||||
|
|||||||
Reference in New Issue
Block a user