예제 #1
0
        public void AddUniqueElements()
        {
            OpenFileDialog fd = new OpenFileDialog();

            fd.Filter      = "All Media Files|*.wav;*.aac;*.wma;*.wmv;*.avi;*.mpg;*.mpeg;*.m1v;*.mp2;*.mp3;*.mpa;*.mpe;*.m3u;*.mp4;*.mov;*.3g2;*.3gp2;*.3gp;*.3gpp;*.m4a;*.cda;*.aif;*.aifc;*.aiff;*.mid;*.midi;*.rmi;*.mkv;*.WAV;*.AAC;*.WMA;*.WMV;*.AVI;*.MPG;*.MPEG;*.M1V;*.MP2;*.MP3;*.MPA;*.MPE;*.M3U;*.MP4;*.MOV;*.3G2;*.3GP2;*.3GP;*.3GPP;*.M4A;*.CDA;*.AIF;*.AIFC;*.AIFF;*.MID;*.MIDI;*.RMI;*.MKV";
            fd.Multiselect = true;

            if (fd.ShowDialog() == true)
            {
                foreach (var media in fd.FileNames)
                {
                    NewFiles.Add(new Media()
                    {
                        MediaPath = new Uri(media), MediaName = media.Split('\\').Last()
                    });
                }
            }
            foreach (var media in NewFiles)
            {
                if (!MediaCollection.Contains(media))
                {
                    MediaCollection.Add(media);
                }
            }
            NewFiles.Clear();
        }
예제 #2
0
        private void ProcessChangesIfAny()
        {
            lock (DedupLock)
            {
                if (NewFiles.Any() || DeletedFiles.Any())
                {
                    DedupTask = Task.Factory.StartNew(
                        ProcessChanges,
                        CancelSource.Token);
                    return;
                }

                if (!CurrentState.Settings.MonitorChanges)
                {
                    operationStartTime = DateTime.MinValue;
                    OnOperationUpdate(
                        OperationType.Completed,
                        ProgressStyle.NoProgress);
                    OnLogged("Finished comparison.");
                    return;
                }

                operationStartTime = DateTime.Now;
                OnOperationUpdate(
                    OperationType.Monitoring,
                    ProgressStyle.Marquee);
                OnLogged("Monitoring for file changes...");
                return;
            }
        }
