private void EvaluateLocallyAbsentFilesAndDirs(SyncedDirectory syncedDirectory)
        {
            //evaluate the files first (needed to evaluate the dir)
            foreach (var syncedFile in syncedDirectory.Files.Where(x => x.LocallyAbsent && !x.RemoteDeleted).ToArray())
            {
                //if this file was present on the last sync, it's really deleted, otherwise it is new on the remote side
                syncedFile.LocallyDeleted = syncedFile.TimestampOnLastSync.Local.HasValue;

                if (!syncedFile.LocallyDeleted)
                {
                    //remote new, construct local directory
                    syncedFile.LocalDirectory = Path.Combine(_fileRepository.StorageDirectory, syncedDirectory.GetRelativePath());
                }
            }

            if (syncedDirectory.LocallyAbsent)
            {
                var shouldLive = syncedDirectory.Files.Any(x => !x.LocallyDeleted);
                syncedDirectory.LocallyDeleted = !shouldLive;
            }

            foreach (var subDir in syncedDirectory.SubDirectories)
            {
                EvaluateLocallyAbsentFilesAndDirs(subDir);
            }
        }
示例#2
0
        private void EvaluateLocallyAbsentFilesAndDirs(SyncedDirectory syncedDirectory)
        {
            //evaluate the files first (needed to evaluate the dir)
            foreach (var syncedFile in syncedDirectory.Files.Where(x => x.LocallyAbsent && !x.RemoteDeleted).ToArray())
            {
                //if this file was present on the last sync, it's really deleted, otherwise it is new on the remote side
                syncedFile.LocallyDeleted = syncedFile.TimestampOnLastSync.Local.HasValue;

                if (!syncedFile.LocallyDeleted)
                {
                    //remote new, construct local directory
                    syncedFile.LocalDirectory = Path.Combine(_fileRepository.StorageDirectory, syncedDirectory.GetRelativePath());
                }
            }

            if (syncedDirectory.LocallyAbsent)
            {
                var shouldLive = syncedDirectory.Files.Any(x => !x.LocallyDeleted);
                syncedDirectory.LocallyDeleted = !shouldLive;
            }

            foreach (var subDir in syncedDirectory.SubDirectories)
            {
                EvaluateLocallyAbsentFilesAndDirs(subDir);
            }
        }
        /// <summary>
        /// merge state from local directory into the current state.
        /// </summary>
        private static void CopyInfoFromLocalState(SyncedDirectory localState, SyncedDirectory myState)
        {
            //recursively walk the subdirectories and merge
            foreach (var mySubDir in myState.SubDirectories)
            {
                var localSubDirectory = localState.SubDirectories.FirstOrDefault(x => x.NameEquals(mySubDir.Name));
                if (localSubDirectory == null)
                {
                    //may be deleted locally, but could also be new on the remote side.
                    //we don't know yet, this will be re-evaluated later (in this class)
                    mySubDir.LocallyAbsent = true;
                    localSubDirectory      = new SyncedDirectory();
                }

                CopyInfoFromLocalState(localSubDirectory, mySubDir);
            }

            //add directories that don't exist in myState but do exist in localState
            //these don't have to be evaluated recursively, because all info is copied immediately by adding the dirs
            var dirsOnlyInLocalState = localState.SubDirectories.Where(local => !myState.SubDirectories.Any(my => my.NameEquals(local.Name)));

            myState.AddDir(dirsOnlyInLocalState.ToArray());

            //merge the files
            foreach (var myFile in myState.Files)
            {
                var localFile = localState.Files.FirstOrDefault(x => x.NameEquals(myFile.Name));

                if (localFile == null)
                {
                    //may be deleted locally, but could also be new on the remote side.
                    //we don't know yet, this will be re-evaluated later
                    myFile.LocallyAbsent = true;
                }
                else
                {
                    myFile.CurrentSyncTimestamp.Local = localFile.CurrentSyncTimestamp.Local;
                    myFile.LocalDirectory             = localFile.LocalDirectory;
                }
            }

            //add local files to cloudDirState that don't exist remotely
            var filesOnlyInLocalState = localState.Files.Where(local => !myState.Files.Any(my => my.NameEquals(local.Name)));

            myState.AddFile(filesOnlyInLocalState.ToArray());
        }
