diff --git a/pkg/autotag/gallery_test.go b/pkg/autotag/gallery_test.go index 53513fb9d..63d82a8d1 100644 --- a/pkg/autotag/gallery_test.go +++ b/pkg/autotag/gallery_test.go @@ -74,13 +74,7 @@ func TestGalleryStudios(t *testing.T) { assert := assert.New(t) - for _, test := range testTables { - mockStudioReader := &mocks.StudioReaderWriter{} - mockGalleryReader := &mocks.GalleryReaderWriter{} - - mockStudioReader.On("QueryForAutoTag", mock.Anything).Return([]*models.Studio{&studio, &reversedStudio}, nil).Once() - mockStudioReader.On("GetAliases", mock.Anything).Return([]string{}, nil).Maybe() - + doTest := func(mockStudioReader *mocks.StudioReaderWriter, mockGalleryReader *mocks.GalleryReaderWriter, test pathTestTable) { if test.Matches { mockGalleryReader.On("Find", galleryID).Return(&models.Gallery{}, nil).Once() expectedStudioID := models.NullInt64(studioID) @@ -100,6 +94,33 @@ func TestGalleryStudios(t *testing.T) { mockStudioReader.AssertExpectations(t) mockGalleryReader.AssertExpectations(t) } + + for _, test := range testTables { + mockStudioReader := &mocks.StudioReaderWriter{} + mockGalleryReader := &mocks.GalleryReaderWriter{} + + mockStudioReader.On("QueryForAutoTag", mock.Anything).Return([]*models.Studio{&studio, &reversedStudio}, nil).Once() + mockStudioReader.On("GetAliases", mock.Anything).Return([]string{}, nil).Maybe() + + doTest(mockStudioReader, mockGalleryReader, test) + } + + // test against aliases + const unmatchedName = "unmatched" + studio.Name.String = unmatchedName + + for _, test := range testTables { + mockStudioReader := &mocks.StudioReaderWriter{} + mockGalleryReader := &mocks.GalleryReaderWriter{} + + mockStudioReader.On("QueryForAutoTag", mock.Anything).Return([]*models.Studio{&studio, &reversedStudio}, nil).Once() + mockStudioReader.On("GetAliases", studioID).Return([]string{ + studioName, + }, nil).Once() + mockStudioReader.On("GetAliases", reversedStudioID).Return([]string{}, nil).Once() + + doTest(mockStudioReader, mockGalleryReader, test) + } } func TestGalleryTags(t *testing.T) { @@ -122,12 +143,7 @@ func TestGalleryTags(t *testing.T) { assert := assert.New(t) - for _, test := range testTables { - mockTagReader := &mocks.TagReaderWriter{} - mockGalleryReader := &mocks.GalleryReaderWriter{} - - mockTagReader.On("QueryForAutoTag", mock.Anything).Return([]*models.Tag{&tag, &reversedTag}, nil).Once() - + doTest := func(mockTagReader *mocks.TagReaderWriter, mockGalleryReader *mocks.GalleryReaderWriter, test pathTestTable) { if test.Matches { mockGalleryReader.On("GetTagIDs", galleryID).Return(nil, nil).Once() mockGalleryReader.On("UpdateTags", galleryID, []int{tagID}).Return(nil).Once() @@ -143,4 +159,30 @@ func TestGalleryTags(t *testing.T) { mockTagReader.AssertExpectations(t) mockGalleryReader.AssertExpectations(t) } + + for _, test := range testTables { + mockTagReader := &mocks.TagReaderWriter{} + mockGalleryReader := &mocks.GalleryReaderWriter{} + + mockTagReader.On("QueryForAutoTag", mock.Anything).Return([]*models.Tag{&tag, &reversedTag}, nil).Once() + mockTagReader.On("GetAliases", mock.Anything).Return([]string{}, nil).Maybe() + + doTest(mockTagReader, mockGalleryReader, test) + } + + const unmatchedName = "unmatched" + tag.Name = unmatchedName + + for _, test := range testTables { + mockTagReader := &mocks.TagReaderWriter{} + mockGalleryReader := &mocks.GalleryReaderWriter{} + + mockTagReader.On("QueryForAutoTag", mock.Anything).Return([]*models.Tag{&tag, &reversedTag}, nil).Once() + mockTagReader.On("GetAliases", tagID).Return([]string{ + tagName, + }, nil).Once() + mockTagReader.On("GetAliases", reversedTagID).Return([]string{}, nil).Once() + + doTest(mockTagReader, mockGalleryReader, test) + } } diff --git a/pkg/autotag/image_test.go b/pkg/autotag/image_test.go index 69e067b9a..c56494602 100644 --- a/pkg/autotag/image_test.go +++ b/pkg/autotag/image_test.go @@ -74,13 +74,7 @@ func TestImageStudios(t *testing.T) { assert := assert.New(t) - for _, test := range testTables { - mockStudioReader := &mocks.StudioReaderWriter{} - mockImageReader := &mocks.ImageReaderWriter{} - - mockStudioReader.On("QueryForAutoTag", mock.Anything).Return([]*models.Studio{&studio, &reversedStudio}, nil).Once() - mockStudioReader.On("GetAliases", mock.Anything).Return([]string{}, nil).Maybe() - + doTest := func(mockStudioReader *mocks.StudioReaderWriter, mockImageReader *mocks.ImageReaderWriter, test pathTestTable) { if test.Matches { mockImageReader.On("Find", imageID).Return(&models.Image{}, nil).Once() expectedStudioID := models.NullInt64(studioID) @@ -100,6 +94,33 @@ func TestImageStudios(t *testing.T) { mockStudioReader.AssertExpectations(t) mockImageReader.AssertExpectations(t) } + + for _, test := range testTables { + mockStudioReader := &mocks.StudioReaderWriter{} + mockImageReader := &mocks.ImageReaderWriter{} + + mockStudioReader.On("QueryForAutoTag", mock.Anything).Return([]*models.Studio{&studio, &reversedStudio}, nil).Once() + mockStudioReader.On("GetAliases", mock.Anything).Return([]string{}, nil).Maybe() + + doTest(mockStudioReader, mockImageReader, test) + } + + // test against aliases + const unmatchedName = "unmatched" + studio.Name.String = unmatchedName + + for _, test := range testTables { + mockStudioReader := &mocks.StudioReaderWriter{} + mockImageReader := &mocks.ImageReaderWriter{} + + mockStudioReader.On("QueryForAutoTag", mock.Anything).Return([]*models.Studio{&studio, &reversedStudio}, nil).Once() + mockStudioReader.On("GetAliases", studioID).Return([]string{ + studioName, + }, nil).Once() + mockStudioReader.On("GetAliases", reversedStudioID).Return([]string{}, nil).Once() + + doTest(mockStudioReader, mockImageReader, test) + } } func TestImageTags(t *testing.T) { @@ -122,12 +143,7 @@ func TestImageTags(t *testing.T) { assert := assert.New(t) - for _, test := range testTables { - mockTagReader := &mocks.TagReaderWriter{} - mockImageReader := &mocks.ImageReaderWriter{} - - mockTagReader.On("QueryForAutoTag", mock.Anything).Return([]*models.Tag{&tag, &reversedTag}, nil).Once() - + doTest := func(mockTagReader *mocks.TagReaderWriter, mockImageReader *mocks.ImageReaderWriter, test pathTestTable) { if test.Matches { mockImageReader.On("GetTagIDs", imageID).Return(nil, nil).Once() mockImageReader.On("UpdateTags", imageID, []int{tagID}).Return(nil).Once() @@ -143,4 +159,31 @@ func TestImageTags(t *testing.T) { mockTagReader.AssertExpectations(t) mockImageReader.AssertExpectations(t) } + + for _, test := range testTables { + mockTagReader := &mocks.TagReaderWriter{} + mockImageReader := &mocks.ImageReaderWriter{} + + mockTagReader.On("QueryForAutoTag", mock.Anything).Return([]*models.Tag{&tag, &reversedTag}, nil).Once() + mockTagReader.On("GetAliases", mock.Anything).Return([]string{}, nil).Maybe() + + doTest(mockTagReader, mockImageReader, test) + } + + // test against aliases + const unmatchedName = "unmatched" + tag.Name = unmatchedName + + for _, test := range testTables { + mockTagReader := &mocks.TagReaderWriter{} + mockImageReader := &mocks.ImageReaderWriter{} + + mockTagReader.On("QueryForAutoTag", mock.Anything).Return([]*models.Tag{&tag, &reversedTag}, nil).Once() + mockTagReader.On("GetAliases", tagID).Return([]string{ + tagName, + }, nil).Once() + mockTagReader.On("GetAliases", reversedTagID).Return([]string{}, nil).Once() + + doTest(mockTagReader, mockImageReader, test) + } } diff --git a/pkg/autotag/scene_test.go b/pkg/autotag/scene_test.go index 6a76a2bbe..5afb4fa5f 100644 --- a/pkg/autotag/scene_test.go +++ b/pkg/autotag/scene_test.go @@ -207,13 +207,7 @@ func TestSceneStudios(t *testing.T) { assert := assert.New(t) - for _, test := range testTables { - mockStudioReader := &mocks.StudioReaderWriter{} - mockSceneReader := &mocks.SceneReaderWriter{} - - mockStudioReader.On("QueryForAutoTag", mock.Anything).Return([]*models.Studio{&studio, &reversedStudio}, nil).Once() - mockStudioReader.On("GetAliases", mock.Anything).Return([]string{}, nil).Maybe() - + doTest := func(mockStudioReader *mocks.StudioReaderWriter, mockSceneReader *mocks.SceneReaderWriter, test pathTestTable) { if test.Matches { mockSceneReader.On("Find", sceneID).Return(&models.Scene{}, nil).Once() expectedStudioID := models.NullInt64(studioID) @@ -233,6 +227,33 @@ func TestSceneStudios(t *testing.T) { mockStudioReader.AssertExpectations(t) mockSceneReader.AssertExpectations(t) } + + for _, test := range testTables { + mockStudioReader := &mocks.StudioReaderWriter{} + mockSceneReader := &mocks.SceneReaderWriter{} + + mockStudioReader.On("QueryForAutoTag", mock.Anything).Return([]*models.Studio{&studio, &reversedStudio}, nil).Once() + mockStudioReader.On("GetAliases", mock.Anything).Return([]string{}, nil).Maybe() + + doTest(mockStudioReader, mockSceneReader, test) + } + + const unmatchedName = "unmatched" + studio.Name.String = unmatchedName + + // test against aliases + for _, test := range testTables { + mockStudioReader := &mocks.StudioReaderWriter{} + mockSceneReader := &mocks.SceneReaderWriter{} + + mockStudioReader.On("QueryForAutoTag", mock.Anything).Return([]*models.Studio{&studio, &reversedStudio}, nil).Once() + mockStudioReader.On("GetAliases", studioID).Return([]string{ + studioName, + }, nil).Once() + mockStudioReader.On("GetAliases", reversedStudioID).Return([]string{}, nil).Once() + + doTest(mockStudioReader, mockSceneReader, test) + } } func TestSceneTags(t *testing.T) { @@ -255,12 +276,7 @@ func TestSceneTags(t *testing.T) { assert := assert.New(t) - for _, test := range testTables { - mockTagReader := &mocks.TagReaderWriter{} - mockSceneReader := &mocks.SceneReaderWriter{} - - mockTagReader.On("QueryForAutoTag", mock.Anything).Return([]*models.Tag{&tag, &reversedTag}, nil).Once() - + doTest := func(mockTagReader *mocks.TagReaderWriter, mockSceneReader *mocks.SceneReaderWriter, test pathTestTable) { if test.Matches { mockSceneReader.On("GetTagIDs", sceneID).Return(nil, nil).Once() mockSceneReader.On("UpdateTags", sceneID, []int{tagID}).Return(nil).Once() @@ -276,4 +292,31 @@ func TestSceneTags(t *testing.T) { mockTagReader.AssertExpectations(t) mockSceneReader.AssertExpectations(t) } + + for _, test := range testTables { + mockTagReader := &mocks.TagReaderWriter{} + mockSceneReader := &mocks.SceneReaderWriter{} + + mockTagReader.On("QueryForAutoTag", mock.Anything).Return([]*models.Tag{&tag, &reversedTag}, nil).Once() + mockTagReader.On("GetAliases", mock.Anything).Return([]string{}, nil).Maybe() + + doTest(mockTagReader, mockSceneReader, test) + } + + const unmatchedName = "unmatched" + tag.Name = unmatchedName + + // test against aliases + for _, test := range testTables { + mockTagReader := &mocks.TagReaderWriter{} + mockSceneReader := &mocks.SceneReaderWriter{} + + mockTagReader.On("QueryForAutoTag", mock.Anything).Return([]*models.Tag{&tag, &reversedTag}, nil).Once() + mockTagReader.On("GetAliases", tagID).Return([]string{ + tagName, + }, nil).Once() + mockTagReader.On("GetAliases", reversedTagID).Return([]string{}, nil).Once() + + doTest(mockTagReader, mockSceneReader, test) + } } diff --git a/pkg/autotag/tag.go b/pkg/autotag/tag.go index c1d2cf271..48de81417 100644 --- a/pkg/autotag/tag.go +++ b/pkg/autotag/tag.go @@ -16,9 +16,27 @@ func getMatchingTags(path string, tagReader models.TagReader) ([]*models.Tag, er } var ret []*models.Tag - for _, p := range tags { - if nameMatchesPath(p.Name, path) { - ret = append(ret, p) + for _, t := range tags { + matches := false + if nameMatchesPath(t.Name, path) { + matches = true + } + + if !matches { + aliases, err := tagReader.GetAliases(t.ID) + if err != nil { + return nil, err + } + for _, alias := range aliases { + if nameMatchesPath(alias, path) { + matches = true + break + } + } + } + + if matches { + ret = append(ret, t) } } diff --git a/pkg/manager/task_autotag.go b/pkg/manager/task_autotag.go index 669ffd7a2..60b86771b 100644 --- a/pkg/manager/task_autotag.go +++ b/pkg/manager/task_autotag.go @@ -385,9 +385,16 @@ func (t *autoTagFilesTask) makeImageFilter() *models.ImageFilterType { func (t *autoTagFilesTask) makeGalleryFilter() *models.GalleryFilterType { ret := &models.GalleryFilterType{} + or := ret sep := string(filepath.Separator) + if len(t.paths) == 0 { + ret.Path = &models.StringCriterionInput{ + Modifier: models.CriterionModifierNotNull, + } + } + for _, p := range t.paths { if !strings.HasSuffix(p, sep) { p = p + sep @@ -638,17 +645,17 @@ func (t *autoTagSceneTask) Start(wg *sync.WaitGroup) { if err := t.txnManager.WithTxn(context.TODO(), func(r models.Repository) error { if t.performers { if err := autotag.ScenePerformers(t.scene, r.Scene(), r.Performer()); err != nil { - return err + return fmt.Errorf("error tagging scene performers for %s: %v", t.scene.Path, err) } } if t.studios { if err := autotag.SceneStudios(t.scene, r.Scene(), r.Studio()); err != nil { - return err + return fmt.Errorf("error tagging scene studio for %s: %v", t.scene.Path, err) } } if t.tags { if err := autotag.SceneTags(t.scene, r.Scene(), r.Tag()); err != nil { - return err + return fmt.Errorf("error tagging scene tags for %s: %v", t.scene.Path, err) } } @@ -672,17 +679,17 @@ func (t *autoTagImageTask) Start(wg *sync.WaitGroup) { if err := t.txnManager.WithTxn(context.TODO(), func(r models.Repository) error { if t.performers { if err := autotag.ImagePerformers(t.image, r.Image(), r.Performer()); err != nil { - return err + return fmt.Errorf("error tagging image performers for %s: %v", t.image.Path, err) } } if t.studios { if err := autotag.ImageStudios(t.image, r.Image(), r.Studio()); err != nil { - return err + return fmt.Errorf("error tagging image studio for %s: %v", t.image.Path, err) } } if t.tags { if err := autotag.ImageTags(t.image, r.Image(), r.Tag()); err != nil { - return err + return fmt.Errorf("error tagging image tags for %s: %v", t.image.Path, err) } } @@ -706,17 +713,17 @@ func (t *autoTagGalleryTask) Start(wg *sync.WaitGroup) { if err := t.txnManager.WithTxn(context.TODO(), func(r models.Repository) error { if t.performers { if err := autotag.GalleryPerformers(t.gallery, r.Gallery(), r.Performer()); err != nil { - return err + return fmt.Errorf("error tagging gallery performers for %s: %v", t.gallery.Path.String, err) } } if t.studios { if err := autotag.GalleryStudios(t.gallery, r.Gallery(), r.Studio()); err != nil { - return err + return fmt.Errorf("error tagging gallery studio for %s: %v", t.gallery.Path.String, err) } } if t.tags { if err := autotag.GalleryTags(t.gallery, r.Gallery(), r.Tag()); err != nil { - return err + return fmt.Errorf("error tagging gallery tags for %s: %v", t.gallery.Path.String, err) } } diff --git a/ui/v2.5/src/components/Changelog/versions/v0100.md b/ui/v2.5/src/components/Changelog/versions/v0100.md index 87d5c44ab..3c2470b32 100644 --- a/ui/v2.5/src/components/Changelog/versions/v0100.md +++ b/ui/v2.5/src/components/Changelog/versions/v0100.md @@ -14,5 +14,6 @@ * Added sv-SE language option. ([#1691](https://github.com/stashapp/stash/pull/1691)) ### 🐛 Bug fixes +* Fix tag aliases not being matched when autotagging from the tasks page. ([#1713](https://github.com/stashapp/stash/pull/1713)) * Disabled float-on-scroll player on mobile devices. ([#1721](https://github.com/stashapp/stash/pull/1721)) * Fix Create Marker form on small devices. ([#1718](https://github.com/stashapp/stash/pull/1718)) \ No newline at end of file