예제 #3
0
        private void OK(object x)
        {
            var win = x as Window;

            if (System.Windows.MessageBox.Show($"Are you sure to apply change to [{ID}] ?",
                                               "Question", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
            {
                if (!NewFiles.Any(y => y[root] == this.Path))
                {
                    mDB.DeleteRecord(this.ID);
                }
                var tID = this.ID;
                foreach (var i in NewFiles)
                {
                    var t = new FileInfo(i).Name;
                    if (i[root] == this.Path)
                    {
                        mDB.UpDateFile(tID, i[root], t, this.Time);
                    }
                    else
                    {
                        mDB.AddDataItem(i[root], t, this.Time, tID, null);
                    }

                    mDB.SetUploadStatus(tID, this.Visable, this.IsUploaded);
                    tID = Database.GenerateID();
                }
                var s = "";
                System.Windows.MessageBox.Show("OK!");
                win.DialogResult = true;
            }
        }
예제 #4
0
 public void AddFile(string filepath, string cascpath, EncodingType encoding = EncodingType.ZLib, byte compression = 9)
 {
     if (File.Exists(filepath))
     {
         NewFiles.Add(cascpath, new CASFile(File.ReadAllBytes(filepath), encoding, compression));
     }
 }
예제 #5
0
        private IEnumerable <VideoFile> GetVideoFileList(
            IFolderSettings folderSettings)
        {
            operationStartTime = DateTime.Now;
            OnOperationUpdate(OperationType.Searching, ProgressStyle.Marquee);

            // Get all video files in source path.
            var foundFiles = GetAllAccessibleFilesIn(
                folderSettings.BasePath,
                folderSettings.ExcludedDirectories,
                folderSettings.Recursive)
                             .Where(f => folderSettings.FileExtensions.Contains(
                                        Path.GetExtension(f),
                                        StringComparer.InvariantCultureIgnoreCase))
                             .Select(f => new VideoFile(f))
                             .ToList();

            if (CurrentState.VideoFiles == null)
            {
                return(foundFiles);
            }

            foreach (var file in foundFiles.Except(CurrentState.VideoFiles))
            {
                NewFiles.TryAdd(file, 0);
            }

            foreach (var file in CurrentState.VideoFiles.Except(foundFiles))
            {
                DeletedFiles.TryAdd(file, 0);
            }

            return(CurrentState.VideoFiles);
        }
예제 #6
0
 private void RemoveFromList(object sender)
 {
     if (RSelectedItem < 0)
     {
         return;
     }
     NewFiles.RemoveAt(RSelectedItem);
 }
예제 #7
0
 public void Dispose()
 {
     NewFiles.Clear();
     NewFiles = null;
     Chunks.Clear();
     Chunks.TrimExcess();
     Chunks = null;
 }
예제 #8
0
        private void HandleNewFileEvent(string filePath)
        {
            if (!IsFilePathRelevant(filePath, CurrentState.Settings))
            {
                return;
            }

            _ = NewFiles.TryAdd(new VideoFile(filePath), 0);
            OnLogged(string.Format(LogNewFile, filePath));
            StartProcessingChanges();
        }
예제 #9
0
        private void OnFilesChanged(object sender, FileSystemEventArgs e)
        {
            var path      = e.FullPath;
            var extension = Path.GetExtension(path);

            if (!Contains(path) && (extension.Contains(".jpg") || extension.Contains(".jpeg")))
            {
                FileNames.Add(path);
                NewFiles.Add(path);
                ItemAdded(sender, e);
                Debug.WriteLine("added " + path);
            }
        }
예제 #10
0
        public void Clear()
        {
            FileCheckedCount = 0;

            NewFiles.Clear();
            NewFilesForGroom.Clear();
            ChangedFiles.Clear();
            MissingFiles.Clear();
            LastModifiedDateFiles.Clear();
            ErrorFiles.Clear();
            IgnoredFiles.Clear();
            NewlyIgnoredFiles.Clear();
            IgnoredFilesForGroom.Clear();
            MovedFiles.Clear();
            MovedFileOrder.Clear();
            DuplicateFiles.Clear();
        }
예제 #11
0
        private void AddToList(object sender)
        {
            if (LSelectedItem < 0)
            {
                return;
            }
            var mItem = FolderItems[LSelectedItem];

            if (!mItem.FilePath.IsNullOrEmptyOrWhiltSpace())
            {
                FileAttributes attr = File.GetAttributes(mItem);
                if ((attr & FileAttributes.Directory) == FileAttributes.Directory)
                {
                    return;
                }
                if (!NewFiles.Any(x => x == mItem))
                {
                    NewFiles.Add(mItem);
                }
            }
        }
예제 #12
0
        // loads update config
        public bool Load(string path, string version)
        {
            this.version = version;

            try
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(path);

                LoadFiles(doc, "newFiles", NewFiles, true);
                LoadFiles(doc, "deletedFiles", DeletedFiles, false);

                return(true);
            }
            catch (Exception e)
            {
                ErrorLog.Add(this, e.Message);
                NewFiles.Clear();
                DeletedFiles.Clear();
            }

            return(false);
        }
예제 #13
0
 private void OpenFile(object sender)
 {
     using (var mdlg = new OpenFileDialog())
     {
         mdlg.CheckFileExists = true;
         mdlg.Filter          = "Transport Stream(*.ts;*.m2ts)|*.ts;*.m2ts|Meta Data(*.meta;*.xml)|*.meta;*.xml|All file(*.*)|*.*";
         mdlg.Multiselect     = true;
         if (mdlg.ShowDialog() == DialogResult.OK)
         {
             foreach (string i in mdlg.FileNames)
             {
                 if (!NewFiles.Any(x => x == i))
                 {
                     NewFiles.Add(i);
                 }
             }
         }
         else
         {
             return;
         }
     }
 }
예제 #14
0
 private void ParseStatusResult(string stdout)
 {
     using (var reader = new StringReader(stdout))
     {
         string line;
         while ((line = reader.ReadLine()) != null)
         {
             if (line.StartsWith("M"))
             {
                 ModifiedFiles.Add(line.Substring(2).TrimStart());
             }
             if (line.StartsWith("D"))
             {
                 DeletedFiles.Add(line.Substring(2).TrimStart());
             }
             if (line.StartsWith("A"))
             {
                 NewFiles.Add(line.Substring(2).TrimStart());
             }
             // renames (R) are ignored - won't be used in a Quince repository
         }
     }
 }
예제 #15
0
        internal static void LoadNewFiles()
        {
            NewFiles = Directory.GetFiles(Configuration.NewDirectory, Configuration.SearchPattern);
            for (int i = 0; i < NewFiles.Length; i++)
            {
                NewFiles[i] = Path.GetFileNameWithoutExtension(NewFiles[i]);
            }

            foreach (string file in NewFiles)
            {
                if (!(file.Contains(Configuration.NewToken)))
                {
                    NewFiles = NewFiles.Where(tempfile => tempfile != file).ToArray();
                }
            }

            for (int i = 0; i < NewFiles.Length; i++)
            {
                if (NewFiles[i].Contains(Configuration.NewToken))
                {
                    NewFiles[i] = NewFiles[i].Remove(NewFiles[i].Length - Configuration.NewToken.Length);
                }
            }
        }
예제 #16
0
 public void MarkNewFilesReceived()
 {
     NewFiles.Clear();
 }
예제 #17
0
        /// <summary>
        /// Executes the scan
        /// </summary>
        public void Process()
        {
            Stopped = false;
            SetStatus();

            if (MainForm.WatchFolders.Count == 0)
            {
                MainForm.MusicFileRepo.DeleteAll().Wait();
                MainForm.PlaylistFileRepo.DeleteAll().Wait();
                MainForm.SetDiscoveredFilesLabel("0");
                MainForm.SetIssuesLabel("0");
                MainForm.SetUploadedLabel("0");
            }

            CurrentMusicFiles = MainForm.MusicFileRepo.LoadAll().Result;
            foreach (var musicFile in CurrentMusicFiles)
            {
                CurrentProcessingFilesHash.Add(musicFile.Path);
            }

            CurrentPlaylistFiles = MainForm.PlaylistFileRepo.LoadAll().Result;
            foreach (var playlistFile in CurrentPlaylistFiles)
            {
                CurrentProcessingFilesHash.Add(playlistFile.Path);
            }

            //
            // Get files to add - Cross reference with the DB
            //
            foreach (var watchFolder in MainForm.WatchFolders)
            {
                if (MainFormAborting())
                {
                    return;
                }

                if (Directory.Exists(watchFolder.Path))
                {
                    foreach (var file in FastDirectoryEnumerator.EnumerateFiles(watchFolder.Path,
                                                                                "*.*",
                                                                                SearchOption.AllDirectories))
                    {
                        try
                        {
                            if (MainFormAborting())
                            {
                                return;
                            }

                            if (!CurrentProcessingFilesHash.Contains(file.Path))
                            {
                                if (Path.GetExtension(file.Name.ToLower()).In(Global.SupportedMusicFiles) ||
                                    Path.GetExtension(file.Name.ToLower()).In(Global.SupportedPlaylistFiles))
                                {
                                    NewFiles.Add(file);
                                    NewFilesHash.Add(file.Path);
                                }
                            }

                            if (MainFormAborting())
                            {
                                return;
                            }

                            if (Path.GetExtension(file.Name.ToLower()).In(Global.SupportedMusicFiles) ||
                                Path.GetExtension(file.Name.ToLower()).In(Global.SupportedPlaylistFiles))
                            {
                                DiscoveredFilesHash.Add(file.Path);
                            }
                        }
                        catch (Exception e)
                        {
                            Logger.Log(
                                e,
                                "FileScanner.Process - Error reading file (possibly removed): " +
                                file.Path,
                                Log.LogTypeEnum.Error,
                                false);
                        }
                    }
                }
                else
                {
                    if (MainFormAborting())
                    {
                        return;
                    }

                    SetStatus("Error: Watch folder directory does not exists: " + watchFolder.Path.EllipsisPath(100), "Directory ");
                    ThreadHelper.SafeSleep(5000);
                }
            }

            //
            // Get files to delete - Cross reference with the DB
            //

            foreach (var musicFile in CurrentMusicFiles)
            {
                if (MainFormAborting())
                {
                    return;
                }

                if (!DiscoveredFilesHash.Contains(musicFile.Path))
                {
                    MusicFilesToDelete.Add(musicFile);
                }
            }

            foreach (var playlistFile in CurrentPlaylistFiles)
            {
                if (MainFormAborting())
                {
                    return;
                }

                if (!DiscoveredFilesHash.Contains(playlistFile.Path))
                {
                    PlaylistFilesToDelete.Add(playlistFile);
                }
            }

            using (var conn = new SQLiteConnection("Data Source=" + Global.DbLocation + ";cache=shared"))
            {
                SetStatus();
                conn.Open();

                try
                {
                    int count = 0;
                    foreach (var file in NewFiles)
                    {
                        if (MainFormAborting(conn))
                        {
                            return;
                        }

                        count++;
                        if (count % 100 == 0)
                        {
                            MainForm.SetDiscoveredFilesLabel(count.ToString());
                        }

                        SetStatus();

                        if (Path.GetExtension(file.Path).ToLower().In(Global.SupportedMusicFiles))
                        {
                            AddMusiFileToDB(conn, new MusicFile(file.Path));
                        }

                        else if (Path.GetExtension(file.Path).ToLower().In(Global.SupportedPlaylistFiles))
                        {
                            AddPlaylistFileToDB(conn, new PlaylistFile(file.Path, file.LastWriteTime));
                        }
                    }

                    if (MainFormAborting(conn))
                    {
                        return;
                    }

                    foreach (var musicFile in MusicFilesToDelete)
                    {
                        if (MainFormAborting(conn))
                        {
                            return;
                        }

                        RemoveMusicFileFromDB(conn, musicFile.Path);
                    }
                    ;

                    if (MainFormAborting(conn))
                    {
                        return;
                    }

                    foreach (var playlistFile in PlaylistFilesToDelete)
                    {
                        if (MainFormAborting(conn))
                        {
                            return;
                        }

                        RemovePlaylistFileFromDb(conn, playlistFile.Path);
                    }
                    ;

                    MainForm.SetDiscoveredFilesLabel(MainForm.MusicFileRepo.CountAll().Result.ToString());
                }
                catch { }

                conn.Close();
            }

            SetStatus(MainForm.ConnectedToYTMusic ? "Ready" : "Waiting for YouTube Music connection", "Waiting for YouTube Music connection");
            Stopped = true;
        }
예제 #18
0
        /// <summary>
        /// Executes the scan
        /// </summary>
        public void Process()
        {
            SetStatus();

            CurrentMusicFiles = MainForm.MusicFileRepo.LoadAll().Result;
            foreach (var musicFile in CurrentMusicFiles)
            {
                CurrentMusicFilesHash.Add(musicFile.Path);
            }

            if (MainForm.WatchFolders.Count == 0)
            {
                MainForm.MusicFileRepo.DeleteAll().Wait();
            }

            //
            // Get files to add - Cross reference with the DB
            //
            foreach (var watchFolder in MainForm.WatchFolders)
            {
                if (MainForm.Aborting)
                {
                    SetStatus("Idle", "Idle");
                    return;
                }

                foreach (var file in FastDirectoryEnumerator.EnumerateFiles(watchFolder.Path,
                                                                            "*.*",
                                                                            SearchOption.AllDirectories))
                {
                    if (MainForm.Aborting)
                    {
                        SetStatus("Idle", "Idle");
                        return;
                    }

                    if (!CurrentMusicFilesHash.Contains(file.Path))
                    {
                        if (Path.GetExtension(file.Name.ToLower()).In(Global.SupportedFiles))
                        {
                            NewFiles.Add(file);
                            NewFilesHash.Add(file.Path);
                        }
                    }

                    if (Path.GetExtension(file.Name.ToLower()).In(Global.SupportedFiles))
                    {
                        DiscoveredFilesHash.Add(file.Path);
                    }
                }
            }

            //
            // Get files to delete - Cross reference with the DB
            //
            foreach (var musicFile in CurrentMusicFiles)
            {
                if (MainForm.Aborting)
                {
                    SetStatus("Idle", "Idle");
                    return;
                }

                if (!DiscoveredFilesHash.Contains(musicFile.Path))
                {
                    MusicFilesToDelete.Add(musicFile);
                }
            }

            using (var conn = new SQLiteConnection("Data Source=" + Global.DbLocation))
            {
                SetStatus();
                conn.Open();
                int count = 0;
                foreach (var file in NewFiles)
                {
                    if (MainForm.Aborting)
                    {
                        MainForm.SetStatusMessage("Idle", "Idle");
                        return;
                    }

                    count++;
                    if (count > MainForm.InitialFilesCount)
                    {
                        if (count % 100 == 0)
                        {
                            MainForm.SetDiscoveredFilesLabel(count.ToString());
                        }
                    }

                    SetStatus();
                    AddToDB(conn, new MusicFile(file.Path));
                }

                if (MainForm.Aborting)
                {
                    SetStatus("Idle", "Idle");
                    return;
                }

                count = 0;
                foreach (var musicFile in MusicFilesToDelete)
                {
                    if (MainForm.Aborting)
                    {
                        MainForm.SetStatusMessage("Idle", "Idle");
                        return;
                    }

                    count++;
                    RemoveFromDB(conn, musicFile.Path);
                }
                ;

                MainForm.SetDiscoveredFilesLabel(MainForm.MusicFileRepo.CountAll().Result.ToString());
            }

            SetStatus(MainForm.ConnectedToYTMusic ? "Ready" : "Waiting for YouTube Music connection", "Waiting for YouTube Music connection");
        }
예제 #19
0
        private void ProcessChanges()
        {
            var cancelToken = CancelSource.Token;

            while (DeletedFiles.Any())
            {
                var deletedFile = DeletedFiles.First().Key;
                _ = DeletedFiles.TryRemove(deletedFile, out var _);

                if (CurrentState.VideoFiles.Remove(deletedFile))
                {
                    CurrentState.SaveState();
                    OnLogged($"Removed file: {deletedFile.FilePath}");
                }
                else
                {
                    OnLogged($"Deleted file not in VideoFile-List: " +
                             $"{deletedFile.FilePath}");
                }
                cancelToken.ThrowIfCancellationRequested();
            }

            operationStartTime = DateTime.Now;
            OnOperationUpdate(OperationType.Comparing, 0, NewFiles.Count());
            // We need to count for the ProgressUpdate since we shrink
            // the Queue on every iteration.
            var filesProcessed = 1;

            while (NewFiles.Any())
            {
                var newFile = NewFiles.First().Key;
                _ = NewFiles.TryRemove(newFile, out var _);
                OnOperationUpdate(OperationType.Comparing, filesProcessed,
                                  filesProcessed + NewFiles.Count());
                filesProcessed++;

                if (!newFile.WaitForFileAccess(cancelToken))
                {
                    OnLogged($"Unable to access new file: {newFile.FileName}");
                    cancelToken.ThrowIfCancellationRequested();
                    continue;
                }
                cancelToken.ThrowIfCancellationRequested();

                if (newFile.Duration == TimeSpan.Zero)
                {
                    OnLogged($"New file has no duration: {newFile.FilePath}");
                    continue;
                }
                cancelToken.ThrowIfCancellationRequested();

                if (!CurrentState.VideoFiles.Contains(newFile))
                {
                    OnLogged($"New file added to VideoFile-List: {newFile.FilePath}");
                    CurrentState.VideoFiles.Add(newFile);
                }
                else
                {
                    OnLogged($"New file already in VideoFile-List: {newFile.FilePath}");
                    continue;
                }
                cancelToken.ThrowIfCancellationRequested();

                FindDuplicatesOf(CurrentState.VideoFiles, newFile, cancelToken);
                CurrentState.SaveState();
                // Cleanup in case of cancel
                foreach (var file in CurrentState.VideoFiles)
                {
                    file.DisposeImages();
                }
                cancelToken.ThrowIfCancellationRequested();
            }

            ProcessChangesIfAny();
        }
예제 #20
0
        protected void UpdateRecursive(
            DirectoryInfo currentDirectoryInfo,
            ManifestDirectoryInfo currentManfestDirInfo)
        {
            // Setup data for current directory
            Dictionary <String, FileInfo> fileDict =
                new Dictionary <string, FileInfo>();

            Dictionary <String, DirectoryInfo> dirDict =
                new Dictionary <string, DirectoryInfo>();

            if (currentDirectoryInfo != null)
            {
                FileInfo[] fileList = null;
                try
                {
                    fileList = currentDirectoryInfo.GetFiles();
                }
                catch (Exception)
                {
                    WriteLine(Manifest.MakeStandardPathString(
                                  currentManfestDirInfo));

                    if (IgnoreFile(Manifest.MakeStandardPathString(
                                       currentManfestDirInfo)) == true)
                    {
                        // This was implemented primarily to allow the user to
                        // silence the process of skipping over inaccessible
                        // system directories by ignoring them.  For example,
                        // in some cases the "$RECYCLE BIN" under Windows
                        // is not accessible and will generate an error.  The
                        // user can now add such directories to the ignore list
                        // and they will be silently ignored.  The special
                        // message for showProgress alerts the user that the
                        // directory is actually being skipped altogether
                        // since it can't be accessed.  The only significant
                        // implication of this is that the ignored files won't
                        // be enumerated and counted as being ignored.
                        if (ShowProgress)
                        {
                            WriteLine(
                                Manifest.MakeStandardPathString(currentManfestDirInfo) +
                                " [IGNORED DIRECTORY AND CANNOT ACCESS]");
                        }
                    }
                    else
                    {
                        ForceWriteLine("Could not access contents of: " +
                                       currentDirectoryInfo.FullName);
                    }

                    return;
                }

                foreach (FileInfo nextFileInfo in fileList)
                {
                    fileDict.Add(nextFileInfo.Name.Normalize(), nextFileInfo);
                }

                DirectoryInfo[] dirList =
                    currentDirectoryInfo.GetDirectories();

                foreach (DirectoryInfo nextDirInfo in dirList)
                {
                    dirDict.Add(nextDirInfo.Name.Normalize(), nextDirInfo);
                }
            }

            // Clone in case we modify during iteration
            List <ManifestFileInfo> fileListClone =
                new List <ManifestFileInfo>(currentManfestDirInfo.Files.Values);

            // Iterate through existing manifest entries
            foreach (ManifestFileInfo nextManFileInfo in fileListClone)
            {
                if (ShowProgress)
                {
                    Write(Manifest.MakeStandardPathString(nextManFileInfo));
                }

                if (fileDict.ContainsKey(nextManFileInfo.Name))
                {
                    FileCheckedCount++;

                    FileInfo nextFileInfo = fileDict[nextManFileInfo.Name];

                    if (IgnoreFile(Manifest.MakeStandardPathString(nextManFileInfo)))
                    {
                        Write(" [NEWLY IGNORED]");

                        currentManfestDirInfo.Files.Remove(
                            nextManFileInfo.Name);

                        NewlyIgnoredFiles.Add(nextManFileInfo);
                    }
                    else if (nextFileInfo.Length != nextManFileInfo.FileLength &&
                             Update == false &&
                             AlwaysCheckHash == false)
                    {
                        // Don't compute hash if we aren't doing an update
                        Write(" [DIFFERENT]");
                        ChangedFiles.Add(nextManFileInfo);
                    }
                    else if (AlwaysCheckHash == true ||
                             MakeNewHash == true ||
                             nextManFileInfo.FileHash == null ||
                             Manifest.CompareManifestDateToFilesystemDate(nextFileInfo.LastWriteTimeUtc, nextManFileInfo.LastModifiedUtc) == false ||
                             nextFileInfo.Length != nextManFileInfo.FileLength)
                    {
                        FileHash checkHash = null;

                        Exception exception = null;
                        try
                        {
                            string hashType = Manifest.DefaultHashMethod;
                            if (nextManFileInfo.FileHash != null)
                            {
                                hashType = nextManFileInfo.FileHash.HashType;
                            }

                            checkHash = FileHash.ComputeHash(
                                nextFileInfo,
                                hashType);
                        }
                        catch (Exception ex)
                        {
                            exception = ex;
                        }

                        if (exception != null)
                        {
                            WriteLine(" [ERROR]");
                            WriteLine(exception.ToString());

                            ErrorFiles.Add(nextManFileInfo);
                        }
                        else
                        {
                            if (nextManFileInfo.FileHash == null)
                            {
                                Write(" [NULL HASH IN MANIFEST]");
                                ChangedFiles.Add(nextManFileInfo);
                            }
                            else if (checkHash.Equals(nextManFileInfo.FileHash) == false)
                            {
                                Write(" [DIFFERENT]");
                                ChangedFiles.Add(nextManFileInfo);
                            }
                            else
                            {
                                if (Manifest.CompareManifestDateToFilesystemDate(
                                        nextFileInfo.LastWriteTimeUtc,
                                        nextManFileInfo.LastModifiedUtc) == false)
                                {
                                    Write(" [LAST MODIFIED DATE]");
                                    LastModifiedDateFiles.Add(nextManFileInfo);

                                    if (BackDate == true)
                                    {
                                        nextFileInfo.LastWriteTimeUtc =
                                            nextManFileInfo.LastModifiedUtc;
                                    }
                                }
                            }
                        }

                        FileHash newHash = checkHash;
                        if (MakeNewHash)
                        {
                            newHash = FileHash.ComputeHash(
                                nextFileInfo,
                                GetNewHashType(Manifest));
                        }

                        // Update hash and last modified date accordingly
                        nextManFileInfo.FileHash = newHash;

                        nextManFileInfo.LastModifiedUtc = nextFileInfo.LastWriteTimeUtc;
                        nextManFileInfo.FileLength      = nextFileInfo.Length;
                    }
                    else
                    {
                        Write(" [SKIPPED]");
                    }
                }
                else
                {
                    Write(" [MISSING]");
                    currentManfestDirInfo.Files.Remove(nextManFileInfo.Name);
                    MissingFiles.Add(nextManFileInfo);
                }

                WriteLine("");
            }

            // Clone in case we modify during iteration
            List <ManifestDirectoryInfo> directoryListClone =
                new List <ManifestDirectoryInfo>(
                    currentManfestDirInfo.Subdirectories.Values);

            foreach (ManifestDirectoryInfo nextManDirInfo in
                     directoryListClone)
            {
                DirectoryInfo nextDirInfo = null;
                if (dirDict.ContainsKey(nextManDirInfo.Name))
                {
                    nextDirInfo = dirDict[nextManDirInfo.Name];
                }

                UpdateRecursive(
                    nextDirInfo,
                    nextManDirInfo);

                if (nextManDirInfo.Empty)
                {
                    currentManfestDirInfo.Subdirectories.Remove(
                        nextManDirInfo.Name);
                }
            }

            // Look for new files
            foreach (String nextFileName in fileDict.Keys)
            {
                FileInfo nextFileInfo = fileDict[nextFileName];

                if (currentManfestDirInfo.Files.ContainsKey(
                        nextFileName) == false)
                {
                    ManifestFileInfo newManFileInfo =
                        new ManifestFileInfo(
                            nextFileName,
                            currentManfestDirInfo);

                    Write(Manifest.MakeStandardPathString(newManFileInfo));

                    if (IgnoreFile(Manifest.MakeStandardPathString(newManFileInfo)))
                    {
                        IgnoredFiles.Add(newManFileInfo);

                        // Don't groom the manifest file!
                        if (Manifest.MakeNativePathString(newManFileInfo) !=
                            ManifestNativeFilePath)
                        {
                            IgnoredFilesForGroom.Add(nextFileInfo);
                        }

                        Write(" [IGNORED]");
                    }
                    else
                    {
                        FileCheckedCount++;

                        bool checkHash = false;
                        if (Update == true ||
                            AlwaysCheckHash == true ||
                            TrackMoves == true)
                        {
                            checkHash = true;
                        }


                        Exception exception = null;
                        if (checkHash)
                        {
                            try
                            {
                                newManFileInfo.FileHash =
                                    FileHash.ComputeHash(
                                        nextFileInfo,
                                        GetNewHashType(Manifest));
                            }
                            catch (Exception ex)
                            {
                                exception = ex;
                            }
                        }

                        if (checkHash && newManFileInfo.FileHash == null)
                        {
                            ErrorFiles.Add(newManFileInfo);

                            WriteLine(" [ERROR]");
                            WriteLine(exception.ToString());
                        }
                        else
                        {
                            NewFiles.Add(newManFileInfo);
                            NewFilesForGroom.Add(nextFileInfo);
                            Write(" [NEW]");
                        }

                        newManFileInfo.FileLength =
                            nextFileInfo.Length;

                        newManFileInfo.LastModifiedUtc =
                            nextFileInfo.LastWriteTimeUtc;

                        newManFileInfo.RegisteredUtc =
                            DateTime.Now.ToUniversalTime();

                        currentManfestDirInfo.Files.Add(
                            nextFileName,
                            newManFileInfo);
                    }

                    WriteLine("");
                }
            }

            // Recurse looking for new directories
            foreach (String nextDirName in dirDict.Keys)
            {
                DirectoryInfo nextDirInfo = dirDict[nextDirName];

                if (currentManfestDirInfo.Subdirectories.ContainsKey(
                        nextDirName) == false)
                {
                    ManifestDirectoryInfo nextManDirInfo =
                        new ManifestDirectoryInfo(
                            nextDirName,
                            currentManfestDirInfo);

                    currentManfestDirInfo.Subdirectories.Add(
                        nextDirName,
                        nextManDirInfo);

                    UpdateRecursive(
                        nextDirInfo,
                        nextManDirInfo);

                    if (nextManDirInfo.Empty)
                    {
                        currentManfestDirInfo.Subdirectories.Remove(
                            nextDirName);
                    }
                }
            }
        }