示例#4
0
        /// <summary>
        /// recursively evaluate syncstate and destill sync commands
        /// </summary>
        private IEnumerable <SyncCommand> CreateSyncCommands(SyncedDirectory dir)
        {
            var result = new List <SyncCommand>();

            foreach (var subDir in dir.SubDirectories)
            {
                result.AddRange(CreateSyncCommands(subDir));
            }

            foreach (var file in dir.Files)
            {
                if (GetSyncInfoFileName().Equals(file.Name))
                {
                    continue;
                }

                var isNewLocally = !file.LocallyAbsent && !file.TimestampOnLastSync.Local.HasValue;
                var isNewRemote  = file.LocallyAbsent && !file.TimestampOnLastSync.Remote.HasValue;

                //local changes go first: remote often has a versioning system in place

                if (file.LocallyDeleted)
                {
                    if (!file.RemoteDeleted)
                    {
                        result.Add(SyncCommand.DeleteRemote(file));
                    }
                }
                else if (file.RemoteDeleted)
                {
                    if (file.LocalPath != null) //may already be deleted locally
                    {
                        result.Add(SyncCommand.DeleteLocal(file));
                    }
                }
                else if (isNewLocally || file.CurrentSyncTimestamp.Local > file.TimestampOnLastSync.Local)
                {
                    result.Add(SyncCommand.Upload(file));
                }
                else if (isNewRemote || file.CurrentSyncTimestamp.Remote > file.TimestampOnLastSync.Remote)
                {
                    result.Add(SyncCommand.Download(file));
                }
            }
            return(result);
        }
        /// <summary>
        /// merge info from previous sync into the current state (mainly 'last sync datetime')
        /// </summary>
        private static void CopyInfoFromPreviousSync(SyncedDirectory prevState, SyncedDirectory myState)
        {
            foreach (var mySubDir in myState.SubDirectories)
            {
                var prevSubDir = prevState.SubDirectories.FirstOrDefault(x => x.NameEquals(mySubDir.Name));
                prevSubDir = prevSubDir ?? new SyncedDirectory();
                CopyInfoFromPreviousSync(prevSubDir, mySubDir);
            }

            foreach (var myFile in myState.Files)
            {
                var prevFile = prevState.Files.FirstOrDefault(x => x.NameEquals(myFile.Name));
                if (prevFile != null)
                {
                    myFile.TimestampOnLastSync = prevFile.TimestampAfterLastSync;
                }
            }
        }
