/// <summary>Estimate viability of operation.</summary> /// <exception cref="FileNotFoundException">If <see cref="SrcPath"/> is not found.</exception> /// <exception cref="FileSystemExceptionFileExists">If <see cref="Path"/> already exists.</exception> protected override void InnerEstimate() { PathConverter pathConverter = new PathConverter(SrcPath, Path); List <IEntry> queue = new List <IEntry>(); // Src IEntry e = SrcFileSystem.GetEntry(SrcPath, srcOption.OptionIntersection(session.Option)); // Src not found if (e == null) { // Throw if (EffectivePolicy.HasFlag(OperationPolicy.SrcThrow)) { throw new FileNotFoundException(SrcPath); } // Skip if (EffectivePolicy.HasFlag(OperationPolicy.SrcSkip)) { SetState(OperationState.Skipped); return; } // Fail anyway throw new FileNotFoundException(SrcPath); } queue.Add(e); while (queue.Count > 0) { try { // Next entry int lastIx = queue.Count - 1; IEntry entry = queue[lastIx]; queue.RemoveAt(lastIx); // Omit package mounts if (session.Policy.HasFlag(OperationPolicy.OmitMountedPackages) && entry.IsPackageMount()) { continue; } // Process directory if (entry.IsDirectory()) { // Browse children IDirectoryContent content = SrcFileSystem.Browse(entry.Path, srcOption.OptionIntersection(session.Option)); // Assert children don't refer to the parent of the parent foreach (IEntry child in content) { if (entry.Path.StartsWith(child.Path)) { throw new IOException($"{child.Path} cannot be child of {entry.Path}"); } } // Visit child for (int i = content.Count - 1; i >= 0; i--) { queue.Add(content[i]); } // Convert path string _dstPath; if (!pathConverter.ParentToChild(entry.Path, out _dstPath)) { throw new Exception("Failed to convert path"); } // Add op if (_dstPath != "") { Ops.Add(new CreateDirectory(session, FileSystem, _dstPath, Option.OptionIntersection(session.Option), OpPolicy)); } } // Process file else if (entry.IsFile()) { // Convert path string _dstPath; if (!pathConverter.ParentToChild(entry.Path, out _dstPath)) { throw new Exception("Failed to convert path"); } // Add op Ops.Add(new CopyFile(session, SrcFileSystem, entry.Path, FileSystem, _dstPath, srcOption.OptionIntersection(session.Option), Option.OptionIntersection(session.Option), OpPolicy)); } } catch (Exception error) when(SetError(error)) { } } base.InnerEstimate(); }