Add PHOTOPRISM_SIDECAR_HIDDEN and PHOTOPRISM_JPEG_HIDDEN flags #311
Signed-off-by: Michael Mayer <michael@liquidbytes.net>
This commit is contained in:
parent
7777fa95a5
commit
e61dda495a
31 changed files with 125 additions and 53 deletions
|
@ -26,3 +26,8 @@ database-dsn: root:photoprism@tcp(localhost:2343)/photoprism?parseTime=true
|
|||
pid-filename: ~/.local/share/photoprism/photoprism.pid
|
||||
log-filename: ~/.local/share/photoprism/photoprism.log
|
||||
detach-server: false
|
||||
sidecar-json: false
|
||||
sidecar-yaml: false
|
||||
sidecar-hidden: true
|
||||
jpeg-quality: 90
|
||||
jpeg-hidden: true
|
||||
|
|
|
@ -29,6 +29,15 @@ services:
|
|||
PHOTOPRISM_SUBTITLE: "Browse your life"
|
||||
PHOTOPRISM_DESCRIPTION: "Personal Photo Management tested by Travis CI."
|
||||
PHOTOPRISM_AUTHOR: "PhotoPrism.org"
|
||||
PHOTOPRISM_THUMB_FILTER: "lanczos" # Resample filter, best to worst: blackman, lanczos, cubic, linear
|
||||
PHOTOPRISM_THUMB_UNCACHED: "true" # On-demand rendering of default thumbnails (high memory and cpu usage)
|
||||
PHOTOPRISM_THUMB_SIZE: 2048 # Default thumbnail size limit (default 2048, min 720, max 3840)
|
||||
PHOTOPRISM_THUMB_LIMIT: 3840 # On-demand thumbnail size limit (default 2048, min 720, max 3840)
|
||||
PHOTOPRISM_JPEG_QUALITY: 90 # Use 95 for high-quality thumbnails (requires more storage)
|
||||
PHOTOPRISM_JPEG_HIDDEN: "true" # Create JPEG files in .photoprism (when converting other file types)
|
||||
PHOTOPRISM_SIDECAR_JSON: "true" # Read metadata from JSON sidecar files created by exiftool
|
||||
PHOTOPRISM_SIDECAR_YAML: "true" # Backup photo metadata to YAML sidecar files
|
||||
PHOTOPRISM_SIDECAR_HIDDEN: "true" # Create JSON and YAML sidecar files in .photoprism (if enabled)
|
||||
CODECOV_TOKEN:
|
||||
CODECOV_ENV:
|
||||
CODECOV_URL:
|
||||
|
|
|
@ -13,6 +13,7 @@ services:
|
|||
- ".:/go/src/github.com/photoprism/photoprism"
|
||||
shm_size: "2gb"
|
||||
environment:
|
||||
TF_CPP_MIN_LOG_LEVEL: 0 # Show TensorFlow log messages for development
|
||||
PHOTOPRISM_URL: "http://localhost:2342/"
|
||||
PHOTOPRISM_DEBUG: "true"
|
||||
PHOTOPRISM_READONLY: "false"
|
||||
|
@ -39,7 +40,15 @@ services:
|
|||
PHOTOPRISM_TITLE: "PhotoPrism"
|
||||
PHOTOPRISM_SUBTITLE: "Browse your life"
|
||||
PHOTOPRISM_AUTHOR: "PhotoPrism.org"
|
||||
TF_CPP_MIN_LOG_LEVEL: 0
|
||||
PHOTOPRISM_THUMB_FILTER: "lanczos" # Resample filter, best to worst: blackman, lanczos, cubic, linear
|
||||
PHOTOPRISM_THUMB_UNCACHED: "true" # On-demand rendering of default thumbnails (high memory and cpu usage)
|
||||
PHOTOPRISM_THUMB_SIZE: 2048 # Default thumbnail size limit (default 2048, min 720, max 3840)
|
||||
PHOTOPRISM_THUMB_LIMIT: 3840 # On-demand thumbnail size limit (default 2048, min 720, max 3840)
|
||||
PHOTOPRISM_JPEG_QUALITY: 90 # Use 95 for high-quality thumbnails (requires more storage)
|
||||
PHOTOPRISM_JPEG_HIDDEN: "true" # Create JPEG files in .photoprism (when converting other file types)
|
||||
PHOTOPRISM_SIDECAR_JSON: "true" # Read metadata from JSON sidecar files created by exiftool
|
||||
PHOTOPRISM_SIDECAR_YAML: "true" # Backup photo metadata to YAML sidecar files
|
||||
PHOTOPRISM_SIDECAR_HIDDEN: "true" # Create JSON and YAML sidecar files in .photoprism (if enabled)
|
||||
|
||||
photoprism-db:
|
||||
image: mariadb:10.5
|
||||
|
|
|
@ -16,14 +16,16 @@ ENV PHOTOPRISM_PUBLIC true
|
|||
ENV PHOTOPRISM_EXPERIMENTAL true
|
||||
ENV PHOTOPRISM_UPLOAD_NSFW false
|
||||
ENV PHOTOPRISM_DETECT_NSFW true
|
||||
ENV PHOTOPRISM_JPEG_QUALITY 95
|
||||
ENV PHOTOPRISM_SIDECAR_JSON true
|
||||
ENV PHOTOPRISM_SIDECAR_YAML false
|
||||
ENV PHOTOPRISM_SIDECAR_HIDDEN true
|
||||
ENV PHOTOPRISM_GEOCODING_API places
|
||||
ENV PHOTOPRISM_THUMB_FILTER lanczos
|
||||
ENV PHOTOPRISM_THUMB_UNCACHED true
|
||||
ENV PHOTOPRISM_THUMB_SIZE 3840
|
||||
ENV PHOTOPRISM_THUMB_LIMIT 3840
|
||||
ENV PHOTOPRISM_GEOCODING_API places
|
||||
ENV PHOTOPRISM_SIDECAR_JSON true
|
||||
ENV PHOTOPRISM_SIDECAR_YAML false
|
||||
ENV PHOTOPRISM_JPEG_QUALITY 95
|
||||
ENV PHOTOPRISM_JPEG_HIDDEN false
|
||||
|
||||
# Import example photos
|
||||
RUN photoprism import
|
||||
|
|
|
@ -43,14 +43,16 @@ services:
|
|||
PHOTOPRISM_DATABASE_DSN: "root:photoprism@tcp(localhost:2343)/photoprism?parseTime=true"
|
||||
# PHOTOPRISM_DATABASE_DRIVER: "mysql" # Using MariaDB or MySQL instead of the internal TiDB is optional
|
||||
# PHOTOPRISM_DATABASE_DSN: "photoprism:photoprism@tcp(photoprism-db:3306)/photoprism?parseTime=true"
|
||||
PHOTOPRISM_JPEG_QUALITY: 90 # Use 95 for high-quality thumbnails (requires more storage)
|
||||
# PHOTOPRISM_SIDECAR_JSON: "true" # Read metadata from JSON sidecar files created by exiftool
|
||||
# PHOTOPRISM_SIDECAR_YAML: "true" # Backup photo metadata to YAML sidecar files
|
||||
PHOTOPRISM_SIDECAR_HIDDEN: "true" # Create JSON and YAML sidecar files in .photoprism (if enabled)
|
||||
PHOTOPRISM_THUMB_FILTER: "lanczos" # Resample filter, best to worst: blackman, lanczos, cubic, linear
|
||||
PHOTOPRISM_THUMB_UNCACHED: "false" # On-demand rendering of default thumbnails (high memory and cpu usage)
|
||||
PHOTOPRISM_THUMB_SIZE: 2048 # Default thumbnail size limit (default 2048, min 720, max 3840)
|
||||
# PHOTOPRISM_THUMB_SIZE: 3840 # For retina screens (requires more storage)
|
||||
PHOTOPRISM_THUMB_LIMIT: 3840 # On-demand thumbnail size limit (default 2048, min 720, max 3840)
|
||||
# PHOTOPRISM_SIDECAR_JSON: "true" # read metadata from json sidecar files created by exiftool
|
||||
# PHOTOPRISM_SIDECAR_YAML: "true" # backup photo metadata to yaml sidecar files
|
||||
PHOTOPRISM_JPEG_QUALITY: 90 # Use 95 for high-quality thumbnails (requires more storage)
|
||||
PHOTOPRISM_JPEG_HIDDEN: "true" # Create JPEG files in .photoprism (when converting other file types)
|
||||
volumes:
|
||||
- "~/Pictures/Originals:/photoprism/originals" # [local path]:[container path]
|
||||
- "~/Pictures/Import:/photoprism/import" # [local path]:[container path] (optional)
|
||||
|
|
|
@ -42,14 +42,16 @@ services:
|
|||
PHOTOPRISM_DATABASE_DSN: "root:photoprism@tcp(localhost:2343)/photoprism?parseTime=true"
|
||||
# PHOTOPRISM_DATABASE_DRIVER: "mysql" # Using MariaDB or MySQL instead of the internal TiDB is optional
|
||||
# PHOTOPRISM_DATABASE_DSN: "photoprism:photoprism@tcp(photoprism-db:3306)/photoprism?parseTime=true"
|
||||
PHOTOPRISM_JPEG_QUALITY: 90 # Use 95 for high-quality thumbnails (requires more storage)
|
||||
# PHOTOPRISM_SIDECAR_JSON: "true" # Read metadata from JSON sidecar files created by exiftool
|
||||
# PHOTOPRISM_SIDECAR_YAML: "true" # Backup photo metadata to YAML sidecar files
|
||||
PHOTOPRISM_SIDECAR_HIDDEN: "true" # Create JSON and YAML sidecar files in .photoprism (if enabled)
|
||||
PHOTOPRISM_THUMB_FILTER: "lanczos" # Resample filter, best to worst: blackman, lanczos, cubic, linear
|
||||
PHOTOPRISM_THUMB_UNCACHED: "false" # On-demand rendering of default thumbnails (high memory and cpu usage)
|
||||
PHOTOPRISM_THUMB_SIZE: 2048 # Default thumbnail size limit (default 2048, min 720, max 3840)
|
||||
# PHOTOPRISM_THUMB_SIZE: 3840 # For retina screens (requires more storage)
|
||||
PHOTOPRISM_THUMB_LIMIT: 3840 # On-demand thumbnail size limit (default 2048, min 720, max 3840)
|
||||
# PHOTOPRISM_SIDECAR_JSON: "true" # read metadata from json sidecar files created by exiftool
|
||||
# PHOTOPRISM_SIDECAR_YAML: "true" # backup photo metadata to yaml sidecar files
|
||||
PHOTOPRISM_JPEG_QUALITY: 90 # Use 95 for high-quality thumbnails (requires more storage)
|
||||
PHOTOPRISM_JPEG_HIDDEN: "true" # Create JPEG files in .photoprism (when converting other file types)
|
||||
volumes:
|
||||
- "~/Pictures/Originals:/photoprism/originals" # [local path]:[container path]
|
||||
- "~/Pictures/Import:/photoprism/import" # [local path]:[container path] (optional)
|
||||
|
|
|
@ -4,14 +4,12 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/photoprism/photoprism/internal/config"
|
||||
"github.com/photoprism/photoprism/internal/entity"
|
||||
"github.com/photoprism/photoprism/internal/event"
|
||||
"github.com/photoprism/photoprism/internal/form"
|
||||
"github.com/photoprism/photoprism/internal/photoprism"
|
||||
"github.com/photoprism/photoprism/internal/query"
|
||||
"github.com/photoprism/photoprism/pkg/fs"
|
||||
"github.com/photoprism/photoprism/pkg/txt"
|
||||
|
@ -21,7 +19,8 @@ import (
|
|||
func SavePhotoAsYaml(p entity.Photo, conf *config.Config) {
|
||||
// Write YAML sidecar file (optional).
|
||||
if conf.SidecarYaml() {
|
||||
yamlFile := filepath.Join(conf.OriginalsPath(), p.PhotoPath, photoprism.HiddenPath, p.PhotoName) + ".yml"
|
||||
yamlFile := p.YamlFileName(conf.OriginalsPath(), conf.SidecarHidden())
|
||||
|
||||
if err := p.SaveAsYaml(yamlFile); err != nil {
|
||||
log.Errorf("photo: %s (update yaml)", err)
|
||||
} else {
|
||||
|
@ -168,7 +167,7 @@ func GetPhotoYaml(router *gin.RouterGroup, conf *config.Config) {
|
|||
}
|
||||
|
||||
if c.Query("download") != "" {
|
||||
c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", c.Param("uuid")+".yml"))
|
||||
c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", c.Param("uuid")+fs.YamlExt))
|
||||
}
|
||||
|
||||
c.Data(http.StatusOK, "text/x-yaml; charset=utf-8", data)
|
||||
|
|
|
@ -94,17 +94,19 @@ func configAction(ctx *cli.Context) error {
|
|||
fmt.Printf("%-25s %s\n", "exiftool-bin", conf.ExifToolBin())
|
||||
fmt.Printf("%-25s %t\n", "sidecar-json", conf.SidecarJson())
|
||||
fmt.Printf("%-25s %t\n", "sidecar-yaml", conf.SidecarYaml())
|
||||
fmt.Printf("%-25s %t\n", "sidecar-hidden", conf.SidecarHidden())
|
||||
|
||||
// Places / Geocoding API
|
||||
fmt.Printf("%-25s %s\n", "geocoding-api", conf.GeoCodingApi())
|
||||
|
||||
// Thumbnails
|
||||
fmt.Printf("%-25s %d\n", "jpeg-quality", conf.JpegQuality())
|
||||
fmt.Printf("%-25s %s\n", "thumb-filter", conf.ThumbFilter())
|
||||
fmt.Printf("%-25s %t\n", "thumb-uncached", conf.ThumbUncached())
|
||||
fmt.Printf("%-25s %d\n", "thumb-size", conf.ThumbSize())
|
||||
fmt.Printf("%-25s %d\n", "thumb-limit", conf.ThumbLimit())
|
||||
fmt.Printf("%-25s %s\n", "thumb-path", conf.ThumbPath())
|
||||
fmt.Printf("%-25s %d\n", "jpeg-quality", conf.JpegQuality())
|
||||
fmt.Printf("%-25s %t\n", "jpeg-hidden", conf.JpegHidden())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -165,6 +165,11 @@ func (c *Config) SidecarYaml() bool {
|
|||
return c.params.SidecarYaml
|
||||
}
|
||||
|
||||
// SidecarHidden returns true if new sidecar files should be created in a .photoprism sub directory (hidden).
|
||||
func (c *Config) SidecarHidden() bool {
|
||||
return c.params.SidecarHidden
|
||||
}
|
||||
|
||||
// HeifConvertBin returns the heif-convert executable file name.
|
||||
func (c *Config) HeifConvertBin() string {
|
||||
return findExecutable(c.params.HeifConvertBin, "heif-convert")
|
||||
|
|
|
@ -175,14 +175,19 @@ var GlobalFlags = []cli.Flag{
|
|||
},
|
||||
cli.BoolFlag{
|
||||
Name: "sidecar-json, j",
|
||||
Usage: "read metadata from json sidecar files created by exiftool",
|
||||
Usage: "read metadata from JSON sidecar files created by exiftool",
|
||||
EnvVar: "PHOTOPRISM_SIDECAR_JSON",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "sidecar-yaml, y",
|
||||
Usage: "backup photo metadata to yaml sidecar files",
|
||||
Usage: "backup photo metadata to YAML sidecar files",
|
||||
EnvVar: "PHOTOPRISM_SIDECAR_YAML",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "sidecar-hidden",
|
||||
Usage: "create JSON and YAML sidecar files in .photoprism if enabled",
|
||||
EnvVar: "PHOTOPRISM_SIDECAR_HIDDEN",
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "http-port",
|
||||
Value: 2342,
|
||||
|
@ -248,12 +253,6 @@ var GlobalFlags = []cli.Flag{
|
|||
Value: "places",
|
||||
EnvVar: "PHOTOPRISM_GEOCODING_API",
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "jpeg-quality, q",
|
||||
Usage: "set to 95 for high-quality thumbnails (25-100)",
|
||||
Value: 90,
|
||||
EnvVar: "PHOTOPRISM_JPEG_QUALITY",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "thumb-filter, f",
|
||||
Usage: "resample filter (best to worst: blackman, lanczos, cubic, linear)",
|
||||
|
@ -277,6 +276,17 @@ var GlobalFlags = []cli.Flag{
|
|||
Value: 3840,
|
||||
EnvVar: "PHOTOPRISM_THUMB_LIMIT",
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "jpeg-quality, q",
|
||||
Usage: "set to 95 for high-quality thumbnails (25-100)",
|
||||
Value: 90,
|
||||
EnvVar: "PHOTOPRISM_JPEG_QUALITY",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "jpeg-hidden",
|
||||
Usage: "create JPEG files in .photoprism when converting other file types",
|
||||
EnvVar: "PHOTOPRISM_JPEG_HIDDEN",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "disable-tf",
|
||||
Usage: "don't use TensorFlow for image classification",
|
||||
|
|
|
@ -70,12 +70,14 @@ type Params struct {
|
|||
ExifToolBin string `yaml:"exiftool-bin" flag:"exiftool-bin"`
|
||||
SidecarJson bool `yaml:"sidecar-json" flag:"sidecar-json"`
|
||||
SidecarYaml bool `yaml:"sidecar-yaml" flag:"sidecar-yaml"`
|
||||
SidecarHidden bool `yaml:"sidecar-hidden" flag:"sidecar-hidden"`
|
||||
PIDFilename string `yaml:"pid-filename" flag:"pid-filename"`
|
||||
LogFilename string `yaml:"log-filename" flag:"log-filename"`
|
||||
DetachServer bool `yaml:"detach-server" flag:"detach-server"`
|
||||
DetectNSFW bool `yaml:"detect-nsfw" flag:"detect-nsfw"`
|
||||
UploadNSFW bool `yaml:"upload-nsfw" flag:"upload-nsfw"`
|
||||
GeoCodingApi string `yaml:"geocoding-api" flag:"geocoding-api"`
|
||||
JpegHidden bool `yaml:"jpeg-hidden" flag:"jpeg-hidden"`
|
||||
JpegQuality int `yaml:"jpeg-quality" flag:"jpeg-quality"`
|
||||
ThumbFilter string `yaml:"thumb-filter" flag:"thumb-filter"`
|
||||
ThumbUncached bool `yaml:"thumb-uncached" flag:"thumb-uncached"`
|
||||
|
|
|
@ -6,6 +6,11 @@ import (
|
|||
"github.com/photoprism/photoprism/internal/thumb"
|
||||
)
|
||||
|
||||
// JpegHidden returns true if JPEG files should be created in a .photoprism sub directory (hidden).
|
||||
func (c *Config) JpegHidden() bool {
|
||||
return c.params.JpegHidden
|
||||
}
|
||||
|
||||
// JpegQuality returns the jpeg quality for resampling, use 95 for high-quality thumbs (25-100).
|
||||
func (c *Config) JpegQuality() int {
|
||||
if c.params.JpegQuality > 100 {
|
||||
|
|
|
@ -43,6 +43,7 @@ func NewTestParams() *Params {
|
|||
ReadOnly: false,
|
||||
DetectNSFW: true,
|
||||
UploadNSFW: false,
|
||||
SidecarHidden: true,
|
||||
DarktableBin: "/usr/bin/darktable-cli",
|
||||
ExifToolBin: "/usr/bin/exiftool",
|
||||
AssetsPath: assetsPath,
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/photoprism/photoprism/pkg/fs"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
@ -30,7 +31,7 @@ func TestFile_DownloadFileName(t *testing.T) {
|
|||
filename := file.ShareFileName()
|
||||
|
||||
assert.Contains(t, filename, "20190115-000000-Berlin-Morning-Mood")
|
||||
assert.Contains(t, filename, ".jpg")
|
||||
assert.Contains(t, filename, fs.JpegExt)
|
||||
})
|
||||
t.Run("photo without title", func(t *testing.T) {
|
||||
photo := &Photo{TakenAtLocal: time.Date(2019, 01, 15, 0, 0, 0, 0, time.UTC), PhotoTitle: ""}
|
||||
|
@ -39,7 +40,7 @@ func TestFile_DownloadFileName(t *testing.T) {
|
|||
filename := file.ShareFileName()
|
||||
|
||||
assert.Contains(t, filename, "20190115-000000-123")
|
||||
assert.Contains(t, filename, ".jpg")
|
||||
assert.Contains(t, filename, fs.JpegExt)
|
||||
})
|
||||
t.Run("photo without photo", func(t *testing.T) {
|
||||
file := &File{Photo: nil, FileType: "jpg", FileHash: "123Hash", FileUUID: "foobar345678765"}
|
||||
|
|
|
@ -3,7 +3,9 @@ package entity
|
|||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/photoprism/photoprism/pkg/fs"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
|
@ -53,3 +55,12 @@ func (m *Photo) LoadFromYaml(fileName string) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// YamlFileName returns the YAML backup file name.
|
||||
func (m *Photo) YamlFileName(originalsPath string, hidden bool) string {
|
||||
if hidden {
|
||||
return filepath.Join(originalsPath, m.PhotoPath, fs.HiddenPath, m.PhotoName) + fs.YamlExt
|
||||
}
|
||||
|
||||
return filepath.Join(originalsPath, m.PhotoPath, m.PhotoName) + fs.YamlExt
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/dsoprea/go-exif/v2/common"
|
||||
"github.com/dsoprea/go-jpeg-image-structure"
|
||||
"github.com/dsoprea/go-png-image-structure"
|
||||
"github.com/photoprism/photoprism/pkg/fs"
|
||||
"github.com/photoprism/photoprism/pkg/txt"
|
||||
"gopkg.in/ugjka/go-tz.v2/tz"
|
||||
)
|
||||
|
@ -51,7 +52,7 @@ func (data *Data) Exif(fileName string) (err error) {
|
|||
|
||||
fileExtension := strings.ToLower(path.Ext(fileName))
|
||||
|
||||
if fileExtension == ".jpg" || fileExtension == ".jpeg" {
|
||||
if fileExtension == fs.JpegExt || fileExtension == ".jpeg" {
|
||||
jmp := jpegstructure.NewJpegMediaParser()
|
||||
|
||||
sl, err := jmp.ParseFile(fileName)
|
||||
|
|
|
@ -52,7 +52,7 @@ func (c *Convert) Start(path string) error {
|
|||
}
|
||||
|
||||
done := make(map[string]bool)
|
||||
ignore := fs.NewIgnoreList(IgnoreFile, true, false)
|
||||
ignore := fs.NewIgnoreList(fs.IgnoreFile, true, false)
|
||||
|
||||
if err := ignore.Dir(path); err != nil {
|
||||
log.Infof("convert: %s", err)
|
||||
|
@ -136,7 +136,7 @@ func (c *Convert) ConvertCommand(mf *MediaFile, jpegName string, xmpName string)
|
|||
|
||||
// ToJson uses exiftool to export metadata to a json file.
|
||||
func (c *Convert) ToJson(mf *MediaFile, hidden bool) (*MediaFile, error) {
|
||||
jsonName := fs.TypeJson.FindSub(mf.FileName(), HiddenPath, c.conf.Settings().Index.Group)
|
||||
jsonName := fs.TypeJson.FindSub(mf.FileName(), fs.HiddenPath, c.conf.Settings().Index.Group)
|
||||
|
||||
result, err := NewMediaFile(jsonName)
|
||||
|
||||
|
@ -202,7 +202,7 @@ func (c *Convert) ToJpeg(image *MediaFile, hidden bool) (*MediaFile, error) {
|
|||
return image, nil
|
||||
}
|
||||
|
||||
jpegName := fs.TypeJpeg.FindSub(image.FileName(), HiddenPath, c.conf.Settings().Index.Group)
|
||||
jpegName := fs.TypeJpeg.FindSub(image.FileName(), fs.HiddenPath, c.conf.Settings().Index.Group)
|
||||
|
||||
mediaFile, err := NewMediaFile(jpegName)
|
||||
|
||||
|
@ -215,9 +215,9 @@ func (c *Convert) ToJpeg(image *MediaFile, hidden bool) (*MediaFile, error) {
|
|||
}
|
||||
|
||||
if hidden {
|
||||
jpegName = image.HiddenName(".jpg", c.conf.Settings().Index.Group)
|
||||
jpegName = image.HiddenName(fs.JpegExt, c.conf.Settings().Index.Group)
|
||||
} else {
|
||||
jpegName = image.RelatedName(".jpg", c.conf.Settings().Index.Group)
|
||||
jpegName = image.RelatedName(fs.JpegExt, c.conf.Settings().Index.Group)
|
||||
}
|
||||
|
||||
fileName := image.RelativeName(c.conf.OriginalsPath())
|
||||
|
|
|
@ -84,7 +84,7 @@ func (imp *Import) Start(opt ImportOptions) map[string]bool {
|
|||
}
|
||||
|
||||
indexOpt := IndexOptionsAll()
|
||||
ignore := fs.NewIgnoreList(IgnoreFile, true, false)
|
||||
ignore := fs.NewIgnoreList(fs.IgnoreFile, true, false)
|
||||
|
||||
if err := ignore.Dir(importPath); err != nil {
|
||||
log.Infof("import: %s", err)
|
||||
|
|
|
@ -103,7 +103,7 @@ func ImportWorker(jobs <-chan ImportJob) {
|
|||
}
|
||||
|
||||
if imp.conf.SidecarJson() && !f.HasJson() {
|
||||
if jsonFile, err := imp.convert.ToJson(f, true); err != nil {
|
||||
if jsonFile, err := imp.convert.ToJson(f, imp.conf.SidecarHidden()); err != nil {
|
||||
log.Errorf("import: creating json sidecar file failed (%s)", err.Error())
|
||||
} else {
|
||||
log.Infof("import: %s created", fs.RelativeName(jsonFile.FileName(), imp.originalsPath()))
|
||||
|
|
|
@ -94,7 +94,7 @@ func (ind *Index) Start(opt IndexOptions) map[string]bool {
|
|||
}()
|
||||
}
|
||||
|
||||
ignore := fs.NewIgnoreList(IgnoreFile, true, false)
|
||||
ignore := fs.NewIgnoreList(fs.IgnoreFile, true, false)
|
||||
|
||||
if err := ignore.Dir(originalsPath); err != nil {
|
||||
log.Infof("index: %s", err)
|
||||
|
|
|
@ -350,7 +350,7 @@ func (ind *Index) MediaFile(m *MediaFile, o IndexOptions, originalName string) (
|
|||
return result
|
||||
}
|
||||
} else {
|
||||
if yamlName := fs.TypeYaml.FindSub(m.FileName(), HiddenPath, ind.conf.Settings().Index.Group); yamlName != "" {
|
||||
if yamlName := fs.TypeYaml.FindSub(m.FileName(), fs.HiddenPath, ind.conf.Settings().Index.Group); yamlName != "" {
|
||||
if err := photo.LoadFromYaml(yamlName); err != nil {
|
||||
log.Errorf("index: %s (restore from yaml)", err.Error())
|
||||
} else {
|
||||
|
@ -491,7 +491,7 @@ func (ind *Index) MediaFile(m *MediaFile, o IndexOptions, originalName string) (
|
|||
|
||||
// Write YAML sidecar file (optional).
|
||||
if file.FilePrimary && ind.conf.SidecarYaml() {
|
||||
yamlFile := m.HiddenName(".yml", ind.conf.Settings().Index.Group)
|
||||
yamlFile := photo.YamlFileName(ind.originalsPath(), ind.conf.SidecarHidden())
|
||||
|
||||
if err := photo.SaveAsYaml(yamlFile); err != nil {
|
||||
log.Errorf("index: %s (update yaml)", err.Error())
|
||||
|
|
|
@ -44,7 +44,7 @@ func IndexWorker(jobs <-chan IndexJob) {
|
|||
}
|
||||
|
||||
if ind.conf.SidecarJson() && !f.HasJson() {
|
||||
if jsonFile, err := ind.convert.ToJson(f, true); err != nil {
|
||||
if jsonFile, err := ind.convert.ToJson(f, ind.conf.SidecarHidden()); err != nil {
|
||||
log.Errorf("index: creating json sidecar file failed (%s)", err.Error())
|
||||
} else {
|
||||
log.Infof("index: %s created", fs.RelativeName(jsonFile.FileName(), ind.originalsPath()))
|
||||
|
|
|
@ -311,7 +311,7 @@ func (m *MediaFile) RelatedFiles(stripSequence bool) (result RelatedFiles, err e
|
|||
|
||||
// Add hidden JPEG if exists.
|
||||
if !result.ContainsJpeg() && result.Main != nil {
|
||||
if jpegName := fs.TypeJpeg.FindSub(result.Main.FileName(), HiddenPath, stripSequence); jpegName != "" {
|
||||
if jpegName := fs.TypeJpeg.FindSub(result.Main.FileName(), fs.HiddenPath, stripSequence); jpegName != "" {
|
||||
if resultFile, err := NewMediaFile(jpegName); err == nil {
|
||||
result.Files = append(result.Files, resultFile)
|
||||
}
|
||||
|
@ -357,7 +357,7 @@ func (m *MediaFile) RelativePath(directory string) string {
|
|||
}
|
||||
|
||||
// Remove hidden sub directory if exists.
|
||||
if path.Base(pathname) == HiddenPath {
|
||||
if path.Base(pathname) == fs.HiddenPath {
|
||||
pathname = path.Dir(pathname)
|
||||
}
|
||||
|
||||
|
@ -395,7 +395,7 @@ func (m *MediaFile) AbsBase(stripSequence bool) string {
|
|||
|
||||
// HiddenName returns the a filename with the same base name and a given extension in a hidden sub directory.
|
||||
func (m *MediaFile) HiddenName(fileExt string, stripSequence bool) string {
|
||||
return fs.SubFileName(m.FileName(), HiddenPath, fileExt, stripSequence)
|
||||
return fs.SubFileName(m.FileName(), fs.HiddenPath, fileExt, stripSequence)
|
||||
}
|
||||
|
||||
// RelatedName returns the a filename with the same base name and a given extension in the same directory.
|
||||
|
@ -611,7 +611,7 @@ func (m *MediaFile) Jpeg() (*MediaFile, error) {
|
|||
return m, nil
|
||||
}
|
||||
|
||||
jpegFilename := fs.TypeJpeg.FindSub(m.FileName(), HiddenPath, false)
|
||||
jpegFilename := fs.TypeJpeg.FindSub(m.FileName(), fs.HiddenPath, false)
|
||||
|
||||
if jpegFilename == "" {
|
||||
return nil, fmt.Errorf("no jpeg found for %s", m.FileName())
|
||||
|
@ -626,7 +626,7 @@ func (m *MediaFile) HasJpeg() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
return fs.TypeJpeg.FindSub(m.FileName(), HiddenPath, false) != ""
|
||||
return fs.TypeJpeg.FindSub(m.FileName(), fs.HiddenPath, false) != ""
|
||||
}
|
||||
|
||||
// HasJson returns true if this file has or is a json sidecar file.
|
||||
|
@ -635,7 +635,7 @@ func (m *MediaFile) HasJson() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
return fs.TypeJson.FindSub(m.FileName(), HiddenPath, false) != ""
|
||||
return fs.TypeJson.FindSub(m.FileName(), fs.HiddenPath, false) != ""
|
||||
}
|
||||
|
||||
func (m *MediaFile) decodeDimensions() error {
|
||||
|
|
|
@ -450,7 +450,7 @@ func TestMediaFile_RelativePath(t *testing.T) {
|
|||
assert.Equal(t, conf.ExamplesPath(), path)
|
||||
})
|
||||
t.Run("hidden root", func(t *testing.T) {
|
||||
path := mediaFile.RelativePath(filepath.Join(conf.ExamplesPath(), HiddenPath))
|
||||
path := mediaFile.RelativePath(filepath.Join(conf.ExamplesPath(), fs.HiddenPath))
|
||||
assert.Equal(t, "", path)
|
||||
})
|
||||
}
|
||||
|
@ -639,7 +639,7 @@ func TestMediaFile_Extension(t *testing.T) {
|
|||
|
||||
mediaFile, err := NewMediaFile(conf.ExamplesPath() + "/elephants.jpg")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, ".jpg", mediaFile.Extension())
|
||||
assert.Equal(t, fs.JpegExt, mediaFile.Extension())
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ func (m *MediaFile) MetaData() (result meta.Data, err error) {
|
|||
m.metaDataOnce.Do(func() {
|
||||
err = m.metaData.Exif(m.FileName())
|
||||
|
||||
if jsonFile := fs.TypeJson.FindSub(m.FileName(), HiddenPath, false); jsonFile == "" {
|
||||
if jsonFile := fs.TypeJson.FindSub(m.FileName(), fs.HiddenPath, false); jsonFile == "" {
|
||||
log.Debugf("mediafile: no json sidecar file found for %s", txt.Quote(filepath.Base(m.FileName())))
|
||||
} else if jsonErr := m.metaData.JSON(jsonFile); jsonErr != nil {
|
||||
log.Warn(jsonErr)
|
||||
|
|
|
@ -12,6 +12,3 @@ import (
|
|||
)
|
||||
|
||||
var log = event.Log
|
||||
|
||||
const IgnoreFile = ".ppignore"
|
||||
const HiddenPath = ".photoprism"
|
||||
|
|
|
@ -47,7 +47,7 @@ func (rs *Resample) Start(force bool) error {
|
|||
}
|
||||
|
||||
done := make(map[string]bool)
|
||||
ignore := fs.NewIgnoreList(IgnoreFile, true, false)
|
||||
ignore := fs.NewIgnoreList(fs.IgnoreFile, true, false)
|
||||
|
||||
if err := ignore.Dir(originalsPath); err != nil {
|
||||
log.Infof("resample: %s", err)
|
||||
|
|
|
@ -139,7 +139,7 @@ func TestClient_UploadAndDelete(t *testing.T) {
|
|||
|
||||
assert.IsType(t, Client{}, c)
|
||||
|
||||
tempName := rnd.UUID() + ".jpg"
|
||||
tempName := rnd.UUID() + fs.JpegExt
|
||||
|
||||
if err := c.Upload("testdata/example.jpg", tempName); err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/photoprism/photoprism/pkg/fs"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
@ -13,7 +14,7 @@ func TestJpeg(t *testing.T) {
|
|||
for _, ext := range formats {
|
||||
t.Run(ext, func(t *testing.T) {
|
||||
src := "testdata/example." + ext
|
||||
dst := "testdata/example." + ext + ".jpg"
|
||||
dst := "testdata/example." + ext + fs.JpegExt
|
||||
|
||||
assert.NoFileExists(t, dst)
|
||||
|
||||
|
|
|
@ -36,6 +36,11 @@ const (
|
|||
type FileExtensions map[string]FileType
|
||||
type TypeExtensions map[FileType][]string
|
||||
|
||||
const (
|
||||
YamlExt = ".yml"
|
||||
JpegExt = ".jpg"
|
||||
)
|
||||
|
||||
// FileExt contains the filename extensions of file formats known to PhotoPrism.
|
||||
var FileExt = FileExtensions{
|
||||
".bmp": TypeBitmap,
|
||||
|
|
|
@ -18,6 +18,9 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
const IgnoreFile = ".ppignore"
|
||||
const HiddenPath = ".photoprism"
|
||||
|
||||
// FileExists returns true if file exists and is not a directory.
|
||||
func FileExists(fileName string) bool {
|
||||
if fileName == "" {
|
||||
|
|
Loading…
Reference in a new issue