-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgram.cs
More file actions
150 lines (131 loc) · 6.61 KB
/
Program.cs
File metadata and controls
150 lines (131 loc) · 6.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
using System;
using System.IO;
using System.Threading.Tasks;
using DropboxEncrypedUploader.Infrastructure;
using DropboxEncrypedUploader.Services;
using DropboxEncrypedUploader.Upload;
using ICSharpCode.SharpZipLib.Zip;
namespace DropboxEncrypedUploader;
internal class Program
{
static async Task Main(string[] args)
{
try
{
// 1. Clean up old session files
Configuration.Configuration.CleanupOldSessions();
// 2. Parse and validate configuration
var config = new Configuration.Configuration(args);
// Configure ZIP encoding settings globally (once before any encryption operations)
if (config.UseEncryption)
{
ZipStrings.UseUnicode = true;
ZipStrings.CodePage = 65001; // UTF-8
}
// 2. Create services
var progress = new ConsoleProgressReporter();
var fileSystem = new FileSystemService();
var dropbox = new DropboxService(config);
var syncService = new SyncService(fileSystem, dropbox, progress, config);
var syncFacade = new SyncFacade(syncService, fileSystem, config);
var sessionPersistence = new SessionPersistenceService(config.SessionFilePath);
var sessionManager = new UploadSessionManager(dropbox, config.MaxRetries);
var encryptedUploadStrategy = new EncryptedUploadStrategy(sessionManager, progress, config, sessionPersistence);
var directUploadStrategy = new DirectUploadStrategy(sessionManager, progress, sessionPersistence);
var recyclingService = new StorageRecyclingService(dropbox, progress, config);
using (dropbox)
{
// 3. Create Dropbox folder
await dropbox.CreateFolderAsync(config.DropboxDirectory);
// 4. Analyze sync
var syncResult = await syncFacade.AnalyzeSyncAsync();
// 4.5. Prioritize resuming active upload session
var savedSession = sessionPersistence.LoadSession();
if (savedSession != null && syncResult.FilesToUpload.Count > 0)
{
// Find the file with active session in the upload queue
int sessionFileIndex = syncResult.FilesToUpload.FindIndex(f =>
string.Equals(f.FullPath, savedSession.FilePath, StringComparison.OrdinalIgnoreCase));
if (sessionFileIndex > 0)
{
// Move the file to the front of the queue
var fileToResume = syncResult.FilesToUpload[sessionFileIndex];
syncResult.FilesToUpload.RemoveAt(sessionFileIndex);
syncResult.FilesToUpload.Insert(0, fileToResume);
progress.ReportMessage($"Prioritizing resume of {fileToResume.RelativePath} (session found)");
}
else if (sessionFileIndex == -1)
{
// Session file is no longer in the upload queue (might have been deleted or modified)
progress.ReportMessage($"Session file no longer needs upload, clearing session");
sessionPersistence.DeleteSession();
}
// If sessionFileIndex == 0, file is already at the front, no action needed
}
// 5. Delete files that no longer exist locally
if (syncResult.FilesToDelete.Count > 0)
{
progress.ReportMessage($"Deleting files: \n{string.Join("\n", syncResult.FilesToDelete)}");
await dropbox.DeleteBatchAsync(syncResult.FilesToDelete);
}
// 6. Upload new/modified files
if (syncResult.FilesToUpload.Count > 0)
{
progress.ReportFileCount(syncResult.FilesToUpload.Count);
using var reader = new AsyncMultiFileReader(
config.ReadBufferSize,
(f, t) => new FileStream(
f,
FileMode.Open,
FileAccess.Read,
FileShare.Read,
config.ReadBufferSize,
useAsync: true));
// Select strategy based on encryption setting
IUploadStrategy strategy = config.UseEncryption
? encryptedUploadStrategy
: directUploadStrategy;
for (int i = 0; i < syncResult.FilesToUpload.Count; i++)
{
var fileToUpload = syncResult.FilesToUpload[i];
for (int attempt = 0;; attempt++)
{
try
{
reader.NextFile = (fileToUpload.FullPath, null);
reader.OpenNextFile();
if (i < syncResult.FilesToUpload.Count - 1)
reader.NextFile = (syncResult.FilesToUpload[i + 1].FullPath, null);
await strategy.UploadFileAsync(fileToUpload, reader);
break;
}
catch (ResumeFailedException ex)
{
progress.ReportMessage($"Resume upload failed, retrying from scratch: {ex.Message}");
sessionPersistence.DeleteSession();
}
catch (Exception ex) when (attempt < 2)
{
progress.ReportMessage($"Upload failed, retrying: {ex.Message}");
await Task.Delay(5000);
}
}
}
}
// 7. Recycle deleted files
progress.ReportMessage("Recycling deleted files for endless storage");
var deletedFiles = await recyclingService.ListRecyclableDeletedFilesAsync(
syncResult.ExistingFiles,
syncResult.ExistingFolders);
await recyclingService.RestoreAndDeleteFilesAsync(deletedFiles);
}
progress.ReportMessage("All done");
}
catch (Exception e)
{
// Redirecting error to normal output
Console.WriteLine(e);
throw;
}
}
}