Run purge after indexing files in Web UI #234

Signed-off-by: Michael Mayer <michael@liquidbytes.net>
This commit is contained in:
Michael Mayer 2020-05-07 21:46:00 +02:00
parent ac33ee87a1
commit 252672b291
7 changed files with 45 additions and 21 deletions

View file

@ -56,19 +56,32 @@ func StartIndexing(router *gin.RouterGroup, conf *config.Config) {
ind := service.Index()
opt := photoprism.IndexOptions{
indOpt := photoprism.IndexOptions{
Rescan: f.Rescan,
Convert: f.Convert && !conf.ReadOnly(),
Path: filepath.Clean(f.Path),
}
if len(opt.Path) > 1 {
event.Info(fmt.Sprintf("indexing files in %s", txt.Quote(opt.Path)))
if len(indOpt.Path) > 1 {
event.Info(fmt.Sprintf("indexing files in %s", txt.Quote(indOpt.Path)))
} else {
event.Info("indexing originals...")
}
ind.Start(opt)
ind.Start(indOpt)
prg := service.Purge()
prgOpt := photoprism.PurgeOptions{
Path: filepath.Clean(f.Path),
}
if files, photos, err := prg.Start(prgOpt); err != nil {
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": txt.UcFirst(err.Error())})
return
} else if len(files) > 0 || len(photos) > 0 {
event.Info(fmt.Sprintf("removed %d files and %d photos", len(files), len(photos)))
}
elapsed := int(time.Since(start).Seconds())

View file

@ -52,9 +52,9 @@ func purgeAction(ctx *cli.Context) error {
subPath := strings.TrimSpace(ctx.Args().First())
if subPath == "" {
log.Infof("purging missing files in %s", txt.Quote(filepath.Base(conf.OriginalsPath())))
log.Infof("removing missing files in %s", txt.Quote(filepath.Base(conf.OriginalsPath())))
} else {
log.Infof("purging missing files in %s", txt.Quote(fs.RelativeName(filepath.Join(conf.OriginalsPath(), subPath), filepath.Dir(conf.OriginalsPath()))))
log.Infof("removing missing files in %s", txt.Quote(fs.RelativeName(filepath.Join(conf.OriginalsPath(), subPath), filepath.Dir(conf.OriginalsPath()))))
}
if conf.ReadOnly() {
@ -74,7 +74,7 @@ func purgeAction(ctx *cli.Context) error {
} else {
elapsed := time.Since(start)
log.Infof("purged %d files and %d photos in %s", len(files), len(photos), elapsed)
log.Infof("removed %d files and %d photos in %s", len(files), len(photos), elapsed)
}
conf.Shutdown()

View file

@ -93,6 +93,10 @@ func (m *File) ShareFileName() string {
// Changed returns true if new and old file size or modified time are different.
func (m File) Changed(fileSize int64, fileModified time.Time) bool {
if m.DeletedAt != nil {
return true
}
if m.FileSize != fileSize {
return true
}

View file

@ -291,6 +291,9 @@ func (ind *Index) MediaFile(m *MediaFile, o IndexOptions, originalName string) (
}
}
photo.DeletedAt = nil
file.DeletedAt = nil
if photoExists {
// Estimate location
if o.Rescan && photo.NoLocation() {

View file

@ -4,7 +4,6 @@ import (
"errors"
"fmt"
"path"
"path/filepath"
"runtime"
"github.com/photoprism/photoprism/internal/config"
@ -45,13 +44,6 @@ func (prg *Purge) Start(opt PurgeOptions) (purgedFiles map[string]bool, purgedPh
purgedFiles = make(map[string]bool)
purgedPhotos = make(map[string]bool)
originalsPath := prg.originalsPath()
optionsPath := filepath.Join(originalsPath, opt.Path)
if !fs.PathExists(optionsPath) {
err = fmt.Errorf("purge: %s does not exist", txt.Quote(optionsPath))
event.Error(err.Error())
return purgedFiles, purgedPhotos, err
}
if err := mutex.Worker.Start(); err != nil {
err = fmt.Errorf("purge: %s", err.Error())
@ -70,7 +62,7 @@ func (prg *Purge) Start(opt PurgeOptions) (purgedFiles map[string]bool, purgedPh
offset := 0
for {
files, err := q.Files(limit, offset)
files, err := q.Files(limit, offset, opt.Path)
if err != nil {
return purgedFiles, purgedPhotos, err
@ -102,7 +94,7 @@ func (prg *Purge) Start(opt PurgeOptions) (purgedFiles map[string]bool, purgedPh
log.Errorf("purge: %s", err)
} else {
purgedFiles[fileName] = true
log.Infof("purge: removed %s", txt.Quote(fs.RelativeName(fileName, originalsPath)))
log.Infof("purge: removed file %s", txt.Quote(fs.RelativeName(fileName, originalsPath)))
}
}
}
@ -151,7 +143,7 @@ func (prg *Purge) Start(opt PurgeOptions) (purgedFiles map[string]bool, purgedPh
if opt.Hard {
log.Infof("purge: permanently deleted photo %s", txt.Quote(photo.PhotoTitle))
} else {
log.Infof("purge: archived photo %s", txt.Quote(photo.PhotoTitle))
log.Infof("purge: removed photo %s", txt.Quote(photo.PhotoTitle))
}
}
}

View file

@ -1,12 +1,24 @@
package query
import (
"strings"
"github.com/photoprism/photoprism/internal/entity"
)
// Files returns file entities in the range of limit and offset sorted by id.
func (q *Query) Files(limit int, offset int) (files []entity.File, err error) {
err = q.db.Unscoped().Where(&entity.File{}).Order("id").Limit(limit).Offset(offset).Find(&files).Error
func (q *Query) Files(limit int, offset int, filePath string) (files []entity.File, err error) {
if strings.HasPrefix(filePath, "/") {
filePath = filePath[1:]
}
stmt := q.db.Unscoped()
if filePath != "" {
stmt = stmt.Where("file_name LIKE ?", filePath + "/%")
}
err = stmt.Order("id").Limit(limit).Offset(offset).Find(&files).Error
return files, err
}

View file

@ -13,7 +13,7 @@ func TestQuery_Files(t *testing.T) {
search := New(conf.Db())
t.Run("files found", func(t *testing.T) {
files, err := search.Files(1000, 0)
files, err := search.Files(1000, 0, "/")
assert.Nil(t, err)
assert.LessOrEqual(t, 5, len(files))