feat(purge): add domain entity, ports, and use case
- commit
- d86a9a19edadc32961a01d905c7f8a7a9f2e89b8
- author
- brice · · 2025-12-22 06:12 UTC
- parent
- 03f2d9a
- signature
- unsigned
4 files · +245 -0
A internal/application/port/filesystem.go +11 -0
| @@ -0,0 +1,11 @@ | |||
| 1 | + | package port | |
| 2 | + | ||
| 3 | + | import "context" | |
| 4 | + | ||
| 5 | + | // FileSystem provides file system operations for the application layer. | |
| 6 | + | type FileSystem interface { | |
| 7 | + | Exists(ctx context.Context, path string) (bool, error) | |
| 8 | + | IsDirectory(ctx context.Context, path string) (bool, error) | |
| 9 | + | GetSize(ctx context.Context, path string) (int64, error) | |
| 10 | + | RemoveAll(ctx context.Context, path string) error | |
| 11 | + | } | |
| @@ -0,0 +1,11 @@ | |||||
| 1 | + | package port | |||
| 2 | + | ||||
| 3 | + | import "context" | |||
| 4 | + | ||||
| 5 | + | // FileSystem provides file system operations for the application layer. | |||
| 6 | + | type FileSystem interface { | |||
| 7 | + | Exists(ctx context.Context, path string) (bool, error) | |||
| 8 | + | IsDirectory(ctx context.Context, path string) (bool, error) | |||
| 9 | + | GetSize(ctx context.Context, path string) (int64, error) | |||
| 10 | + | RemoveAll(ctx context.Context, path string) error | |||
| 11 | + | } | |||
A internal/application/port/xdg.go +13 -0
| @@ -0,0 +1,13 @@ | |||
| 1 | + | package port | |
| 2 | + | ||
| 3 | + | // XDGPaths provides XDG Base Directory paths. | |
| 4 | + | type XDGPaths interface { | |
| 5 | + | ConfigDir() (string, error) | |
| 6 | + | DataDir() (string, error) | |
| 7 | + | StateDir() (string, error) | |
| 8 | + | CacheDir() (string, error) | |
| 9 | + | ||
| 10 | + | FilterJSONDir() (string, error) | |
| 11 | + | FilterStoreDir() (string, error) | |
| 12 | + | FilterCacheDir() (string, error) | |
| 13 | + | } | |
| @@ -0,0 +1,13 @@ | |||||
| 1 | + | package port | |||
| 2 | + | ||||
| 3 | + | // XDGPaths provides XDG Base Directory paths. | |||
| 4 | + | type XDGPaths interface { | |||
| 5 | + | ConfigDir() (string, error) | |||
| 6 | + | DataDir() (string, error) | |||
| 7 | + | StateDir() (string, error) | |||
| 8 | + | CacheDir() (string, error) | |||
| 9 | + | ||||
| 10 | + | FilterJSONDir() (string, error) | |||
| 11 | + | FilterStoreDir() (string, error) | |||
| 12 | + | FilterCacheDir() (string, error) | |||
| 13 | + | } | |||
A internal/application/usecase/purge_data.go +189 -0
| @@ -0,0 +1,189 @@ | |||
| 1 | + | package usecase | |
| 2 | + | ||
| 3 | + | import ( | |
| 4 | + | "context" | |
| 5 | + | "fmt" | |
| 6 | + | ||
| 7 | + | "github.com/bnema/dumber/internal/application/port" | |
| 8 | + | "github.com/bnema/dumber/internal/domain/entity" | |
| 9 | + | "github.com/bnema/dumber/internal/logging" | |
| 10 | + | ) | |
| 11 | + | ||
| 12 | + | // PurgeDataUseCase handles discovering and purging application data. | |
| 13 | + | type PurgeDataUseCase struct { | |
| 14 | + | fs port.FileSystem | |
| 15 | + | xdg port.XDGPaths | |
| 16 | + | desktop port.DesktopIntegration | |
| 17 | + | } | |
| 18 | + | ||
| 19 | + | // NewPurgeDataUseCase creates a new PurgeDataUseCase. | |
| 20 | + | func NewPurgeDataUseCase(fs port.FileSystem, xdg port.XDGPaths, desktop port.DesktopIntegration) *PurgeDataUseCase { | |
| 21 | + | return &PurgeDataUseCase{fs: fs, xdg: xdg, desktop: desktop} | |
| 22 | + | } | |
| 23 | + | ||
| 24 | + | // GetPurgeTargets returns all available purge targets with their current state. | |
| 25 | + | func (uc *PurgeDataUseCase) GetPurgeTargets(ctx context.Context) ([]entity.PurgeTarget, error) { | |
| 26 | + | configDir, err := uc.xdg.ConfigDir() | |
| 27 | + | if err != nil { | |
| 28 | + | return nil, err | |
| 29 | + | } | |
| 30 | + | dataDir, err := uc.xdg.DataDir() | |
| 31 | + | if err != nil { | |
| 32 | + | return nil, err | |
| 33 | + | } | |
| 34 | + | stateDir, err := uc.xdg.StateDir() | |
| 35 | + | if err != nil { | |
| 36 | + | return nil, err | |
| 37 | + | } | |
| 38 | + | cacheDir, err := uc.xdg.CacheDir() | |
| 39 | + | if err != nil { | |
| 40 | + | return nil, err | |
| 41 | + | } | |
| 42 | + | filterJSONDir, err := uc.xdg.FilterJSONDir() | |
| 43 | + | if err != nil { | |
| 44 | + | return nil, err | |
| 45 | + | } | |
| 46 | + | filterStoreDir, err := uc.xdg.FilterStoreDir() | |
| 47 | + | if err != nil { | |
| 48 | + | return nil, err | |
| 49 | + | } | |
| 50 | + | filterCacheDir, err := uc.xdg.FilterCacheDir() | |
| 51 | + | if err != nil { | |
| 52 | + | return nil, err | |
| 53 | + | } | |
| 54 | + | ||
| 55 | + | baseTargets := []entity.PurgeTarget{ | |
| 56 | + | {Type: entity.PurgeTargetConfig, Path: configDir, Description: "config"}, | |
| 57 | + | {Type: entity.PurgeTargetData, Path: dataDir, Description: "data"}, | |
| 58 | + | {Type: entity.PurgeTargetState, Path: stateDir, Description: "state"}, | |
| 59 | + | {Type: entity.PurgeTargetCache, Path: cacheDir, Description: "cache"}, | |
| 60 | + | {Type: entity.PurgeTargetFilterJSON, Path: filterJSONDir, Description: "filter JSON cache"}, | |
| 61 | + | {Type: entity.PurgeTargetFilterStore, Path: filterStoreDir, Description: "compiled filters"}, | |
| 62 | + | {Type: entity.PurgeTargetFilterCache, Path: filterCacheDir, Description: "filter cache"}, | |
| 63 | + | } | |
| 64 | + | ||
| 65 | + | status, statusErr := uc.desktop.GetStatus(ctx) | |
| 66 | + | if statusErr != nil { | |
| 67 | + | // Desktop status should not block purge targets discovery. | |
| 68 | + | logging.FromContext(ctx).Warn().Err(statusErr).Msg("failed to get desktop integration status") | |
| 69 | + | } | |
| 70 | + | ||
| 71 | + | if status != nil { | |
| 72 | + | baseTargets = append(baseTargets, | |
| 73 | + | entity.PurgeTarget{Type: entity.PurgeTargetDesktopFile, Path: status.DesktopFilePath, Description: "desktop file"}, | |
| 74 | + | entity.PurgeTarget{Type: entity.PurgeTargetIcon, Path: status.IconFilePath, Description: "icon"}, | |
| 75 | + | ) | |
| 76 | + | } | |
| 77 | + | ||
| 78 | + | var targets []entity.PurgeTarget | |
| 79 | + | for _, t := range baseTargets { | |
| 80 | + | if t.Path == "" { | |
| 81 | + | t.Exists = false | |
| 82 | + | t.Size = 0 | |
| 83 | + | targets = append(targets, t) | |
| 84 | + | continue | |
| 85 | + | } | |
| 86 | + | exists, err := uc.fs.Exists(ctx, t.Path) | |
| 87 | + | if err != nil { | |
| 88 | + | return nil, err | |
| 89 | + | } | |
| 90 | + | t.Exists = exists | |
| 91 | + | if !exists { | |
| 92 | + | t.Size = 0 | |
| 93 | + | targets = append(targets, t) | |
| 94 | + | continue | |
| 95 | + | } | |
| 96 | + | size, err := uc.fs.GetSize(ctx, t.Path) | |
| 97 | + | if err != nil { | |
| 98 | + | return nil, err | |
| 99 | + | } | |
| 100 | + | t.Size = size | |
| 101 | + | targets = append(targets, t) | |
| 102 | + | } | |
| 103 | + | ||
| 104 | + | return targets, nil | |
| 105 | + | } | |
| 106 | + | ||
| 107 | + | // PurgeInput specifies which target types to purge. | |
| 108 | + | type PurgeInput struct { | |
| 109 | + | TargetTypes []entity.PurgeTargetType | |
| 110 | + | } | |
| 111 | + | ||
| 112 | + | // PurgeOutput contains the results of the purge operation. | |
| 113 | + | type PurgeOutput struct { | |
| 114 | + | Results []entity.PurgeResult | |
| 115 | + | TotalSize int64 | |
| 116 | + | SuccessCount int | |
| 117 | + | FailureCount int | |
| 118 | + | } | |
| 119 | + | ||
| 120 | + | // Execute purges the selected target types. | |
| 121 | + | // Continues on errors, collecting all results. | |
| 122 | + | func (uc *PurgeDataUseCase) Execute(ctx context.Context, input PurgeInput) (*PurgeOutput, error) { | |
| 123 | + | log := logging.FromContext(ctx) | |
| 124 | + | ||
| 125 | + | targets, err := uc.GetPurgeTargets(ctx) | |
| 126 | + | if err != nil { | |
| 127 | + | return nil, err | |
| 128 | + | } | |
| 129 | + | ||
| 130 | + | selected := make(map[entity.PurgeTargetType]struct{}, len(input.TargetTypes)) | |
| 131 | + | for _, tt := range input.TargetTypes { | |
| 132 | + | selected[tt] = struct{}{} | |
| 133 | + | } | |
| 134 | + | ||
| 135 | + | out := &PurgeOutput{} | |
| 136 | + | for _, t := range targets { | |
| 137 | + | if _, ok := selected[t.Type]; !ok { | |
| 138 | + | continue | |
| 139 | + | } | |
| 140 | + | if !t.Exists { | |
| 141 | + | continue | |
| 142 | + | } | |
| 143 | + | ||
| 144 | + | res := entity.PurgeResult{Target: t} | |
| 145 | + | out.TotalSize += t.Size | |
| 146 | + | ||
| 147 | + | switch t.Type { | |
| 148 | + | case entity.PurgeTargetDesktopFile: | |
| 149 | + | err = uc.desktop.RemoveDesktopFile(ctx) | |
| 150 | + | case entity.PurgeTargetIcon: | |
| 151 | + | err = uc.desktop.RemoveIcon(ctx) | |
| 152 | + | default: | |
| 153 | + | err = uc.fs.RemoveAll(ctx, t.Path) | |
| 154 | + | } | |
| 155 | + | ||
| 156 | + | if err != nil { | |
| 157 | + | res.Success = false | |
| 158 | + | res.Error = err | |
| 159 | + | out.FailureCount++ | |
| 160 | + | log.Warn().Err(err).Str("path", t.Path).Int("type", int(t.Type)).Msg("purge target failed") | |
| 161 | + | } else { | |
| 162 | + | res.Success = true | |
| 163 | + | out.SuccessCount++ | |
| 164 | + | log.Info().Str("path", t.Path).Int("type", int(t.Type)).Msg("purge target removed") | |
| 165 | + | } | |
| 166 | + | ||
| 167 | + | out.Results = append(out.Results, res) | |
| 168 | + | } | |
| 169 | + | ||
| 170 | + | if out.FailureCount > 0 { | |
| 171 | + | return out, fmt.Errorf("failed to remove %d items", out.FailureCount) | |
| 172 | + | } | |
| 173 | + | return out, nil | |
| 174 | + | } | |
| 175 | + | ||
| 176 | + | // PurgeAll purges all existing targets (for --force mode). | |
| 177 | + | func (uc *PurgeDataUseCase) PurgeAll(ctx context.Context) (*PurgeOutput, error) { | |
| 178 | + | targets, err := uc.GetPurgeTargets(ctx) | |
| 179 | + | if err != nil { | |
| 180 | + | return nil, err | |
| 181 | + | } | |
| 182 | + | ||
| 183 | + | var types []entity.PurgeTargetType | |
| 184 | + | for _, t := range targets { | |
| 185 | + | types = append(types, t.Type) | |
| 186 | + | } | |
| 187 | + | ||
| 188 | + | return uc.Execute(ctx, PurgeInput{TargetTypes: types}) | |
| 189 | + | } | |
| @@ -0,0 +1,189 @@ | |||||
| 1 | + | package usecase | |||
| 2 | + | ||||
| 3 | + | import ( | |||
| 4 | + | "context" | |||
| 5 | + | "fmt" | |||
| 6 | + | ||||
| 7 | + | "github.com/bnema/dumber/internal/application/port" | |||
| 8 | + | "github.com/bnema/dumber/internal/domain/entity" | |||
| 9 | + | "github.com/bnema/dumber/internal/logging" | |||
| 10 | + | ) | |||
| 11 | + | ||||
| 12 | + | // PurgeDataUseCase handles discovering and purging application data. | |||
| 13 | + | type PurgeDataUseCase struct { | |||
| 14 | + | fs port.FileSystem | |||
| 15 | + | xdg port.XDGPaths | |||
| 16 | + | desktop port.DesktopIntegration | |||
| 17 | + | } | |||
| 18 | + | ||||
| 19 | + | // NewPurgeDataUseCase creates a new PurgeDataUseCase. | |||
| 20 | + | func NewPurgeDataUseCase(fs port.FileSystem, xdg port.XDGPaths, desktop port.DesktopIntegration) *PurgeDataUseCase { | |||
| 21 | + | return &PurgeDataUseCase{fs: fs, xdg: xdg, desktop: desktop} | |||
| 22 | + | } | |||
| 23 | + | ||||
| 24 | + | // GetPurgeTargets returns all available purge targets with their current state. | |||
| 25 | + | func (uc *PurgeDataUseCase) GetPurgeTargets(ctx context.Context) ([]entity.PurgeTarget, error) { | |||
| 26 | + | configDir, err := uc.xdg.ConfigDir() | |||
| 27 | + | if err != nil { | |||
| 28 | + | return nil, err | |||
| 29 | + | } | |||
| 30 | + | dataDir, err := uc.xdg.DataDir() | |||
| 31 | + | if err != nil { | |||
| 32 | + | return nil, err | |||
| 33 | + | } | |||
| 34 | + | stateDir, err := uc.xdg.StateDir() | |||
| 35 | + | if err != nil { | |||
| 36 | + | return nil, err | |||
| 37 | + | } | |||
| 38 | + | cacheDir, err := uc.xdg.CacheDir() | |||
| 39 | + | if err != nil { | |||
| 40 | + | return nil, err | |||
| 41 | + | } | |||
| 42 | + | filterJSONDir, err := uc.xdg.FilterJSONDir() | |||
| 43 | + | if err != nil { | |||
| 44 | + | return nil, err | |||
| 45 | + | } | |||
| 46 | + | filterStoreDir, err := uc.xdg.FilterStoreDir() | |||
| 47 | + | if err != nil { | |||
| 48 | + | return nil, err | |||
| 49 | + | } | |||
| 50 | + | filterCacheDir, err := uc.xdg.FilterCacheDir() | |||
| 51 | + | if err != nil { | |||
| 52 | + | return nil, err | |||
| 53 | + | } | |||
| 54 | + | ||||
| 55 | + | baseTargets := []entity.PurgeTarget{ | |||
| 56 | + | {Type: entity.PurgeTargetConfig, Path: configDir, Description: "config"}, | |||
| 57 | + | {Type: entity.PurgeTargetData, Path: dataDir, Description: "data"}, | |||
| 58 | + | {Type: entity.PurgeTargetState, Path: stateDir, Description: "state"}, | |||
| 59 | + | {Type: entity.PurgeTargetCache, Path: cacheDir, Description: "cache"}, | |||
| 60 | + | {Type: entity.PurgeTargetFilterJSON, Path: filterJSONDir, Description: "filter JSON cache"}, | |||
| 61 | + | {Type: entity.PurgeTargetFilterStore, Path: filterStoreDir, Description: "compiled filters"}, | |||
| 62 | + | {Type: entity.PurgeTargetFilterCache, Path: filterCacheDir, Description: "filter cache"}, | |||
| 63 | + | } | |||
| 64 | + | ||||
| 65 | + | status, statusErr := uc.desktop.GetStatus(ctx) | |||
| 66 | + | if statusErr != nil { | |||
| 67 | + | // Desktop status should not block purge targets discovery. | |||
| 68 | + | logging.FromContext(ctx).Warn().Err(statusErr).Msg("failed to get desktop integration status") | |||
| 69 | + | } | |||
| 70 | + | ||||
| 71 | + | if status != nil { | |||
| 72 | + | baseTargets = append(baseTargets, | |||
| 73 | + | entity.PurgeTarget{Type: entity.PurgeTargetDesktopFile, Path: status.DesktopFilePath, Description: "desktop file"}, | |||
| 74 | + | entity.PurgeTarget{Type: entity.PurgeTargetIcon, Path: status.IconFilePath, Description: "icon"}, | |||
| 75 | + | ) | |||
| 76 | + | } | |||
| 77 | + | ||||
| 78 | + | var targets []entity.PurgeTarget | |||
| 79 | + | for _, t := range baseTargets { | |||
| 80 | + | if t.Path == "" { | |||
| 81 | + | t.Exists = false | |||
| 82 | + | t.Size = 0 | |||
| 83 | + | targets = append(targets, t) | |||
| 84 | + | continue | |||
| 85 | + | } | |||
| 86 | + | exists, err := uc.fs.Exists(ctx, t.Path) | |||
| 87 | + | if err != nil { | |||
| 88 | + | return nil, err | |||
| 89 | + | } | |||
| 90 | + | t.Exists = exists | |||
| 91 | + | if !exists { | |||
| 92 | + | t.Size = 0 | |||
| 93 | + | targets = append(targets, t) | |||
| 94 | + | continue | |||
| 95 | + | } | |||
| 96 | + | size, err := uc.fs.GetSize(ctx, t.Path) | |||
| 97 | + | if err != nil { | |||
| 98 | + | return nil, err | |||
| 99 | + | } | |||
| 100 | + | t.Size = size | |||
| 101 | + | targets = append(targets, t) | |||
| 102 | + | } | |||
| 103 | + | ||||
| 104 | + | return targets, nil | |||
| 105 | + | } | |||
| 106 | + | ||||
| 107 | + | // PurgeInput specifies which target types to purge. | |||
| 108 | + | type PurgeInput struct { | |||
| 109 | + | TargetTypes []entity.PurgeTargetType | |||
| 110 | + | } | |||
| 111 | + | ||||
| 112 | + | // PurgeOutput contains the results of the purge operation. | |||
| 113 | + | type PurgeOutput struct { | |||
| 114 | + | Results []entity.PurgeResult | |||
| 115 | + | TotalSize int64 | |||
| 116 | + | SuccessCount int | |||
| 117 | + | FailureCount int | |||
| 118 | + | } | |||
| 119 | + | ||||
| 120 | + | // Execute purges the selected target types. | |||
| 121 | + | // Continues on errors, collecting all results. | |||
| 122 | + | func (uc *PurgeDataUseCase) Execute(ctx context.Context, input PurgeInput) (*PurgeOutput, error) { | |||
| 123 | + | log := logging.FromContext(ctx) | |||
| 124 | + | ||||
| 125 | + | targets, err := uc.GetPurgeTargets(ctx) | |||
| 126 | + | if err != nil { | |||
| 127 | + | return nil, err | |||
| 128 | + | } | |||
| 129 | + | ||||
| 130 | + | selected := make(map[entity.PurgeTargetType]struct{}, len(input.TargetTypes)) | |||
| 131 | + | for _, tt := range input.TargetTypes { | |||
| 132 | + | selected[tt] = struct{}{} | |||
| 133 | + | } | |||
| 134 | + | ||||
| 135 | + | out := &PurgeOutput{} | |||
| 136 | + | for _, t := range targets { | |||
| 137 | + | if _, ok := selected[t.Type]; !ok { | |||
| 138 | + | continue | |||
| 139 | + | } | |||
| 140 | + | if !t.Exists { | |||
| 141 | + | continue | |||
| 142 | + | } | |||
| 143 | + | ||||
| 144 | + | res := entity.PurgeResult{Target: t} | |||
| 145 | + | out.TotalSize += t.Size | |||
| 146 | + | ||||
| 147 | + | switch t.Type { | |||
| 148 | + | case entity.PurgeTargetDesktopFile: | |||
| 149 | + | err = uc.desktop.RemoveDesktopFile(ctx) | |||
| 150 | + | case entity.PurgeTargetIcon: | |||
| 151 | + | err = uc.desktop.RemoveIcon(ctx) | |||
| 152 | + | default: | |||
| 153 | + | err = uc.fs.RemoveAll(ctx, t.Path) | |||
| 154 | + | } | |||
| 155 | + | ||||
| 156 | + | if err != nil { | |||
| 157 | + | res.Success = false | |||
| 158 | + | res.Error = err | |||
| 159 | + | out.FailureCount++ | |||
| 160 | + | log.Warn().Err(err).Str("path", t.Path).Int("type", int(t.Type)).Msg("purge target failed") | |||
| 161 | + | } else { | |||
| 162 | + | res.Success = true | |||
| 163 | + | out.SuccessCount++ | |||
| 164 | + | log.Info().Str("path", t.Path).Int("type", int(t.Type)).Msg("purge target removed") | |||
| 165 | + | } | |||
| 166 | + | ||||
| 167 | + | out.Results = append(out.Results, res) | |||
| 168 | + | } | |||
| 169 | + | ||||
| 170 | + | if out.FailureCount > 0 { | |||
| 171 | + | return out, fmt.Errorf("failed to remove %d items", out.FailureCount) | |||
| 172 | + | } | |||
| 173 | + | return out, nil | |||
| 174 | + | } | |||
| 175 | + | ||||
| 176 | + | // PurgeAll purges all existing targets (for --force mode). | |||
| 177 | + | func (uc *PurgeDataUseCase) PurgeAll(ctx context.Context) (*PurgeOutput, error) { | |||
| 178 | + | targets, err := uc.GetPurgeTargets(ctx) | |||
| 179 | + | if err != nil { | |||
| 180 | + | return nil, err | |||
| 181 | + | } | |||
| 182 | + | ||||
| 183 | + | var types []entity.PurgeTargetType | |||
| 184 | + | for _, t := range targets { | |||
| 185 | + | types = append(types, t.Type) | |||
| 186 | + | } | |||
| 187 | + | ||||
| 188 | + | return uc.Execute(ctx, PurgeInput{TargetTypes: types}) | |||
| 189 | + | } | |||
A internal/domain/entity/purge.go +32 -0
| @@ -0,0 +1,32 @@ | |||
| 1 | + | package entity | |
| 2 | + | ||
| 3 | + | // PurgeTargetType identifies what kind of purgeable item this is. | |
| 4 | + | type PurgeTargetType int | |
| 5 | + | ||
| 6 | + | const ( | |
| 7 | + | PurgeTargetConfig PurgeTargetType = iota | |
| 8 | + | PurgeTargetData | |
| 9 | + | PurgeTargetState | |
| 10 | + | PurgeTargetCache | |
| 11 | + | PurgeTargetFilterJSON | |
| 12 | + | PurgeTargetFilterStore | |
| 13 | + | PurgeTargetFilterCache | |
| 14 | + | PurgeTargetDesktopFile | |
| 15 | + | PurgeTargetIcon | |
| 16 | + | ) | |
| 17 | + | ||
| 18 | + | // PurgeTarget represents something that can be purged. | |
| 19 | + | type PurgeTarget struct { | |
| 20 | + | Type PurgeTargetType | |
| 21 | + | Path string | |
| 22 | + | Description string | |
| 23 | + | Size int64 | |
| 24 | + | Exists bool | |
| 25 | + | } | |
| 26 | + | ||
| 27 | + | // PurgeResult represents the outcome of purging a single target. | |
| 28 | + | type PurgeResult struct { | |
| 29 | + | Target PurgeTarget | |
| 30 | + | Success bool | |
| 31 | + | Error error | |
| 32 | + | } | |
| @@ -0,0 +1,32 @@ | |||||
| 1 | + | package entity | |||
| 2 | + | ||||
| 3 | + | // PurgeTargetType identifies what kind of purgeable item this is. | |||
| 4 | + | type PurgeTargetType int | |||
| 5 | + | ||||
| 6 | + | const ( | |||
| 7 | + | PurgeTargetConfig PurgeTargetType = iota | |||
| 8 | + | PurgeTargetData | |||
| 9 | + | PurgeTargetState | |||
| 10 | + | PurgeTargetCache | |||
| 11 | + | PurgeTargetFilterJSON | |||
| 12 | + | PurgeTargetFilterStore | |||
| 13 | + | PurgeTargetFilterCache | |||
| 14 | + | PurgeTargetDesktopFile | |||
| 15 | + | PurgeTargetIcon | |||
| 16 | + | ) | |||
| 17 | + | ||||
| 18 | + | // PurgeTarget represents something that can be purged. | |||
| 19 | + | type PurgeTarget struct { | |||
| 20 | + | Type PurgeTargetType | |||
| 21 | + | Path string | |||
| 22 | + | Description string | |||
| 23 | + | Size int64 | |||
| 24 | + | Exists bool | |||
| 25 | + | } | |||
| 26 | + | ||||
| 27 | + | // PurgeResult represents the outcome of purging a single target. | |||
| 28 | + | type PurgeResult struct { | |||
| 29 | + | Target PurgeTarget | |||
| 30 | + | Success bool | |||
| 31 | + | Error error | |||
| 32 | + | } | |||