@@ -7,12 +7,10 @@ import eu.darken.butler.common.debug.logging.logTag
77import eu.darken.butler.common.files.LocalPath
88import eu.darken.butler.common.files.actions.DeleteAction
99import eu.darken.butler.common.files.actions.PathActionIssue
10- import eu.darken.butler.common.files.errors.ReadException
1110import eu.darken.butler.common.files.errors.WriteException
1211import eu.darken.butler.common.files.metadata.FileType
1312import eu.darken.butler.common.io.R
1413import kotlinx.coroutines.currentCoroutineContext
15- import kotlinx.coroutines.delay
1614import kotlinx.coroutines.isActive
1715import java.io.IOException
1816import java.nio.file.Files
@@ -41,19 +39,16 @@ suspend fun Collection<LocalPath>.delete(
4139 val deleted = linkedSetOf<LocalPathLookup >()
4240 var bytesTotal = 0L
4341
44- // Apply-to-all state management
45- var skipAllPermissionIssues = false
42+ var issueSkippAllPermission = false
43+ var issueSkippAllUnknown = false
4644
47- // Process each original target separately for cleaner progress tracking
4845 this .forEachIndexed { index, currentTopLevel ->
4946 log(TAG , VERBOSE ) { " delete(): Processing target ${index + 1 } /${this .size} : $currentTopLevel " }
5047
51- // Collect all items for this specific target
5248 val toVisit = ArrayDeque <LocalPath >().apply { add(currentTopLevel) }
5349 val files = ArrayDeque <LocalPathLookup >()
5450 val dirsPost = ArrayDeque <LocalPathLookup >()
5551
56- // Traverse this target's tree
5752 while (toVisit.isNotEmpty() && currentCoroutineContext().isActive) {
5853 val localPath = toVisit.removeFirst()
5954 val lookup = localPath.performLookup()
@@ -89,7 +84,6 @@ suspend fun Collection<LocalPath>.delete(
8984 suspend fun tryDelete (target : LocalPathLookup ) {
9085 while (currentCoroutineContext().isActive) {
9186 try {
92-
9387 onProgress?.invoke(
9488 DeleteAction .State .Progress (
9589 target = target,
@@ -120,92 +114,73 @@ suspend fun Collection<LocalPath>.delete(
120114 } else null
121115 )
122116 )
123- delay(50 ) // FIXME Just for testing
124- // Files.delete(target.file.toPath()) // FIXME Just for testing.
117+ Files .delete(target.lookedUp.file.toPath())
125118 bytesTotal + = size
126119 deleted + = target
127120 itemsProcessed++
128121 break
129- } catch (e: NoSuchFileException ) {
130- log(TAG , WARN ) { " delete(): File doesn't exist: $target " }
131- if (ignoreMissing) break else throw ReadException (path = target.lookedUp, cause = e)
132-
133122 } catch (securityError: SecurityException ) {
134123 log(TAG , ERROR ) { " delete(): Security exception on $target : $securityError " }
135124
136- if (skipAllPermissionIssues ) {
125+ if (issueSkippAllPermission ) {
137126 log(TAG , INFO ) { " Skipping permission issue (apply-to-all): $target " }
138127 break
139128 }
140129
141130 val deleteError = WriteException (path = target.lookedUp, cause = securityError)
142-
143131 if (onIssue == null ) throw deleteError
144132
145- val issue = try {
146- PathActionIssue .InsufficientPermission (
147- destination = target,
148- exception = deleteError,
149- )
150- } catch (e: Exception ) {
151- PathActionIssue .UnknownError (exception = e)
152- }
133+ val issue = PathActionIssue .InsufficientPermission (
134+ destination = target,
135+ exception = deleteError,
136+ )
153137
154- val resolution = onIssue.invoke(issue)
155- when (issue) {
156- is PathActionIssue .InsufficientPermission -> {
157- val permissionResolution = resolution as PathActionIssue .InsufficientPermission .Resolution
158- when (permissionResolution) {
159- is PathActionIssue .InsufficientPermission .Resolution .Cancel -> throw CancellationException (
160- " User cancelled" ,
161- deleteError
162- )
163- is PathActionIssue .InsufficientPermission .Resolution .Skip -> {
164- if (permissionResolution.applyToAll) skipAllPermissionIssues = true
165- break
166- }
167- }
168- }
169- is PathActionIssue .UnknownError -> {
170- val unknownResolution = resolution as PathActionIssue .UnknownError .Resolution
171- when (unknownResolution) {
172- is PathActionIssue .UnknownError .Resolution .Cancel -> throw CancellationException (
173- " User cancelled" ,
174- deleteError
175- )
176- is PathActionIssue .UnknownError .Resolution .Retry -> continue
177- is PathActionIssue .UnknownError .Resolution .Skip -> break
178- }
138+ when (val resolution = onIssue.invoke(issue) as PathActionIssue .InsufficientPermission .Resolution ) {
139+ is PathActionIssue .InsufficientPermission .Resolution .Cancel -> throw CancellationException (
140+ " User cancelled" ,
141+ deleteError
142+ )
143+ is PathActionIssue .InsufficientPermission .Resolution .Skip -> {
144+ if (resolution.applyToAll) issueSkippAllPermission = true
145+ break
179146 }
180- else -> throw IllegalStateException (" Unexpected issue type: $issue " )
181147 }
182148 } catch (deleteError: Exception ) {
183149 log(TAG , ERROR ) { " delete(): Failed to delete $target : $deleteError " }
184- if (onIssue == null ) throw deleteError
185150
186- val issue = try {
187- PathActionIssue .UnknownError (
188- destination = target,
189- exception = deleteError
190- )
191- } catch (e: Exception ) {
192- PathActionIssue .UnknownError (exception = e)
151+ if (issueSkippAllUnknown) {
152+ log(TAG , INFO ) { " Skipping unknown issue (apply-to-all): $target " }
153+ break
154+ }
155+
156+ if (deleteError is NoSuchFileException ) {
157+ log(TAG , WARN ) { " delete(): File doesn't exist: $target " }
158+ if (ignoreMissing) break
193159 }
194160
195- val resolution = onIssue.invoke(issue) as PathActionIssue .UnknownError .Resolution
196- when (resolution) {
161+ val deleteError = WriteException (path = target.lookedUp, cause = deleteError)
162+ if (onIssue == null ) throw deleteError
163+
164+ val issue = PathActionIssue .UnknownError (
165+ destination = target,
166+ exception = deleteError
167+ )
168+
169+ when (val resolution = onIssue.invoke(issue) as PathActionIssue .UnknownError .Resolution ) {
197170 is PathActionIssue .UnknownError .Resolution .Cancel -> throw CancellationException (
198171 " User cancelled" ,
199172 deleteError
200173 )
201174 is PathActionIssue .UnknownError .Resolution .Retry -> continue
202- is PathActionIssue .UnknownError .Resolution .Skip -> break
175+ is PathActionIssue .UnknownError .Resolution .Skip -> {
176+ if (resolution.applyToAll) issueSkippAllUnknown = true
177+ break
178+ }
203179 }
204180 }
205181 }
206182 }
207183
208- // Delete files and directories for this target
209184 log(TAG , VERBOSE ) { " delete(): Deleting ${files.size} files for target: $currentTopLevel " }
210185 for (localPath in files) tryDelete(localPath)
211186
0 commit comments