mirror of
https://github.com/stashapp/stash.git
synced 2025-12-18 04:44:37 +03:00
Add Dry Run option to clean task (#1081)
This commit is contained in:
@@ -26,8 +26,8 @@ mutation MetadataAutoTag($input: AutoTagMetadataInput!) {
|
||||
metadataAutoTag(input: $input)
|
||||
}
|
||||
|
||||
mutation MetadataClean {
|
||||
metadataClean
|
||||
mutation MetadataClean($input: CleanMetadataInput!) {
|
||||
metadataClean(input: $input)
|
||||
}
|
||||
|
||||
mutation MigrateHashNaming {
|
||||
|
||||
@@ -213,7 +213,7 @@ type Mutation {
|
||||
"""Start auto-tagging. Returns the job ID"""
|
||||
metadataAutoTag(input: AutoTagMetadataInput!): String!
|
||||
"""Clean metadata. Returns the job ID"""
|
||||
metadataClean: String!
|
||||
metadataClean(input: CleanMetadataInput!): String!
|
||||
"""Migrate generated files for the current hash naming"""
|
||||
migrateHashNaming: String!
|
||||
|
||||
|
||||
@@ -44,6 +44,11 @@ input ScanMetadataInput {
|
||||
scanGenerateSprites: Boolean!
|
||||
}
|
||||
|
||||
input CleanMetadataInput {
|
||||
"""Do a dry run. Don't delete any files"""
|
||||
dryRun: Boolean!
|
||||
}
|
||||
|
||||
input AutoTagMetadataInput {
|
||||
"""IDs of performers to tag files with, or "*" for all"""
|
||||
performers: [String!]
|
||||
@@ -95,4 +100,4 @@ input ImportObjectsInput {
|
||||
|
||||
input BackupDatabaseInput {
|
||||
download: Boolean
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,8 +70,8 @@ func (r *mutationResolver) MetadataAutoTag(ctx context.Context, input models.Aut
|
||||
return "todo", nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) MetadataClean(ctx context.Context) (string, error) {
|
||||
manager.GetInstance().Clean()
|
||||
func (r *mutationResolver) MetadataClean(ctx context.Context, input models.CleanMetadataInput) (string, error) {
|
||||
manager.GetInstance().Clean(input)
|
||||
return "todo", nil
|
||||
}
|
||||
|
||||
|
||||
@@ -783,7 +783,7 @@ func (s *singleton) autoTagTags(tagIds []string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *singleton) Clean() {
|
||||
func (s *singleton) Clean(input models.CleanMetadataInput) {
|
||||
if s.Status.Status != Idle {
|
||||
return
|
||||
}
|
||||
@@ -803,8 +803,13 @@ func (s *singleton) Clean() {
|
||||
gqb := r.Gallery()
|
||||
|
||||
logger.Infof("Starting cleaning of tracked files")
|
||||
if input.DryRun {
|
||||
logger.Infof("Running in Dry Mode")
|
||||
}
|
||||
var err error
|
||||
|
||||
scenes, err = qb.All()
|
||||
|
||||
if err != nil {
|
||||
return errors.New("failed to fetch list of scenes for cleaning")
|
||||
}
|
||||
@@ -853,7 +858,7 @@ func (s *singleton) Clean() {
|
||||
Scene: scene,
|
||||
fileNamingAlgorithm: fileNamingAlgo,
|
||||
}
|
||||
go task.Start(&wg)
|
||||
go task.Start(&wg, input.DryRun)
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
@@ -875,7 +880,7 @@ func (s *singleton) Clean() {
|
||||
TxnManager: s.TxnManager,
|
||||
Image: img,
|
||||
}
|
||||
go task.Start(&wg)
|
||||
go task.Start(&wg, input.DryRun)
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
@@ -897,7 +902,7 @@ func (s *singleton) Clean() {
|
||||
TxnManager: s.TxnManager,
|
||||
Gallery: gallery,
|
||||
}
|
||||
go task.Start(&wg)
|
||||
go task.Start(&wg, input.DryRun)
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
|
||||
@@ -21,18 +21,18 @@ type CleanTask struct {
|
||||
fileNamingAlgorithm models.HashAlgorithm
|
||||
}
|
||||
|
||||
func (t *CleanTask) Start(wg *sync.WaitGroup) {
|
||||
func (t *CleanTask) Start(wg *sync.WaitGroup, dryRun bool) {
|
||||
defer wg.Done()
|
||||
|
||||
if t.Scene != nil && t.shouldCleanScene(t.Scene) {
|
||||
if t.Scene != nil && t.shouldCleanScene(t.Scene) && !dryRun {
|
||||
t.deleteScene(t.Scene.ID)
|
||||
}
|
||||
|
||||
if t.Gallery != nil && t.shouldCleanGallery(t.Gallery) {
|
||||
if t.Gallery != nil && t.shouldCleanGallery(t.Gallery) && !dryRun {
|
||||
t.deleteGallery(t.Gallery.ID)
|
||||
}
|
||||
|
||||
if t.Image != nil && t.shouldCleanImage(t.Image) {
|
||||
if t.Image != nil && t.shouldCleanImage(t.Image) && !dryRun {
|
||||
t.deleteImage(t.Image.ID)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* Allow configuration of visible navbar items.
|
||||
|
||||
### 🎨 Improvements
|
||||
* Add dry-run option for Clean task.
|
||||
* Refresh UI when changing custom CSS options.
|
||||
* Add batch deleting of performers, tags, studios, and movies.
|
||||
* Reset cache after scan/clean to ensure scenes are updated.
|
||||
|
||||
@@ -41,6 +41,7 @@ export const SettingsTasksPanel: React.FC = () => {
|
||||
const [scanGenerateSprites, setScanGenerateSprites] = useState<boolean>(
|
||||
false
|
||||
);
|
||||
const [cleanDryRun, setCleanDryRun] = useState<boolean>(false);
|
||||
const [
|
||||
scanGenerateImagePreviews,
|
||||
setScanGenerateImagePreviews,
|
||||
@@ -132,12 +133,31 @@ export const SettingsTasksPanel: React.FC = () => {
|
||||
|
||||
function onClean() {
|
||||
setIsCleanAlertOpen(false);
|
||||
mutateMetadataClean().then(() => {
|
||||
mutateMetadataClean({
|
||||
dryRun: cleanDryRun,
|
||||
}).then(() => {
|
||||
jobStatus.refetch();
|
||||
});
|
||||
}
|
||||
|
||||
function renderCleanAlert() {
|
||||
let msg;
|
||||
if (cleanDryRun) {
|
||||
msg = (
|
||||
<p>
|
||||
Dry Mode selected. No actual deleting will take place, only logging.
|
||||
</p>
|
||||
);
|
||||
} else {
|
||||
msg = (
|
||||
<p>
|
||||
Are you sure you want to Clean? This will delete database information
|
||||
and generated content for all scenes and galleries that are no longer
|
||||
found in the filesystem.
|
||||
</p>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
show={isCleanAlertOpen}
|
||||
@@ -145,11 +165,7 @@ export const SettingsTasksPanel: React.FC = () => {
|
||||
accept={{ text: "Clean", variant: "danger", onClick: onClean }}
|
||||
cancel={{ onClick: () => setIsCleanAlertOpen(false) }}
|
||||
>
|
||||
<p>
|
||||
Are you sure you want to Clean? This will delete database information
|
||||
and generated content for all scenes and galleries that are no longer
|
||||
found in the filesystem.
|
||||
</p>
|
||||
{msg}
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
@@ -442,6 +458,17 @@ export const SettingsTasksPanel: React.FC = () => {
|
||||
|
||||
<h5>Generated Content</h5>
|
||||
<GenerateButton />
|
||||
|
||||
<hr />
|
||||
<h5>Maintenance</h5>
|
||||
<Form.Group>
|
||||
<Form.Check
|
||||
id="clean-dryrun"
|
||||
checked={cleanDryRun}
|
||||
label="Only perform a dry run. Don't remove anything"
|
||||
onChange={() => setCleanDryRun(!cleanDryRun)}
|
||||
/>
|
||||
</Form.Group>
|
||||
<Form.Group>
|
||||
<Button
|
||||
id="clean"
|
||||
|
||||
@@ -826,9 +826,10 @@ export const mutateMetadataGenerate = (input: GQL.GenerateMetadataInput) =>
|
||||
variables: { input },
|
||||
});
|
||||
|
||||
export const mutateMetadataClean = () =>
|
||||
export const mutateMetadataClean = (input: GQL.CleanMetadataInput) =>
|
||||
client.mutate<GQL.MetadataCleanMutation>({
|
||||
mutation: GQL.MetadataCleanDocument,
|
||||
variables: { input },
|
||||
});
|
||||
|
||||
export const mutateMigrateHashNaming = () =>
|
||||
|
||||
Reference in New Issue
Block a user