private IEnumerable <IList <RobocopyMetadata> > GetBuckets() { IList <RobocopyMetadata> allSources = new List <RobocopyMetadata>(); IList <IList <RobocopyMetadata> > allBuckets = new List <IList <RobocopyMetadata> >(); foreach (ITaskItem item in Sources ?? Enumerable.Empty <ITaskItem>()) { if (RobocopyMetadata.TryParse(item, Log, FileSystem.DirectoryExists, out RobocopyMetadata metadata)) { allSources.Add(metadata); } } int bucketNum = -1; int itemIndex = 0; while (allSources.Count > 0) { RobocopyMetadata first = allSources.First(); allSources.RemoveAt(0); List <RobocopyMetadata> bucket = new List <RobocopyMetadata> { first, }; allBuckets.Add(bucket); if (ShowDiagnosticTrace) { first.Dump(Log, ++bucketNum, 0); itemIndex = 1; } for (int i = 0; i < allSources.Count; ++i) { RobocopyMetadata item = allSources[i]; if (string.Equals(item.SourceFolder, first.SourceFolder, StringComparison.OrdinalIgnoreCase) && item.HasWildcardMatches == first.HasWildcardMatches && item.IsRecursive == first.IsRecursive) { bucket.Add(item); allSources.RemoveAt(i); --i; if (ShowDiagnosticTrace) { item.Dump(Log, bucketNum, itemIndex++); } } } } return(allBuckets); }
private void CopyItems(IList <RobocopyMetadata> items) { // buckets are grouped by source, IsRecursive, and HasWildcardMatches RobocopyMetadata first = items.First(); bool isRecursive = first.IsRecursive; bool hasWildcards = first.HasWildcardMatches; DirectoryInfo source = new DirectoryInfo(first.SourceFolder); if (hasWildcards || isRecursive) { string match = GetMatchString(items); CopySearch(items, isRecursive, match, source, null); } else { // optimized path for direct file copies CopyItems(items, source); } }
public static bool TryParse(ITaskItem item, TaskLoggingHelper log, Func <string, bool> directoryExists, out RobocopyMetadata metadata) { metadata = null; if (string.IsNullOrEmpty(item.GetMetadata("DestinationFolder"))) { log.LogError("A value for \"DestinationFolder\" is required for the item \"{0}\".", item.ItemSpec); return(false); } // A common error - a property doesn't resolve and it references the drive root if (item.ItemSpec.StartsWith(@"\") && !item.ItemSpec.StartsWith(@"\\")) { log.LogError("The specified source location \"{0}\" cannot start with '\'", item.ItemSpec); return(false); } string source; try { source = Path.GetFullPath(item.ItemSpec).TrimEnd(Path.DirectorySeparatorChar); } catch (Exception e) { log.LogError("Failed to expand the path \"{0}\".", item.ItemSpec); log.LogErrorFromException(e); return(false); } metadata = new RobocopyMetadata { IsRecursive = item.GetMetadataBoolean(nameof(IsRecursive)), VerifyExists = item.GetMetadataBoolean(nameof(VerifyExists)), AlwaysCopy = item.GetMetadataBoolean(nameof(AlwaysCopy), defaultValue: false), OnlyNewer = item.GetMetadataBoolean(nameof(OnlyNewer), defaultValue: false), }; foreach (string destination in item.GetMetadata("DestinationFolder").Split(DestinationSplitter, StringSplitOptions.RemoveEmptyEntries)) { if (destination.StartsWith(@"\") && !destination.StartsWith(@"\\")) { log.LogError("The specified destination \"{0}\" cannot start with '{1}'", destination, Path.DirectorySeparatorChar); return(false); } try { metadata.DestinationFolders.Add(Path.GetFullPath(destination).TrimEnd(Path.DirectorySeparatorChar)); } catch (Exception e) { log.LogError("Failed to expand the path \"{0}\".", item.ItemSpec); log.LogErrorFromException(e); return(false); } } if (directoryExists(source)) { metadata.SourceFolder = source; metadata.SplitItems("FileMatch", item); metadata.SplitItems("FileExclude", item); metadata.SplitItems("DirExclude", item); metadata.HasWildcardMatches = metadata.FileRegexMatches != null || metadata.FileRegexExcludes != null || metadata.DirRegexExcludes != null; } else { metadata.IsRecursive = false; metadata.SourceFolder = Path.GetDirectoryName(source); metadata.FileMatches = new[] { Path.GetFileName(source) }; if (metadata.SourceFolder == null) { return(false); } } return(true); }
private void CopyFile(FileInfo sourceFile, FileInfo destFile, bool createDirs, RobocopyMetadata metadata) { if (createDirs) { CreateDirectoryWithRetries(destFile.DirectoryName); } for (int retry = 0; retry <= RetryCount; ++retry) { try { if (metadata.ShouldCopy(FileSystem, sourceFile, destFile)) { destFile = FileSystem.CopyFile(sourceFile, destFile.FullName, true); destFile.Attributes = FileAttributes.Normal; destFile.LastWriteTime = sourceFile.LastWriteTime; Log.LogMessage(MessageImportance.Low, "Copied {0} to {1}", sourceFile.FullName, destFile.FullName); } else { Log.LogMessage(MessageImportance.Low, "Skipped copying {0} to {1}", sourceFile.FullName, destFile.FullName); } break; } catch (IOException e) { LogCopyFailureAndSleep(retry, "Failed to copy {0} to {1}. {2}", sourceFile.FullName, destFile.FullName, e.Message); } } }