2019-03-23 22:40:56 +01:00
|
|
|
/*
|
2020-04-14 01:08:07 +02:00
|
|
|
* Copyright (C) 2020 Philipp Haefelfinger (http://www.haefelfinger.ch/). All Rights Reserved.
|
2019-03-23 22:40:56 +01:00
|
|
|
* This application is licensed under GPLv2. See the LICENSE file in the root directory of the project.
|
|
|
|
*/
|
|
|
|
|
2019-02-23 00:58:32 +01:00
|
|
|
package localFileStructure
|
|
|
|
|
|
|
|
import (
|
2019-02-25 23:58:44 +01:00
|
|
|
"fmt"
|
2019-02-25 23:36:18 +01:00
|
|
|
"github.com/sirupsen/logrus"
|
2019-02-23 00:58:32 +01:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
2019-02-25 23:11:09 +01:00
|
|
|
"strings"
|
2019-03-12 23:47:19 +01:00
|
|
|
"time"
|
2019-02-23 00:58:32 +01:00
|
|
|
)
|
|
|
|
|
2019-03-12 23:47:19 +01:00
|
|
|
type FilesystemNode struct {
|
|
|
|
Key string
|
|
|
|
Path string
|
|
|
|
Name string
|
|
|
|
IsDir bool
|
|
|
|
ModTime time.Time
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *FilesystemNode) String() string {
|
|
|
|
return fmt.Sprintf("FilesystemNode: %s", n.Path)
|
|
|
|
}
|
|
|
|
|
2020-04-14 23:13:46 +02:00
|
|
|
func ScanLocalFileStructure(path string, extensions []string, ignoreDirs []string, dirSuffixToSkip int) (map[string]*FilesystemNode, error) {
|
2019-02-25 23:58:44 +01:00
|
|
|
fullPathRoot, err := filepath.Abs(path)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2019-02-25 23:11:09 +01:00
|
|
|
|
2020-04-14 23:13:46 +02:00
|
|
|
ignoreDirsMap := make(map[string]struct{}, len(ignoreDirs))
|
|
|
|
for _, ignoredFolder := range ignoreDirs {
|
|
|
|
ignoreDirsMap[strings.ToLower(ignoredFolder)] = struct{}{}
|
2020-04-14 01:08:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
extensionsMap := make(map[string]struct{}, len(extensions))
|
|
|
|
for _, extension := range extensions {
|
|
|
|
extensionsMap["."+strings.ToLower(extension)] = struct{}{}
|
|
|
|
}
|
|
|
|
|
2020-04-14 23:13:46 +02:00
|
|
|
if len(extensionsMap) == 0 {
|
|
|
|
logrus.Debug("No extensions specified, adding jpg and png")
|
|
|
|
extensionsMap[".jpg"] = struct{}{}
|
|
|
|
extensionsMap[".png"] = struct{}{}
|
|
|
|
}
|
|
|
|
|
2019-02-25 23:58:44 +01:00
|
|
|
logrus.Infof("Scanning %s for images...", fullPathRoot)
|
2019-02-25 23:36:18 +01:00
|
|
|
|
2019-02-25 23:58:44 +01:00
|
|
|
fileMap := make(map[string]*FilesystemNode)
|
2019-02-26 22:50:33 +01:00
|
|
|
fullPathReplace := fmt.Sprintf("%s%c", fullPathRoot, os.PathSeparator)
|
2019-02-25 23:36:18 +01:00
|
|
|
numberOfDirectories := 0
|
|
|
|
numberOfImages := 0
|
2019-02-23 00:58:32 +01:00
|
|
|
|
2019-02-27 22:11:47 +01:00
|
|
|
err = filepath.Walk(fullPathRoot, func(path string, info os.FileInfo, err error) error {
|
|
|
|
if fullPathRoot == path {
|
2019-02-23 00:58:32 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-04-07 00:12:01 +02:00
|
|
|
if strings.HasPrefix(info.Name(), ".") {
|
|
|
|
logrus.Tracef("Skipping hidden file or directory %s", path)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-04-14 23:13:46 +02:00
|
|
|
_, dirIgnored := ignoreDirsMap[strings.ToLower(info.Name())]
|
|
|
|
if dirIgnored && info.IsDir() {
|
2020-04-14 01:08:07 +02:00
|
|
|
logrus.Tracef("Skipping ignored directory %s", path)
|
|
|
|
return filepath.SkipDir
|
|
|
|
}
|
|
|
|
|
2019-02-28 22:30:58 +01:00
|
|
|
extension := strings.ToLower(filepath.Ext(path))
|
2020-04-14 01:08:07 +02:00
|
|
|
_, extensionSupported := extensionsMap[extension]
|
|
|
|
if !extensionSupported && !info.IsDir() {
|
2019-02-28 22:30:58 +01:00
|
|
|
return nil
|
|
|
|
}
|
2019-02-23 00:58:32 +01:00
|
|
|
|
2020-04-14 23:13:46 +02:00
|
|
|
key := buildKey(path, info, fullPathReplace, dirSuffixToSkip)
|
2019-02-25 23:11:09 +01:00
|
|
|
|
2019-02-27 22:11:47 +01:00
|
|
|
fileMap[path] = &FilesystemNode{
|
|
|
|
Key: key,
|
|
|
|
Path: path,
|
2020-04-16 00:18:56 +02:00
|
|
|
Name: filepath.Base(key),
|
2019-02-27 22:11:47 +01:00
|
|
|
IsDir: info.IsDir(),
|
|
|
|
ModTime: info.ModTime(),
|
2019-02-23 00:58:32 +01:00
|
|
|
}
|
2019-02-25 23:36:18 +01:00
|
|
|
|
|
|
|
if info.IsDir() {
|
|
|
|
numberOfDirectories += 1
|
|
|
|
} else {
|
|
|
|
numberOfImages += 1
|
|
|
|
}
|
|
|
|
|
2019-02-23 22:02:12 +01:00
|
|
|
return nil
|
2019-02-23 00:58:32 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
if err != nil {
|
2019-02-24 21:38:28 +01:00
|
|
|
return nil, err
|
2019-02-23 00:58:32 +01:00
|
|
|
}
|
|
|
|
|
2019-02-25 23:36:18 +01:00
|
|
|
logrus.Infof("Found %d directories and %d images on the local filesystem", numberOfDirectories, numberOfImages)
|
|
|
|
|
2019-02-24 21:38:28 +01:00
|
|
|
return fileMap, nil
|
2019-02-23 00:58:32 +01:00
|
|
|
}
|
2020-04-14 23:13:46 +02:00
|
|
|
|
|
|
|
func buildKey(path string, info os.FileInfo, fullPathReplace string, dirSuffixToSkip int) string {
|
|
|
|
if info.IsDir() {
|
|
|
|
return trimPathForKey(path, fullPathReplace, dirSuffixToSkip)
|
|
|
|
}
|
|
|
|
fileName := filepath.Base(path)
|
|
|
|
directoryName := filepath.Dir(path)
|
|
|
|
cleanDir := trimPathForKey(directoryName, fullPathReplace, dirSuffixToSkip)
|
|
|
|
return filepath.Join(cleanDir, fileName)
|
|
|
|
}
|
|
|
|
|
|
|
|
func trimPathForKey(path string, fullPathReplace string, dirSuffixToSkip int) string {
|
|
|
|
trimmedPath := strings.Replace(path, fullPathReplace, "", 1)
|
|
|
|
for i := 0; i < dirSuffixToSkip; i++ {
|
|
|
|
trimmedPath = filepath.Clean(strings.TrimSuffix(trimmedPath, filepath.Base(trimmedPath)))
|
|
|
|
}
|
|
|
|
if trimmedPath == "." {
|
|
|
|
return "root"
|
|
|
|
}
|
|
|
|
return trimmedPath
|
|
|
|
}
|