22using System . IO ;
33using Microsoft . Extensions . Configuration ;
44using System . Runtime . InteropServices ;
5+ using System . Diagnostics . CodeAnalysis ;
56
67namespace FolderSync
78{
89 public class FolderSync
910 {
11+ [ NotNull ]
1012 private static int syncPeriod ;
11- private static string sourceFolder ;
12- private static string destinationFolder ;
13+ [ NotNull ]
14+ private static string sourceRoot ;
15+ [ NotNull ]
16+ private static string backupRoot ;
17+ [ NotNull ]
1318 private static string logFilePath ;
19+ private static List < FileProps > sourceFileList ;
20+ private static List < FileProps > backupFileList ;
1421
1522 public static void Main ( string [ ] args )
1623 {
1724 IConfiguration config = new ConfigurationBuilder ( ) . AddCommandLine ( args ) . Build ( ) ;
1825 ParseArgs ( config ) ;
19- Sync ( ) ;
26+ InitalSync ( ) ;
27+ // Sync();
2028 }
2129
2230 private static void ParseArgs ( IConfiguration config )
@@ -36,13 +44,13 @@ private static void ParseArgs(IConfiguration config)
3644 break ;
3745 case "sourceFolder" :
3846 if ( Directory . Exists ( kvp . Value ) )
39- sourceFolder = kvp . Value ;
47+ sourceRoot = kvp . Value ;
4048 else
4149 InvalidPath ( kvp . Value ) ;
4250 break ;
4351 case "destFolder" :
4452 if ( Directory . Exists ( kvp . Value ) )
45- destinationFolder = kvp . Value ;
53+ backupRoot = kvp . Value ;
4654 else
4755 InvalidPath ( kvp . Value ) ;
4856 break ;
@@ -67,68 +75,101 @@ private static void InvalidPath(string value)
6775 Environment . Exit ( 0 ) ;
6876 }
6977
70- private static void Sync ( )
78+ // Here we make sure that all required directories exist and clean the backup folder if the source is empty. We're not logging deletion here because it's not really a part of the actual file sync.
79+ private static void InitalSync ( )
7180 {
72- List < FileProps > sourceFileList = new List < FileProps > ( ) ;
73- List < FileProps > backupFileList = new List < FileProps > ( ) ;
81+ string [ ] sourceDirs = Directory . GetDirectories ( sourceRoot , "*" , SearchOption . AllDirectories ) . OrderBy ( s => s ) . ToArray ( ) ;
82+ string [ ] destDirs = Directory . GetDirectories ( backupRoot , "*" , SearchOption . AllDirectories ) . OrderBy ( s => s ) . ToArray ( ) ;
7483
75- string [ ] sourceDirs = Directory . GetDirectories ( sourceFolder , "*" , SearchOption . AllDirectories ) . OrderBy ( s => s ) . ToArray ( ) ;
76- string [ ] destDirs = Directory . GetDirectories ( destinationFolder , "*" , SearchOption . AllDirectories ) . OrderBy ( s => s ) . ToArray ( ) ;
77-
78- foreach ( var dir in sourceDirs ) // Make sure the folders that are in the source are also in the backup
84+ foreach ( var dir in sourceDirs ) // Make sure the folders that are in the source are also in the backup
7985 {
80- string backupDir = dir . Replace ( sourceFolder , destinationFolder ) ;
86+ string backupDir = dir . Replace ( sourceRoot , backupRoot ) ;
8187 if ( ! Directory . Exists ( backupDir ) )
8288 {
8389 Directory . CreateDirectory ( backupDir ) ;
8490 Log ( backupDir , Actions . created ) ;
8591 }
8692 }
8793
88- string [ ] sourceFiles = Directory . GetFiles ( sourceFolder , "*" , SearchOption . AllDirectories ) ;
89- foreach ( string file in sourceFiles )
90- sourceFileList . Add ( new FileProps ( file , sourceFolder ) ) ;
91-
92- string [ ] destFiles = Directory . GetFiles ( destinationFolder , "*" , SearchOption . AllDirectories ) ;
93- foreach ( string file in destFiles )
94- backupFileList . Add ( new FileProps ( file , destinationFolder ) ) ;
95-
96- if ( sourceFileList . Count == 0 && backupFileList . Count > 0 ) // If the source folder is empty, delete all files in the backup folder
94+ if ( Directory . GetFiles ( sourceRoot , "*" , SearchOption . AllDirectories ) . Length == 0 && Directory . GetFiles ( backupRoot , "*" , SearchOption . AllDirectories ) . Length > 0 )
9795 {
98- foreach ( var file in backupFileList )
99- {
100- File . Delete ( file . AbsoluteFilePath ) ;
101- Log ( file . FileName , file . AbsolutePath , Actions . deleted ) ;
102- }
96+ foreach ( var file in Directory . GetFiles ( backupRoot , "*" , SearchOption . AllDirectories ) )
97+ File . Delete ( file ) ;
10398 }
104- if ( sourceDirs . Length == 0 && destDirs . Length > 1 )
99+
100+ if ( sourceDirs . Length == 0 && destDirs . Length > 0 ) // If the source folder is empty, make sure the backup folder is empty as well
105101 {
106- for ( int i = destDirs . Length - 1 ; i >= 0 ; -- i )
107- {
102+ for ( int i = destDirs . Length - 1 ; i >= 0 ; -- i )
108103 Directory . Delete ( destDirs [ i ] ) ;
109- Log ( destDirs [ i ] , Actions . deleted ) ;
110- }
111104 }
105+ }
106+
107+ private static void Sync ( )
108+ {
109+ sourceFileList = new List < FileProps > ( ) ;
110+ backupFileList = new List < FileProps > ( ) ;
111+ string [ ] sourceFiles = Directory . GetFiles ( sourceRoot , "*" , SearchOption . AllDirectories ) ;
112+ foreach ( string file in sourceFiles )
113+ sourceFileList . Add ( new FileProps ( file , sourceRoot ) ) ;
114+
115+ string [ ] destFiles = Directory . GetFiles ( backupRoot , "*" , SearchOption . AllDirectories ) ;
116+ foreach ( string file in destFiles )
117+ backupFileList . Add ( new FileProps ( file , backupRoot ) ) ;
118+
119+ // if (sourceFileList.Count == 0 && backupFileList.Count > 0) // If the source folder is empty, delete all files in the backup folder
120+ // {
121+ // foreach (var file in backupFileList)
122+ // {
123+ // File.Delete(file.GetAbsoluteFilePath);
124+ // Log(file.GetFileName, file.GetAbsolutePath, Actions.deleted);
125+ // }
126+ // }
112127
113128 foreach ( var file in sourceFileList )
114129 {
115- var matchingBackupFile = backupFileList . Find ( backup => backup . IsFileTheSame ( file . RelativeFilePath , file . md5Code ) ) ;
130+ var matchingSourceFiles = sourceFileList . FindAll ( source => source . IsFileCopied ( file . GetFileName , file . GetMD5Code , file . GetRelativePath ) ) ;
131+ if ( matchingSourceFiles . Count > 0 ) // An exact copy of the file exists in a different directory
132+ {
133+ foreach ( var matchingSourceFile in matchingSourceFiles )
134+ {
135+ var match = backupFileList . Find ( backup => backup . IsFileTheSame ( file . GetRelativeFilePath , file . GetMD5Code ) ) ; // See if the copy is already backed up
136+ if ( match == null )
137+ {
138+ CreateCopyFile ( file , Actions . copied ) ;
139+ continue ;
140+ }
141+ }
142+ }
143+ var matchingBackupFile = backupFileList . Find ( backup => backup . IsFileTheSame ( file . GetRelativeFilePath , file . GetMD5Code ) ) ;
116144 if ( matchingBackupFile == null ) // if no match of the file is found, create a backup
117145 {
118- File . Copy ( file . AbsoluteFilePath , Path . Combine ( destinationFolder , file . RelativeFilePath ) ) ;
119- Log ( file . FileName , Path . Combine ( destinationFolder , file . RelativePath ) , Actions . created ) ;
146+ CreateCopyFile ( file , Actions . created ) ;
147+ continue ;
120148 }
121149 }
122-
123- foreach ( var file in backupFileList )
150+
151+ foreach ( var file in backupFileList )
124152 {
125- var matchingSourceFile = sourceFileList . Find ( source => source . IsFileTheSame ( file . RelativeFilePath , file . md5Code ) ) ;
126- if ( matchingSourceFile == null ) // the file was deleted
153+ var matchingSourceFile = sourceFileList . Find ( source => source . IsFileTheSame ( file . GetRelativeFilePath , file . GetMD5Code ) ) ;
154+ if ( matchingSourceFile == null ) // the file was deleted
127155 {
128- File . Delete ( file . AbsoluteFilePath ) ;
129- Log ( file . FileName , file . AbsolutePath , Actions . deleted ) ;
156+ File . Delete ( file . GetAbsoluteFilePath ) ;
157+ Log ( file . GetFileName , file . GetAbsolutePath , Actions . deleted ) ;
130158 }
131159 }
160+
161+ }
162+
163+ private static void CreateCopyFile ( FileProps file , Actions action )
164+ {
165+ string newFile = Path . Combine ( backupRoot , file . GetRelativeFilePath ) ;
166+ File . Copy ( file . GetAbsoluteFilePath , newFile ) ; //
167+ Log ( file . GetFileName , newFile , action ) ;
168+ }
169+
170+ private static void EditFile ( FileProps file , Actions action )
171+ {
172+
132173 }
133174
134175 enum Actions
0 commit comments