Index: Check if the originals folder is empty before indexing #2299

Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
Michael Mayer
2022-08-01 17:08:46 +02:00
parent 197acbc802
commit eba9fd701b
9 changed files with 145 additions and 112 deletions

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-06-16 16:58+0000\n" "POT-Creation-Date: 2022-08-01 15:07+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,323 +17,331 @@ msgstr ""
"Content-Type: text/plain; charset=CHARSET\n" "Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
#: messages.go:85 #: messages.go:87
msgid "Unexpected error, please try again" msgid "Unexpected error, please try again"
msgstr "" msgstr ""
#: messages.go:86 #: messages.go:88
msgid "Invalid request" msgid "Invalid request"
msgstr "" msgstr ""
#: messages.go:87 #: messages.go:89
msgid "Changes could not be saved" msgid "Changes could not be saved"
msgstr "" msgstr ""
#: messages.go:88 #: messages.go:90
msgid "Could not be deleted" msgid "Could not be deleted"
msgstr "" msgstr ""
#: messages.go:89 #: messages.go:91
#, c-format #, c-format
msgid "%s already exists" msgid "%s already exists"
msgstr "" msgstr ""
#: messages.go:90 #: messages.go:92
msgid "Not found" msgid "Not found"
msgstr "" msgstr ""
#: messages.go:91 #: messages.go:93
msgid "File not found" msgid "File not found"
msgstr "" msgstr ""
#: messages.go:92
msgid "Selection not found"
msgstr ""
#: messages.go:93
msgid "Entity not found"
msgstr ""
#: messages.go:94 #: messages.go:94
msgid "Account not found" msgid "Originals folder is empty"
msgstr "" msgstr ""
#: messages.go:95 #: messages.go:95
msgid "User not found" msgid "Selection not found"
msgstr "" msgstr ""
#: messages.go:96 #: messages.go:96
msgid "Label not found" msgid "Entity not found"
msgstr "" msgstr ""
#: messages.go:97 #: messages.go:97
msgid "Album not found" msgid "Account not found"
msgstr "" msgstr ""
#: messages.go:98 #: messages.go:98
msgid "Subject not found" msgid "User not found"
msgstr "" msgstr ""
#: messages.go:99 #: messages.go:99
msgid "Person not found" msgid "Label not found"
msgstr "" msgstr ""
#: messages.go:100 #: messages.go:100
msgid "Face not found" msgid "Album not found"
msgstr "" msgstr ""
#: messages.go:101 #: messages.go:101
msgid "Not available in public mode" msgid "Subject not found"
msgstr "" msgstr ""
#: messages.go:102 #: messages.go:102
msgid "not available in read-only mode" msgid "Person not found"
msgstr "" msgstr ""
#: messages.go:103 #: messages.go:103
msgid "Please log in and try again" msgid "Face not found"
msgstr "" msgstr ""
#: messages.go:104 #: messages.go:104
msgid "Upload might be offensive" msgid "Not available in public mode"
msgstr "" msgstr ""
#: messages.go:105 #: messages.go:105
msgid "No items selected" msgid "not available in read-only mode"
msgstr "" msgstr ""
#: messages.go:106 #: messages.go:106
msgid "Failed creating file, please check permissions" msgid "Please log in and try again"
msgstr "" msgstr ""
#: messages.go:107 #: messages.go:107
msgid "Failed creating folder, please check permissions" msgid "Upload might be offensive"
msgstr "" msgstr ""
#: messages.go:108 #: messages.go:108
msgid "Could not connect, please try again" msgid "No items selected"
msgstr "" msgstr ""
#: messages.go:109 #: messages.go:109
msgid "Invalid password, please try again" msgid "Failed creating file, please check permissions"
msgstr "" msgstr ""
#: messages.go:110 #: messages.go:110
msgid "Feature disabled" msgid "Failed creating folder, please check permissions"
msgstr "" msgstr ""
#: messages.go:111 #: messages.go:111
msgid "No labels selected" msgid "Could not connect, please try again"
msgstr "" msgstr ""
#: messages.go:112 #: messages.go:112
msgid "No albums selected" msgid "Invalid password, please try again"
msgstr "" msgstr ""
#: messages.go:113 #: messages.go:113
msgid "No files available for download" msgid "Feature disabled"
msgstr "" msgstr ""
#: messages.go:114 #: messages.go:114
msgid "Failed to create zip file" msgid "No labels selected"
msgstr "" msgstr ""
#: messages.go:115 #: messages.go:115
msgid "Invalid credentials" msgid "No albums selected"
msgstr "" msgstr ""
#: messages.go:116 #: messages.go:116
msgid "Invalid link" msgid "No files available for download"
msgstr "" msgstr ""
#: messages.go:117 #: messages.go:117
msgid "Invalid name" msgid "Failed to create zip file"
msgstr "" msgstr ""
#: messages.go:118 #: messages.go:118
msgid "Busy, please try again later" msgid "Invalid credentials"
msgstr "" msgstr ""
#: messages.go:119 #: messages.go:119
msgid "Invalid link"
msgstr ""
#: messages.go:120
msgid "Invalid name"
msgstr ""
#: messages.go:121
msgid "Busy, please try again later"
msgstr ""
#: messages.go:122
#, c-format #, c-format
msgid "The wakeup interval is %s, but must be 1h or less" msgid "The wakeup interval is %s, but must be 1h or less"
msgstr "" msgstr ""
#: messages.go:122
msgid "Changes successfully saved"
msgstr ""
#: messages.go:123 #: messages.go:123
msgid "Album created" msgid "Your account could not be connected"
msgstr ""
#: messages.go:124
msgid "Album saved"
msgstr ""
#: messages.go:125
#, c-format
msgid "Album %s deleted"
msgstr "" msgstr ""
#: messages.go:126 #: messages.go:126
msgid "Album contents cloned" msgid "Changes successfully saved"
msgstr "" msgstr ""
#: messages.go:127 #: messages.go:127
msgid "File removed from stack" msgid "Album created"
msgstr "" msgstr ""
#: messages.go:128 #: messages.go:128
msgid "File deleted" msgid "Album saved"
msgstr "" msgstr ""
#: messages.go:129 #: messages.go:129
#, c-format #, c-format
msgid "Selection added to %s" msgid "Album %s deleted"
msgstr "" msgstr ""
#: messages.go:130 #: messages.go:130
#, c-format msgid "Album contents cloned"
msgid "One entry added to %s"
msgstr "" msgstr ""
#: messages.go:131 #: messages.go:131
#, c-format msgid "File removed from stack"
msgid "%d entries added to %s"
msgstr "" msgstr ""
#: messages.go:132 #: messages.go:132
#, c-format msgid "File deleted"
msgid "One entry removed from %s"
msgstr "" msgstr ""
#: messages.go:133 #: messages.go:133
#, c-format #, c-format
msgid "%d entries removed from %s" msgid "Selection added to %s"
msgstr "" msgstr ""
#: messages.go:134 #: messages.go:134
msgid "Account created" #, c-format
msgid "One entry added to %s"
msgstr "" msgstr ""
#: messages.go:135 #: messages.go:135
msgid "Account saved" #, c-format
msgid "%d entries added to %s"
msgstr "" msgstr ""
#: messages.go:136 #: messages.go:136
msgid "Account deleted" #, c-format
msgid "One entry removed from %s"
msgstr "" msgstr ""
#: messages.go:137 #: messages.go:137
msgid "Settings saved" #, c-format
msgid "%d entries removed from %s"
msgstr "" msgstr ""
#: messages.go:138 #: messages.go:138
msgid "Password changed" msgid "Account created"
msgstr "" msgstr ""
#: messages.go:139 #: messages.go:139
#, c-format msgid "Account saved"
msgid "Import completed in %d s"
msgstr "" msgstr ""
#: messages.go:140 #: messages.go:140
msgid "Import canceled" msgid "Account deleted"
msgstr "" msgstr ""
#: messages.go:141 #: messages.go:141
#, c-format msgid "Settings saved"
msgid "Indexing completed in %d s"
msgstr "" msgstr ""
#: messages.go:142 #: messages.go:142
msgid "Indexing originals..." msgid "Password changed"
msgstr "" msgstr ""
#: messages.go:143 #: messages.go:143
#, c-format #, c-format
msgid "Indexing files in %s" msgid "Import completed in %d s"
msgstr "" msgstr ""
#: messages.go:144 #: messages.go:144
msgid "Indexing canceled" msgid "Import canceled"
msgstr "" msgstr ""
#: messages.go:145 #: messages.go:145
#, c-format #, c-format
msgid "Removed %d files and %d photos" msgid "Indexing completed in %d s"
msgstr "" msgstr ""
#: messages.go:146 #: messages.go:146
#, c-format msgid "Indexing originals..."
msgid "Moving files from %s"
msgstr "" msgstr ""
#: messages.go:147 #: messages.go:147
#, c-format #, c-format
msgid "Copying files from %s" msgid "Indexing files in %s"
msgstr "" msgstr ""
#: messages.go:148 #: messages.go:148
msgid "Labels deleted" msgid "Indexing canceled"
msgstr "" msgstr ""
#: messages.go:149 #: messages.go:149
msgid "Label saved" #, c-format
msgid "Removed %d files and %d photos"
msgstr "" msgstr ""
#: messages.go:150 #: messages.go:150
msgid "Subject saved" #, c-format
msgid "Moving files from %s"
msgstr "" msgstr ""
#: messages.go:151 #: messages.go:151
msgid "Subject deleted" #, c-format
msgid "Copying files from %s"
msgstr "" msgstr ""
#: messages.go:152 #: messages.go:152
msgid "Person saved" msgid "Labels deleted"
msgstr "" msgstr ""
#: messages.go:153 #: messages.go:153
msgid "Person deleted" msgid "Label saved"
msgstr "" msgstr ""
#: messages.go:154 #: messages.go:154
msgid "Subject saved"
msgstr ""
#: messages.go:155
msgid "Subject deleted"
msgstr ""
#: messages.go:156
msgid "Person saved"
msgstr ""
#: messages.go:157
msgid "Person deleted"
msgstr ""
#: messages.go:158
#, c-format #, c-format
msgid "%d files uploaded in %d s" msgid "%d files uploaded in %d s"
msgstr "" msgstr ""
#: messages.go:155 #: messages.go:159
msgid "Selection approved" msgid "Selection approved"
msgstr "" msgstr ""
#: messages.go:156 #: messages.go:160
msgid "Selection archived" msgid "Selection archived"
msgstr "" msgstr ""
#: messages.go:157 #: messages.go:161
msgid "Selection restored" msgid "Selection restored"
msgstr "" msgstr ""
#: messages.go:158 #: messages.go:162
msgid "Selection marked as private" msgid "Selection marked as private"
msgstr "" msgstr ""
#: messages.go:159 #: messages.go:163
msgid "Albums deleted" msgid "Albums deleted"
msgstr "" msgstr ""
#: messages.go:160 #: messages.go:164
#, c-format #, c-format
msgid "Zip created in %d s" msgid "Zip created in %d s"
msgstr "" msgstr ""
#: messages.go:161 #: messages.go:165
msgid "Permanently deleted" msgid "Permanently deleted"
msgstr "" msgstr ""
#: messages.go:162 #: messages.go:166
#, c-format #, c-format
msgid "%s has been restored" msgid "%s has been restored"
msgstr "" msgstr ""