示例#6
0
        /// <summary>
        /// merge syncinfo from after sync to the properties in the syncinfo
        /// </summary>
        /// <param name="inputForSync">syncinfo before and during sync</param>
        /// <param name="syncStateAfterTheFact">syncinfo after sync</param>
        private void CopyCurrentTimestampsToAfterLastSyncFrom(SyncedDirectory inputForSync, SyncedDirectory syncStateAfterTheFact)
        {
            foreach (var inputDir in inputForSync.SubDirectories)
            {
                var dirAfterTheFact = syncStateAfterTheFact.SubDirectories.FirstOrDefault(x => x.NameEquals(inputDir.Name));
                dirAfterTheFact = dirAfterTheFact ?? new SyncedDirectory(); //apparently removed during sync by another app or manually
                CopyCurrentTimestampsToAfterLastSyncFrom(inputDir, dirAfterTheFact);
            }

            foreach (var inputFile in inputForSync.Files)
            {
                var fileAfterTheFact = syncStateAfterTheFact.Files.FirstOrDefault(x => x.NameEquals(inputFile.Name));
                if (fileAfterTheFact != null)
                {
                    inputFile.TimestampAfterLastSync = fileAfterTheFact.CurrentSyncTimestamp;
                }
            }
        }
        /// <summary>
        /// merge state from local directory into the current state.
        /// </summary>
        private static void CopyInfoFromLocalState(SyncedDirectory localState, SyncedDirectory myState)
        {
            //recursively walk the subdirectories and merge
            foreach (var mySubDir in myState.SubDirectories)
            {
                var localSubDirectory = localState.SubDirectories.FirstOrDefault(x => x.NameEquals(mySubDir.Name));
                if (localSubDirectory == null)
                {
                    //may be deleted locally, but could also be new on the remote side.
                    //we don't know yet, this will be re-evaluated later (in this class)
                    mySubDir.LocallyAbsent = true;
                    localSubDirectory = new SyncedDirectory();
                }

                CopyInfoFromLocalState(localSubDirectory, mySubDir);
            }

            //add directories that don't exist in myState but do exist in localState
            //these don't have to be evaluated recursively, because all info is copied immediately by adding the dirs 
            var dirsOnlyInLocalState = localState.SubDirectories.Where(local => !myState.SubDirectories.Any(my => my.NameEquals(local.Name)));
            myState.AddDir(dirsOnlyInLocalState.ToArray());

            //merge the files
            foreach (var myFile in myState.Files)
            {
                var localFile = localState.Files.FirstOrDefault(x => x.NameEquals(myFile.Name));

                if (localFile == null)
                {
                    //may be deleted locally, but could also be new on the remote side.
                    //we don't know yet, this will be re-evaluated later 
                    myFile.LocallyAbsent = true;
                }
                else
                {
                    myFile.CurrentSyncTimestamp.Local = localFile.CurrentSyncTimestamp.Local;
                    myFile.LocalDirectory = localFile.LocalDirectory;
                }
            }

            //add local files to cloudDirState that don't exist remotely
            var filesOnlyInLocalState = localState.Files.Where(local => !myState.Files.Any(my => my.NameEquals(local.Name)));
            myState.AddFile(filesOnlyInLocalState.ToArray());
        }
示例#8
0
        /// <summary>
        /// restore sync info from previous sync from disk
        /// </summary>
        private SyncedDirectory GetPrevSyncInfo()
        {
            var prevSyncInfoText = _fileRepository.GetText(GetSyncInfoFileName());
            var prevSyncInfo     = new SyncedDirectory();

            if (!string.IsNullOrEmpty(prevSyncInfoText))
            {
                try
                {
                    prevSyncInfo = JsonConvert.DeserializeObject <SyncedDirectory>(prevSyncInfoText);
                }
                catch
                {
                    //file is apparently broken: all sync information is lost.
                    //will be overwritten with new information.
                }
            }
            return(prevSyncInfo);
        }
 /// <summary>
 /// restore sync info from previous sync from disk
 /// </summary>
 private SyncedDirectory GetPrevSyncInfo()
 {
     var prevSyncInfoText = _fileRepository.GetText(GetSyncInfoFileName());
     var prevSyncInfo = new SyncedDirectory();
     if (!string.IsNullOrEmpty(prevSyncInfoText))
     {
         try
         {
             prevSyncInfo = JsonConvert.DeserializeObject<SyncedDirectory>(prevSyncInfoText);
         }
         catch
         {
             //file is apparently broken: all sync information is lost.
             //will be overwritten with new information.
         }
     }
     return prevSyncInfo;
 }
 /// <summary>
 /// Synchronize all files to and from Dropbox
 /// </summary>
 public async Task Initialize()
 {
     _syncState = await BuildUpSyncState();
 }
