} // func CompareFile private void CompareDirectory(DirectoryInfo source, DirectoryInfo target) { if (!source.Exists) { throw new ArgumentException($"Path not found ({source.FullName})."); } // get the files of the current directories var sourceItems = GetFileItems(source); var targetItems = target.Exists ? target.GetFileSystemInfos() : emptyFileSystemInfos; if (!copyStarted) { if (unchecked (Environment.TickCount - lastScanEmitted) > 500) { EnqueueAction(() => bar.CurrentOperation = $"Scan: {GetRelativePath(source.FullName, sourceOffset) }"); lastScanEmitted = Environment.TickCount; } } // compare for (var i = 0; i < sourceItems.Length; i++) { var fsi = sourceItems[i]; // is this path filtered var currentSourcePath = GetRelativePath(fsi.FullName, sourceOffset); if (rules.IsFiltered(currentSourcePath)) { EnqueueAction(() => WriteVerbose($"Skip: {currentSourcePath}")); continue; } // compare the file items var index = Array.FindIndex(targetItems, c => c != null && String.Compare(c.Name, fsi.Name, StringComparison.OrdinalIgnoreCase) == 0); if (fsi is DirectoryInfo di) { if ((di.Attributes & FileAttributes.ReparsePoint) != 0) { continue; // skip reparse points } if (index == -1) { CompareDirectory(di, new DirectoryInfo(Path.Combine(target.FullName, fsi.Name))); } else { CompareDirectory(di, (DirectoryInfo)targetItems[index]); } } else if (fsi is FileInfo fi) { if (index == -1) { CompareFile(fi, new FileInfo(Path.Combine(target.FullName, fi.Name))); } else { CompareFile(fi, (FileInfo)targetItems[index]); } } else { throw new ArgumentException(); } if (index != -1) { targetItems[index] = null; } if (Stopping) { return; } } // Remove items that are not touched for (var j = 0; j < targetItems.Length; j++) { var fsi = targetItems[j]; if (fsi != null) { EnqueueAction(() => RemoveItem(fsi)); } } } // func CompareDirectory
} // proc UpdateMetaData protected override void ProcessRecord() { var notify = new CmdletNotify(this); var totalBytes = 0L; // Lese den Index ein var index = new FileIndex(); index.ReadIndex(notify, Path.Combine(Source, "index.txt.gz")); // Suche alle aktiven Archive var archives = new Dictionary <string, List <FileIndexItem> >(StringComparer.OrdinalIgnoreCase); using (var bar = notify.CreateStatus("Wiederherstellen eines Verzeichnisses", $"Wiederherstellen von {Source}...")) { var filter = new FileFilterRules(Filter); // Erzeuge Filter und entferne alle Dateien aus dem Index die dem nicht entsprechen if (filter.IsEmpty) { foreach (var c in index) { AddArchive(archives, c, ref totalBytes); } } else { var remove = new List <FileIndexItem>(); foreach (var c in index) { if (filter.IsFiltered(c.RelativePath)) { AddArchive(archives, c, ref totalBytes); } else { remove.Add(c); } } foreach (var c in remove) { index.RemoveEntry(c); } } // Entpacke die Archvie bar.StartRemaining(); bar.Maximum = totalBytes; foreach (var c in archives) { if (Stuff.IsGZipFile(c.Key) || Stuff.IsNoPackFile(c.Key)) // GZip-Datei { using (var src = Stuff.OpenRead(new FileInfo(Path.Combine(Source, c.Key)), notify, CompressMode.Auto)) { var srcFile = c.Value[0]; var dstFile = new FileInfo(Path.Combine(Target, srcFile.RelativePath)); using (var dst = Override ? Stuff.OpenWrite(dstFile, notify) : Stuff.OpenCreate(dstFile, notify)) { dst.SetLength(srcFile.Length); Stuff.CopyRawBytes(bar, srcFile.RelativePath, srcFile.Length, src, dst); } // Aktualisiere die Attribute UpdateMetaData(notify, srcFile, dstFile); } } else // zip-Datei { using (var zipStream = Stuff.OpenRead(new FileInfo(Path.Combine(Source, c.Key)), notify, CompressMode.Stored)) using (var zip = new ZipInputStream(zipStream)) { var srcEntry = zip.GetNextEntry(); while (srcEntry != null) { // Suche den passenden Index var srcIndex = c.Value.Find(c2 => String.Compare(srcEntry.Name, ZipEntry.CleanName(c2.RelativePath), StringComparison.OrdinalIgnoreCase) == 0); if (srcIndex != null) { var dstFile = new FileInfo(Path.Combine(Target, srcIndex.RelativePath)); using (var dst = Override ? Stuff.OpenWrite(dstFile, notify) : Stuff.OpenCreate(dstFile, notify)) { dst.SetLength(srcIndex.Length); Stuff.CopyRawBytes(bar, srcIndex.RelativePath, srcIndex.Length, zip, dst); } // Aktualisiere die Attribute UpdateMetaData(notify, srcIndex, dstFile); } else { zip.CloseEntry(); } // Schließe den Eintrag ab srcEntry = zip.GetNextEntry(); } } } } } } // proc ProcessRecord