• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ParadoxGameConverters / Fronter.NET / 25262018293

02 May 2026 09:13PM UTC coverage: 26.674% (+0.7%) from 25.99%
25262018293

push

github

web-flow
Fix a failure to copy a mod to a OneDrive-synced folder (#976)

173 of 778 branches covered (22.24%)

Branch coverage included in aggregate %.

27 of 32 new or added lines in 3 files covered. (84.38%)

767 of 2746 relevant lines covered (27.93%)

5.13 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.47
/Fronter.NET/Services/FileSystemHelper.cs
1
using System;
2
using System.IO;
3

4
namespace Fronter.Services;
5

6
/// <summary>
7
/// Filesystem helpers that handle edge cases such as OneDrive-backed paths
8
/// where cloud-sync clients set blocking attributes on entries that prevent
9
/// standard recursive deletion.
10
/// </summary>
11
internal static class FileSystemHelper {
12
        /// <summary>
13
        /// Attempts to delete a directory and all its contents.
14
        /// When the standard delete fails with an access or IO error (common on
15
        /// OneDrive-backed folders because of ReadOnly attributes set by the sync
16
        /// client), falls back to clearing all blocking attributes on every entry
17
        /// in the tree before retrying.
18
        /// </summary>
19
        /// <returns>True if the folder was deleted or did not exist, false otherwise.</returns>
20
        internal static bool TryDeleteFolder(string folderPath) {
4✔
21
                if (!Directory.Exists(folderPath)) {
5✔
22
                        return true;
1✔
23
                }
24

25
                try {
3✔
26
                        Directory.Delete(folderPath, recursive: true);
3✔
27
                        return true;
2✔
28
                } catch (Exception e) when (e is IOException or UnauthorizedAccessException) {
2✔
29
                        // OneDrive and similar cloud-sync clients can set ReadOnly (and other blocking)
30
                        // attributes on files and directories, causing Directory.Delete to fail with
31
                        // access-denied. Clear all attributes in the tree and retry.
32
                        return TryDeleteFolderWithAttributeReset(folderPath);
1✔
33
                }
34
        }
4✔
35

36
        private static bool TryDeleteFolderWithAttributeReset(string folderPath) {
1✔
37
                try {
1✔
38
                        ResetAttributesRecursive(new DirectoryInfo(folderPath));
1✔
39
                        Directory.Delete(folderPath, recursive: true);
1✔
40
                        return true;
1✔
NEW
41
                } catch {
×
NEW
42
                        return false;
×
43
                }
44
        }
1✔
45

46
        private static void ResetAttributesRecursive(DirectoryInfo directory) {
6✔
47
                // Clear blocking attributes on the directory itself.
48
                directory.Attributes &= ~FileAttributes.ReadOnly;
6✔
49

50
                foreach (FileInfo file in directory.EnumerateFiles()) {
21✔
51
                        file.IsReadOnly = false;
1✔
52
                }
1✔
53

54
                foreach (DirectoryInfo subDir in directory.EnumerateDirectories()) {
33✔
55
                        // Reparse points (junctions, symlinks) should be deleted as directory entries
56
                        // rather than traversed — we must not recurse into what they point at.
57
                        if (subDir.Attributes.HasFlag(FileAttributes.ReparsePoint)) {
5!
NEW
58
                                Directory.Delete(subDir.FullName);
×
59
                        } else {
5✔
60
                                ResetAttributesRecursive(subDir);
5✔
61
                        }
5✔
62
                }
5✔
63
        }
6✔
64
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc