2020-01-02 00:03:07 +01:00
|
|
|
package config
|
|
|
|
|
|
|
|
import (
|
2020-01-21 13:59:41 +01:00
|
|
|
"fmt"
|
2020-01-02 00:03:07 +01:00
|
|
|
"os"
|
|
|
|
"os/exec"
|
|
|
|
"path/filepath"
|
|
|
|
|
2020-01-12 14:00:56 +01:00
|
|
|
"github.com/photoprism/photoprism/pkg/fs"
|
2020-05-03 18:00:50 +02:00
|
|
|
"github.com/photoprism/photoprism/pkg/txt"
|
2020-01-02 00:03:07 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
func findExecutable(configBin, defaultBin string) (result string) {
|
|
|
|
if configBin == "" {
|
|
|
|
result = defaultBin
|
|
|
|
} else {
|
|
|
|
result = configBin
|
|
|
|
}
|
|
|
|
|
|
|
|
if path, err := exec.LookPath(result); err == nil {
|
|
|
|
result = path
|
|
|
|
}
|
|
|
|
|
2020-01-12 14:00:56 +01:00
|
|
|
if !fs.FileExists(result) {
|
2020-01-02 00:03:07 +01:00
|
|
|
result = ""
|
|
|
|
}
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2020-01-21 13:59:41 +01:00
|
|
|
// CreateDirectories creates directories for storing photos, metadata and cache files.
|
2020-01-02 00:03:07 +01:00
|
|
|
func (c *Config) CreateDirectories() error {
|
2020-01-21 13:59:41 +01:00
|
|
|
createError := func(path string, err error) (result error) {
|
|
|
|
if fs.FileExists(path) {
|
2020-05-07 12:33:09 +02:00
|
|
|
result = fmt.Errorf("%s is a file, not a folder: please check your configuration", txt.Quote(path))
|
2020-01-21 13:59:41 +01:00
|
|
|
} else {
|
2020-05-03 18:00:50 +02:00
|
|
|
result = fmt.Errorf("can't create %s: please check configuration and permissions", txt.Quote(path))
|
2020-01-21 13:59:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
log.Debug(err)
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2020-01-02 00:03:07 +01:00
|
|
|
if err := os.MkdirAll(c.OriginalsPath(), os.ModePerm); err != nil {
|
2020-01-21 13:59:41 +01:00
|
|
|
return createError(c.OriginalsPath(), err)
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if err := os.MkdirAll(c.ImportPath(), os.ModePerm); err != nil {
|
2020-01-21 13:59:41 +01:00
|
|
|
return createError(c.ImportPath(), err)
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
2020-04-06 16:34:29 +02:00
|
|
|
if err := os.MkdirAll(c.TempPath(), os.ModePerm); err != nil {
|
|
|
|
return createError(c.TempPath(), err)
|
|
|
|
}
|
|
|
|
|
2020-05-05 17:04:13 +02:00
|
|
|
if err := os.MkdirAll(c.ThumbPath(), os.ModePerm); err != nil {
|
|
|
|
return createError(c.ThumbPath(), err)
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if err := os.MkdirAll(c.ResourcesPath(), os.ModePerm); err != nil {
|
2020-01-21 13:59:41 +01:00
|
|
|
return createError(c.ResourcesPath(), err)
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
2020-04-28 22:49:02 +02:00
|
|
|
if err := os.MkdirAll(c.TidbServerPath(), os.ModePerm); err != nil {
|
|
|
|
return createError(c.TidbServerPath(), err)
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if err := os.MkdirAll(c.TensorFlowModelPath(), os.ModePerm); err != nil {
|
2020-01-21 13:59:41 +01:00
|
|
|
return createError(c.TensorFlowModelPath(), err)
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if err := os.MkdirAll(c.HttpStaticBuildPath(), os.ModePerm); err != nil {
|
2020-01-21 13:59:41 +01:00
|
|
|
return createError(c.HttpStaticBuildPath(), err)
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if err := os.MkdirAll(filepath.Dir(c.PIDFilename()), os.ModePerm); err != nil {
|
2020-01-21 13:59:41 +01:00
|
|
|
return createError(filepath.Dir(c.PIDFilename()), err)
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if err := os.MkdirAll(filepath.Dir(c.LogFilename()), os.ModePerm); err != nil {
|
2020-01-21 13:59:41 +01:00
|
|
|
return createError(filepath.Dir(c.LogFilename()), err)
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ConfigFile returns the config file name.
|
|
|
|
func (c *Config) ConfigFile() string {
|
2020-04-13 18:08:21 +02:00
|
|
|
return c.params.ConfigFile
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// SettingsFile returns the user settings file name.
|
|
|
|
func (c *Config) SettingsFile() string {
|
2020-05-05 18:26:44 +02:00
|
|
|
return filepath.Join(c.ConfigPath(), "settings.yml")
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// ConfigPath returns the config path.
|
|
|
|
func (c *Config) ConfigPath() string {
|
2020-04-13 18:08:21 +02:00
|
|
|
if c.params.ConfigPath == "" {
|
2020-05-05 18:26:44 +02:00
|
|
|
return filepath.Join(c.AssetsPath(), "config")
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
2020-04-13 18:08:21 +02:00
|
|
|
return fs.Abs(c.params.ConfigPath)
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// PIDFilename returns the filename for storing the server process id (pid).
|
|
|
|
func (c *Config) PIDFilename() string {
|
2020-04-13 18:08:21 +02:00
|
|
|
if c.params.PIDFilename == "" {
|
2020-05-05 18:26:44 +02:00
|
|
|
return filepath.Join(c.AssetsPath(), "photoprism.pid")
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
2020-04-13 18:08:21 +02:00
|
|
|
return fs.Abs(c.params.PIDFilename)
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// LogFilename returns the filename for storing server logs.
|
|
|
|
func (c *Config) LogFilename() string {
|
2020-04-13 18:08:21 +02:00
|
|
|
if c.params.LogFilename == "" {
|
2020-05-05 18:26:44 +02:00
|
|
|
return filepath.Join(c.AssetsPath(), "photoprism.log")
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
2020-04-13 18:08:21 +02:00
|
|
|
return fs.Abs(c.params.LogFilename)
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// OriginalsPath returns the originals.
|
|
|
|
func (c *Config) OriginalsPath() string {
|
2020-04-13 18:08:21 +02:00
|
|
|
return fs.Abs(c.params.OriginalsPath)
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// ImportPath returns the import directory.
|
|
|
|
func (c *Config) ImportPath() string {
|
2020-04-13 18:08:21 +02:00
|
|
|
return fs.Abs(c.params.ImportPath)
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
2020-05-11 18:29:17 +02:00
|
|
|
// SipsBin returns the sips executable file name.
|
2020-01-02 00:03:07 +01:00
|
|
|
func (c *Config) SipsBin() string {
|
2020-04-13 18:08:21 +02:00
|
|
|
return findExecutable(c.params.SipsBin, "sips")
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
2020-05-11 18:29:17 +02:00
|
|
|
// DarktableBin returns the darktable-cli executable file name.
|
2020-01-02 00:03:07 +01:00
|
|
|
func (c *Config) DarktableBin() string {
|
2020-04-13 18:08:21 +02:00
|
|
|
return findExecutable(c.params.DarktableBin, "darktable-cli")
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
2020-05-11 18:29:17 +02:00
|
|
|
// ExifToolBin returns the exiftool executable file name.
|
|
|
|
func (c *Config) ExifToolBin() string {
|
|
|
|
return findExecutable(c.params.ExifToolBin, "exiftool")
|
|
|
|
}
|
|
|
|
|
2020-05-13 20:53:15 +02:00
|
|
|
// SidecarJson returns true if metadata should be synced with json sidecar files as used by exiftool.
|
|
|
|
func (c *Config) SidecarJson() bool {
|
2020-05-11 18:29:17 +02:00
|
|
|
if c.ReadOnly() || c.ExifToolBin() == "" {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2020-05-13 20:53:15 +02:00
|
|
|
return c.params.SidecarJson
|
2020-05-11 18:29:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// HeifConvertBin returns the heif-convert executable file name.
|
2020-01-02 00:03:07 +01:00
|
|
|
func (c *Config) HeifConvertBin() string {
|
2020-04-13 18:08:21 +02:00
|
|
|
return findExecutable(c.params.HeifConvertBin, "heif-convert")
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
2020-05-11 18:29:17 +02:00
|
|
|
// FFmpegBin returns the ffmpeg executable file name.
|
|
|
|
func (c *Config) FFmpegBin() string {
|
|
|
|
return findExecutable(c.params.FFmpegBin, "ffmpeg")
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
2020-04-06 16:34:29 +02:00
|
|
|
// TempPath returns a temporary directory name for uploads and downloads.
|
|
|
|
func (c *Config) TempPath() string {
|
2020-04-13 18:08:21 +02:00
|
|
|
if c.params.TempPath == "" {
|
2020-05-05 18:26:44 +02:00
|
|
|
return filepath.Join(os.TempDir(), "photoprism")
|
2020-04-06 16:34:29 +02:00
|
|
|
}
|
|
|
|
|
2020-04-13 18:08:21 +02:00
|
|
|
return fs.Abs(c.params.TempPath)
|
2020-04-06 16:34:29 +02:00
|
|
|
}
|
|
|
|
|
2020-01-02 00:03:07 +01:00
|
|
|
// CachePath returns the path to the cache.
|
|
|
|
func (c *Config) CachePath() string {
|
2020-04-13 18:08:21 +02:00
|
|
|
return fs.Abs(c.params.CachePath)
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// AssetsPath returns the path to the assets.
|
|
|
|
func (c *Config) AssetsPath() string {
|
2020-04-13 18:08:21 +02:00
|
|
|
return fs.Abs(c.params.AssetsPath)
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// ResourcesPath returns the path to the app resources like static files.
|
|
|
|
func (c *Config) ResourcesPath() string {
|
2020-04-13 18:08:21 +02:00
|
|
|
if c.params.ResourcesPath == "" {
|
2020-05-05 18:26:44 +02:00
|
|
|
return filepath.Join(c.AssetsPath(), "resources")
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
2020-04-13 18:08:21 +02:00
|
|
|
return fs.Abs(c.params.ResourcesPath)
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// ExamplesPath returns the example files path.
|
|
|
|
func (c *Config) ExamplesPath() string {
|
2020-05-05 18:26:44 +02:00
|
|
|
return filepath.Join(c.ResourcesPath(), "examples")
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// TensorFlowModelPath returns the tensorflow model path.
|
|
|
|
func (c *Config) TensorFlowModelPath() string {
|
2020-05-05 18:26:44 +02:00
|
|
|
return filepath.Join(c.ResourcesPath(), "nasnet")
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// NSFWModelPath returns the NSFW tensorflow model path.
|
|
|
|
func (c *Config) NSFWModelPath() string {
|
2020-05-05 18:26:44 +02:00
|
|
|
return filepath.Join(c.ResourcesPath(), "nsfw")
|
2020-01-02 00:03:07 +01:00
|
|
|
}
|