示例#11
0
 /// <summary>
 /// Synchronize all files to and from Dropbox
 /// </summary>
 public async Task Initialize()
 {
     _syncState = await BuildUpSyncState();
 }
        /// <summary>
        /// merge syncinfo from after sync to the properties in the syncinfo
        /// </summary>
        /// <param name="inputForSync">syncinfo before and during sync</param>
        /// <param name="syncStateAfterTheFact">syncinfo after sync</param>
        private void CopyCurrentTimestampsToAfterLastSyncFrom(SyncedDirectory inputForSync, SyncedDirectory syncStateAfterTheFact)
        {
            foreach (var inputDir in inputForSync.SubDirectories)
            {
                var dirAfterTheFact = syncStateAfterTheFact.SubDirectories.FirstOrDefault(x => x.NameEquals(inputDir.Name));
                dirAfterTheFact = dirAfterTheFact ?? new SyncedDirectory(); //apparently removed during sync by another app or manually
                CopyCurrentTimestampsToAfterLastSyncFrom(inputDir, dirAfterTheFact);
            }

            foreach (var inputFile in inputForSync.Files)
            {
                var fileAfterTheFact = syncStateAfterTheFact.Files.FirstOrDefault(x => x.NameEquals(inputFile.Name));
                if (fileAfterTheFact != null)
                {
                    inputFile.TimestampAfterLastSync = fileAfterTheFact.CurrentSyncTimestamp;
                }
            }
        }
 public void CopyInfoFromLocalState(SyncedDirectory localState)
 {
     CopyInfoFromLocalState(localState, this);
 }
        private SyncedDirectory GetLocalSyncState(DirectoryInfo dir)
        {
            var result = new SyncedDirectory { Name = dir.Name };
            foreach (var subDir in dir.GetDirectories())
            {
                result.AddDir(GetLocalSyncState(subDir));
            }

            foreach (var file in dir.GetFiles())
            {
                result.AddFile(new SyncedFile
                {
                    Name = file.Name,
                    LocalDirectory = file.DirectoryName,
                    CurrentSyncTimestamp = { Local = file.LastWriteTimeUtc }
                });
            }

            return result;
        }
 public void CopyInfoFromPreviousSync(SyncedDirectory prevState)
 {
     CopyInfoFromPreviousSync(prevState, this);
 }
 public void CopyInfoFromPreviousSync(SyncedDirectory prevState)
 {
     CopyInfoFromPreviousSync(prevState, this);
 }
        /// <summary>
        /// recursively evaluate syncstate and destill sync commands 
        /// </summary>
        private IEnumerable<SyncCommand> CreateSyncCommands(SyncedDirectory dir)
        {
            var result = new List<SyncCommand>();
            foreach (var subDir in dir.SubDirectories)
            {
                result.AddRange(CreateSyncCommands(subDir));
            }

            foreach (var file in dir.Files)
            {
                if (GetSyncInfoFileName().Equals(file.Name))
                {
                    continue;
                }

                var isNewLocally = !file.LocallyAbsent && !file.TimestampOnLastSync.Local.HasValue;
                var isNewRemote = file.LocallyAbsent && !file.TimestampOnLastSync.Remote.HasValue;

                //local changes go first: remote often has a versioning system in place

                if (file.LocallyDeleted)
                {
                    if (!file.RemoteDeleted)
                    {
                        result.Add(SyncCommand.DeleteRemote(file));
                    }
                }
                else if (file.RemoteDeleted)
                {
                    if (file.LocalPath != null) //may already be deleted locally
                    {
                        result.Add(SyncCommand.DeleteLocal(file));
                    }
                }
                else if (isNewLocally || file.CurrentSyncTimestamp.Local > file.TimestampOnLastSync.Local)
                {
                    result.Add(SyncCommand.Upload(file));
                }
                else if (isNewRemote || file.CurrentSyncTimestamp.Remote > file.TimestampOnLastSync.Remote)
                {
                    result.Add(SyncCommand.Download(file));
                }
            }
            return result;
        }
 public void CopyInfoFromLocalState(SyncedDirectory localState)
 {
     CopyInfoFromLocalState(localState, this);
 }
        /// <summary>
        /// merge info from previous sync into the current state (mainly 'last sync datetime')
        /// </summary>
        private static void CopyInfoFromPreviousSync(SyncedDirectory prevState, SyncedDirectory myState)
        {
            foreach (var mySubDir in myState.SubDirectories)
            {
                var prevSubDir = prevState.SubDirectories.FirstOrDefault(x => x.NameEquals(mySubDir.Name));
                prevSubDir = prevSubDir ?? new SyncedDirectory();
                CopyInfoFromPreviousSync(prevSubDir, mySubDir);
            }

            foreach (var myFile in myState.Files)
            {
                var prevFile = prevState.Files.FirstOrDefault(x => x.NameEquals(myFile.Name));
                if (prevFile != null)
                {
                    myFile.TimestampOnLastSync = prevFile.TimestampAfterLastSync;
                }
            }
        }