this repo has no description
1import Foundation
2
3/// Utilities for discovering and managing backup directories
4struct BackupDiscovery {
5 /// Get the main backups directory (Documents/backups/)
6 static func backupsDirectory() throws -> URL {
7 guard
8 let documentsDirectory = FileManager.default.urls(
9 for: .documentDirectory, in: .userDomainMask
10 ).first
11 else {
12 throw BackupError.documentsDirectoryNotFound
13 }
14 return documentsDirectory.appendingPathComponent("backups")
15 }
16
17 /// Get the backup directory for a specific account DID
18 static func accountBackupDirectory(for did: String) throws -> URL {
19 try backupsDirectory().appendingPathComponent(did)
20 }
21
22 /// Discover all backed up account DIDs by scanning the backups directory
23 static func discoverBackedUpAccounts() throws -> [DiscoveredAccount] {
24 let backupsDir = try backupsDirectory()
25
26 guard FileManager.default.fileExists(atPath: backupsDir.path) else {
27 return []
28 }
29
30 let contents = try FileManager.default.contentsOfDirectory(
31 at: backupsDir,
32 includingPropertiesForKeys: [.isDirectoryKey],
33 options: [.skipsHiddenFiles]
34 )
35
36 var discoveredAccounts: [DiscoveredAccount] = []
37
38 for url in contents {
39 // Check if it's a directory
40 guard let resourceValues = try? url.resourceValues(forKeys: [.isDirectoryKey]),
41 let isDirectory = resourceValues.isDirectory,
42 isDirectory
43 else {
44 continue
45 }
46
47 let did = url.lastPathComponent
48
49 // Try to load metadata for this DID
50 do {
51 if let metadata = try BackupMetadata.load(from: url) {
52 discoveredAccounts.append(
53 DiscoveredAccount(
54 did: metadata.did,
55 handle: metadata.handle,
56 pds: metadata.pds,
57 lastBackup: metadata.completedAt,
58 backupDirectory: url
59 ))
60 }
61 } catch {
62 print("Failed to load metadata for DID \(did): \(error)")
63 // Still add the account but without metadata
64 discoveredAccounts.append(
65 DiscoveredAccount(
66 did: did,
67 handle: nil,
68 pds: nil,
69 lastBackup: nil,
70 backupDirectory: url
71 ))
72 }
73 }
74
75 return discoveredAccounts.sorted {
76 ($0.lastBackup ?? .distantPast) > ($1.lastBackup ?? .distantPast)
77 }
78 }
79}
80
81/// Represents a discovered backup account
82struct DiscoveredAccount {
83 let did: String
84 let handle: String?
85 let pds: String?
86 let lastBackup: Date?
87 let backupDirectory: URL
88}
89
90/// Errors related to backup discovery
91enum BackupError: Error {
92 case documentsDirectoryNotFound
93 case backupDirectoryNotFound
94}