View File

@@ -84,7 +84,7 @@ func StartImport(router *gin.RouterGroup) {
imp.Start(opt) imp.Start(opt)
if subPath != "" && path != conf.ImportPath() && fs.IsEmpty(path) { if subPath != "" && path != conf.ImportPath() && fs.DirIsEmpty(path) {
if err := os.Remove(path); err != nil { if err := os.Remove(path); err != nil {
log.Errorf("import: failed deleting empty folder %s: %s", clean.Log(path), err) log.Errorf("import: failed deleting empty folder %s: %s", clean.Log(path), err)
} else { } else {

View File

@@ -8,6 +8,7 @@ const (
ErrAlreadyExists ErrAlreadyExists
ErrNotFound ErrNotFound
ErrFileNotFound ErrFileNotFound
ErrOriginalsEmpty
ErrSelectionNotFound ErrSelectionNotFound
ErrEntityNotFound ErrEntityNotFound
ErrAccountNotFound ErrAccountNotFound
@@ -90,6 +91,7 @@ var Messages = MessageMap{
ErrAlreadyExists: gettext("%s already exists"), ErrAlreadyExists: gettext("%s already exists"),
ErrNotFound: gettext("Not found"), ErrNotFound: gettext("Not found"),
ErrFileNotFound: gettext("File not found"), ErrFileNotFound: gettext("File not found"),
ErrOriginalsEmpty: gettext("Originals folder is empty"),
ErrSelectionNotFound: gettext("Selection not found"), ErrSelectionNotFound: gettext("Selection not found"),
ErrEntityNotFound: gettext("Entity not found"), ErrEntityNotFound: gettext("Entity not found"),
ErrAccountNotFound: gettext("Account not found"), ErrAccountNotFound: gettext("Account not found"),

View File

@@ -44,6 +44,13 @@ func (w *CleanUp) Start(opt CleanUpOptions) (thumbs int, orphans int, sidecars i
} }
}() }()
originalsPath := w.conf.OriginalsPath()
// Check if originals folder is empty.
if fs.DirIsEmpty(originalsPath) {
return thumbs, orphans, sidecars, err
}
if err = mutex.MainWorker.Start(); err != nil { if err = mutex.MainWorker.Start(); err != nil {
log.Warnf("cleanup: %s (start)", err) log.Warnf("cleanup: %s (start)", err)
return thumbs, orphans, sidecars, err return thumbs, orphans, sidecars, err

View File

@@ -10,8 +10,6 @@ import (
"sort" "sort"
"sync" "sync"
"github.com/photoprism/photoprism/pkg/media"
"github.com/karrick/godirwalk" "github.com/karrick/godirwalk"
"github.com/photoprism/photoprism/internal/config" "github.com/photoprism/photoprism/internal/config"
@@ -20,6 +18,7 @@ import (
"github.com/photoprism/photoprism/internal/mutex" "github.com/photoprism/photoprism/internal/mutex"
"github.com/photoprism/photoprism/pkg/clean" "github.com/photoprism/photoprism/pkg/clean"
"github.com/photoprism/photoprism/pkg/fs" "github.com/photoprism/photoprism/pkg/fs"
"github.com/photoprism/photoprism/pkg/media"
) )
// Import represents an importer that can copy/move MediaFiles to the originals directory. // Import represents an importer that can copy/move MediaFiles to the originals directory.
@@ -69,6 +68,7 @@ func (imp *Import) Start(opt ImportOptions) fs.Done {
ind := imp.index ind := imp.index
importPath := opt.Path importPath := opt.Path
// Check if the import folder exists.
if !fs.PathExists(importPath) { if !fs.PathExists(importPath) {
event.Error(fmt.Sprintf("import: %s does not exist", importPath)) event.Error(fmt.Sprintf("import: %s does not exist", importPath))
return done return done
@@ -221,7 +221,7 @@ func (imp *Import) Start(opt ImportOptions) fs.Done {
if opt.RemoveEmptyDirectories { if opt.RemoveEmptyDirectories {
// Remove empty directories from import path. // Remove empty directories from import path.
for _, directory := range directories { for _, directory := range directories {
if fs.IsEmpty(directory) { if fs.DirIsEmpty(directory) {
if err := os.Remove(directory); err != nil { if err := os.Remove(directory); err != nil {
log.Errorf("import: failed deleting empty folder %s (%s)", clean.Log(fs.RelName(directory, importPath)), err) log.Errorf("import: failed deleting empty folder %s (%s)", clean.Log(fs.RelName(directory, importPath)), err)
} else { } else {

View File

@@ -15,6 +15,7 @@ import (
"github.com/photoprism/photoprism/internal/entity" "github.com/photoprism/photoprism/internal/entity"
"github.com/photoprism/photoprism/internal/event" "github.com/photoprism/photoprism/internal/event"
"github.com/photoprism/photoprism/internal/face" "github.com/photoprism/photoprism/internal/face"
"github.com/photoprism/photoprism/internal/i18n"
"github.com/photoprism/photoprism/internal/mutex" "github.com/photoprism/photoprism/internal/mutex"
"github.com/photoprism/photoprism/internal/nsfw" "github.com/photoprism/photoprism/internal/nsfw"
"github.com/photoprism/photoprism/pkg/clean" "github.com/photoprism/photoprism/pkg/clean"
@@ -89,7 +90,10 @@ func (ind *Index) Start(o IndexOptions) fs.Done {
optionsPath := filepath.Join(originalsPath, o.Path) optionsPath := filepath.Join(originalsPath, o.Path)
if !fs.PathExists(optionsPath) { if !fs.PathExists(optionsPath) {
event.Error(fmt.Sprintf("index: %s does not exist", clean.Log(optionsPath))) event.Error(fmt.Sprintf("%s does not exist", clean.Log(optionsPath)))
return done
} else if fs.DirIsEmpty(originalsPath) {
event.InfoMsg(i18n.ErrOriginalsEmpty)
return done return done
} }

View File

@@ -41,6 +41,13 @@ func (w *Purge) Start(opt PurgeOptions) (purgedFiles map[string]bool, purgedPhot
} }
}() }()
originalsPath := w.conf.OriginalsPath()
// Check if originals folder is empty.
if fs.DirIsEmpty(originalsPath) {
return purgedFiles, purgedPhotos, err
}
var ignore fs.Done var ignore fs.Done
if opt.Ignore != nil { if opt.Ignore != nil {

View File

@@ -213,8 +213,8 @@ func Download(filepath string, url string) error {
return nil return nil
} }
// IsEmpty returns true if a directory is empty. // DirIsEmpty returns true if a directory is empty.
func IsEmpty(path string) bool { func DirIsEmpty(path string) bool {
f, err := os.Open(path) f, err := os.Open(path)
if err != nil { if err != nil {

View File

@@ -82,16 +82,21 @@ func TestExpandedFilename(t *testing.T) {
}) })
} }
func TestDirectoryIsEmpty(t *testing.T) { func TestDirIsEmpty(t *testing.T) {
t.Run("not empty path", func(t *testing.T) { t.Run("CurrentDir", func(t *testing.T) {
assert.Equal(t, false, IsEmpty("./testdata")) assert.Equal(t, false, DirIsEmpty("."))
}) })
t.Run("not existing path", func(t *testing.T) { t.Run("Testdata", func(t *testing.T) {
assert.Equal(t, false, IsEmpty("./xxx")) assert.Equal(t, false, DirIsEmpty("./testdata"))
}) })
t.Run("empty path", func(t *testing.T) { t.Run("XXX", func(t *testing.T) {
os.Mkdir("./testdata/emptyDir", 0777) assert.Equal(t, false, DirIsEmpty("./xxx"))
})
t.Run("EmptyDir", func(t *testing.T) {
if err := os.Mkdir("./testdata/emptyDir", 0777); err != nil {
t.Fatal(err)
}
defer os.RemoveAll("./testdata/emptyDir") defer os.RemoveAll("./testdata/emptyDir")
assert.Equal(t, true, IsEmpty("./testdata/emptyDir")) assert.Equal(t, true, DirIsEmpty("./testdata/emptyDir"))
}) })
} }