Exemple #1
0
        /// <summary>
        /// Original copy code that performs single-threaded copies.
        /// Used for single-file copies and when parallelism is 1.
        /// </summary>
        private bool CopySingleThreaded(
            CopyFileWithState copyFile,
            out List <ITaskItem> destinationFilesSuccessfullyCopied)
        {
            bool success = true;

            destinationFilesSuccessfullyCopied = new List <ITaskItem>(DestinationFiles.Length);

            // Set of files we actually copied and the location from which they were originally copied.  The purpose
            // of this collection is to let us skip copying duplicate files.  We will only copy the file if it
            // either has never been copied to this destination before (key doesn't exist) or if we have copied it but
            // from a different location (value is different.)
            // { dest -> source }
            var filesActuallyCopied = new Dictionary <string, string>(
                DestinationFiles.Length, // Set length to common case of 1:1 source->dest.
                StringComparer.OrdinalIgnoreCase);

            // Now that we have a list of destinationFolder files, copy from source to destinationFolder.
            for (int i = 0; i < SourceFiles.Length && !_cancellationTokenSource.IsCancellationRequested; ++i)
            {
                bool   copyComplete = false;
                string destPath     = DestinationFiles[i].ItemSpec;
                MSBuildEventSource.Log.CopyUpToDateStart(destPath);
                if (filesActuallyCopied.TryGetValue(destPath, out string originalSource))
                {
                    if (String.Equals(originalSource, SourceFiles[i].ItemSpec, StringComparison.OrdinalIgnoreCase))
                    {
                        // Already copied from this location, don't copy again.
                        copyComplete = true;
                    }
                }

                if (!copyComplete)
                {
                    if (DoCopyIfNecessary(new FileState(SourceFiles[i].ItemSpec), new FileState(DestinationFiles[i].ItemSpec), copyFile))
                    {
                        filesActuallyCopied[destPath] = SourceFiles[i].ItemSpec;
                        copyComplete = true;
                    }
                    else
                    {
                        success = false;
                    }
                }
                else
                {
                    MSBuildEventSource.Log.CopyUpToDateStop(destPath, true);
                }

                if (copyComplete)
                {
                    SourceFiles[i].CopyMetadataTo(DestinationFiles[i]);
                    destinationFilesSuccessfullyCopied.Add(DestinationFiles[i]);
                }
            }

            return(success);
        }
        internal bool Execute(CopyFileWithState copyFile)
        {
            if ((this.sourceFiles == null) || (this.sourceFiles.Length == 0))
            {
                this.destinationFiles = new TaskItem[0];
                this.copiedFiles      = new TaskItem[0];
                return(true);
            }
            if (!this.ValidateInputs() || !this.InitializeDestinationFiles())
            {
                return(false);
            }
            bool                        flag       = true;
            List <ITaskItem>            list       = new List <ITaskItem>();
            Dictionary <string, string> dictionary = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);

            for (int i = 0; i < this.sourceFiles.Length; i++)
            {
                string str;
                bool   flag2 = false;
                if (dictionary.TryGetValue(this.destinationFiles[i].ItemSpec, out str) && string.Equals(str, this.sourceFiles[i].ItemSpec, StringComparison.OrdinalIgnoreCase))
                {
                    flag2 = true;
                }
                if (!flag2)
                {
                    if (this.DoCopyIfNecessary(new Microsoft.Build.Tasks.FileState(this.sourceFiles[i].ItemSpec), new Microsoft.Build.Tasks.FileState(this.destinationFiles[i].ItemSpec), copyFile))
                    {
                        dictionary[this.destinationFiles[i].ItemSpec] = this.sourceFiles[i].ItemSpec;
                        flag2 = true;
                    }
                    else
                    {
                        flag = false;
                    }
                }
                if (flag2)
                {
                    this.sourceFiles[i].CopyMetadataTo(this.destinationFiles[i]);
                    list.Add(this.destinationFiles[i]);
                }
            }
            this.copiedFiles = list.ToArray();
            return(flag);
        }
 private bool DoCopyIfNecessary(Microsoft.Build.Tasks.FileState sourceFileState, Microsoft.Build.Tasks.FileState destinationFileState, CopyFileWithState copyFile)
 {
     bool flag = true;
     try
     {
         if (this.skipUnchangedFiles && IsMatchingSizeAndTimeStamp(sourceFileState, destinationFileState))
         {
             base.Log.LogMessageFromResources(MessageImportance.Low, "Copy.DidNotCopyBecauseOfFileMatch", new object[] { sourceFileState.Name, destinationFileState.Name, "SkipUnchangedFiles", "true" });
             return flag;
         }
         if (string.Compare(sourceFileState.Name, destinationFileState.Name, StringComparison.OrdinalIgnoreCase) != 0)
         {
             flag = this.DoCopyWithRetries(sourceFileState, destinationFileState, copyFile);
         }
     }
     catch (PathTooLongException exception)
     {
         base.Log.LogErrorWithCodeFromResources("Copy.Error", new object[] { sourceFileState.Name, destinationFileState.Name, exception.Message });
         flag = false;
     }
     catch (IOException exception2)
     {
         if (this.PathsAreIdentical(sourceFileState.Name, destinationFileState.Name))
         {
             return flag;
         }
         if (Microsoft.Build.Shared.ExceptionHandling.NotExpectedException(exception2))
         {
             throw;
         }
         base.Log.LogErrorWithCodeFromResources("Copy.Error", new object[] { sourceFileState.Name, destinationFileState.Name, exception2.Message });
         flag = false;
     }
     catch (Exception exception3)
     {
         if (Microsoft.Build.Shared.ExceptionHandling.NotExpectedException(exception3))
         {
             throw;
         }
         base.Log.LogErrorWithCodeFromResources("Copy.Error", new object[] { sourceFileState.Name, destinationFileState.Name, exception3.Message });
         flag = false;
     }
     return flag;
 }
Exemple #4
0
        /// <summary>
        /// Copy the files.
        /// </summary>
        /// <param name="copyFile">Delegate used to copy the files.</param>
        /// <param name="parallelism">
        /// Thread parallelism allowed during copies. 1 uses the original algorithm, >1 uses newer algorithm.
        /// </param>
        /// <param name="staticEvaluation">Whether we are in static mode.</param>
        internal bool Execute
        (
            CopyFileWithState copyFile,
            int parallelism,
            bool staticEvaluation
        )
        {
            // If there are no source files then just return success.
            if (SourceFiles == null || SourceFiles.Length == 0)
            {
                DestinationFiles = Array.Empty <ITaskItem>();
                CopiedFiles      = Array.Empty <ITaskItem>();
                return(true);
            }

            if (!(ValidateInputs() && InitializeDestinationFiles()))
            {
                return(false);
            }

            // Environment variable stomps on user-requested value if it's set.
            if (Environment.GetEnvironmentVariable(AlwaysOverwriteReadOnlyFilesEnvVar) != null)
            {
                OverwriteReadOnlyFiles = true;
            }

            // Track successfully copied subset.
            List <ITaskItem> destinationFilesSuccessfullyCopied;

            // Use single-threaded code path when requested or when there is only copy to make
            // (no need to create all the parallel infrastructure for that case).
            bool success = parallelism == 1 || DestinationFiles.Length == 1
                ? CopySingleThreaded(copyFile, staticEvaluation, out destinationFilesSuccessfullyCopied)
                : CopyParallel(copyFile, parallelism, staticEvaluation, out destinationFilesSuccessfullyCopied);

            // copiedFiles contains only the copies that were successful.
            CopiedFiles = destinationFilesSuccessfullyCopied.ToArray();

            return(success && !_cancellationTokenSource.IsCancellationRequested);
        }
Exemple #5
0
        /// <summary>
        /// Copy one file with the appropriate number of retries if it fails.
        /// </summary>
        private bool DoCopyWithRetries(FileState sourceFileState, FileState destinationFileState, CopyFileWithState copyFile)
        {
            int retries = 0;

            while (!_cancellationTokenSource.IsCancellationRequested)
            {
                try
                {
                    bool?result = copyFile(sourceFileState, destinationFileState);
                    if (result.HasValue)
                    {
                        return(result.Value);
                    }
                }
                catch (OperationCanceledException)
                {
                    break;
                }
                catch (Exception e) when(ExceptionHandling.IsIoRelatedException(e))
                {
                    if (e is ArgumentException ||     // Invalid chars
                        e is NotSupportedException || // Colon in the middle of the path
                        e is PathTooLongException)
                    {
                        // No use retrying these cases
                        throw;
                    }

                    if (e is UnauthorizedAccessException || e is IOException) // Not clear why we can get one and not the other
                    {
                        int code = Marshal.GetHRForException(e);

                        LogDiagnostic("Got {0} copying {1} to {2} and HR is {3}", e.ToString(), sourceFileState.Name, destinationFileState.Name, code);
                        if (code == NativeMethods.ERROR_ACCESS_DENIED)
                        {
                            // ERROR_ACCESS_DENIED can either mean there's an ACL preventing us, or the file has the readonly bit set.
                            // In either case, that's likely not a race, and retrying won't help.
                            // Retrying is mainly for ERROR_SHARING_VIOLATION, where someone else is using the file right now.
                            // However, there is a limited set of circumstances where a copy failure will show up as access denied due
                            // to a failure to reset the readonly bit properly, in which case retrying will succeed.  This seems to be
                            // a pretty edge scenario, but since some of our internal builds appear to be hitting it, provide a secret
                            // environment variable to allow overriding the default behavior and forcing retries in this circumstance as well.
                            if (!s_alwaysRetryCopy)
                            {
                                throw;
                            }
                            else
                            {
                                LogDiagnostic("Retrying on ERROR_ACCESS_DENIED because MSBUILDALWAYSRETRY = 1");
                            }
                        }
                    }

                    if (e is IOException && DestinationFolder != null && FileSystems.Default.FileExists(DestinationFolder.ItemSpec))
                    {
                        // We failed to create the DestinationFolder because it's an existing file. No sense retrying.
                        // We don't check for this case upstream because it'd be another hit to the filesystem.
                        throw;
                    }

                    if (e is IOException)
                    {
                        // if this was just because the source and destination files are the
                        // same file, that's not a failure.
                        // Note -- we check this exceptional case here, not before the copy, for perf.
                        if (PathsAreIdentical(sourceFileState.Name, destinationFileState.Name))
                        {
                            return(true);
                        }
                    }

                    if (retries < Retries)
                    {
                        retries++;
                        Log.LogWarningWithCodeFromResources("Copy.Retrying", sourceFileState.Name,
                                                            destinationFileState.Name, retries, RetryDelayMilliseconds, e.Message,
                                                            GetLockedFileMessage(destinationFileState.Name));

                        // if we have to retry for some reason, wipe the state -- it may not be correct anymore.
                        destinationFileState.Reset();

                        Thread.Sleep(RetryDelayMilliseconds);
                        continue;
                    }
                    else if (Retries > 0)
                    {
                        // Exception message is logged in caller
                        Log.LogErrorWithCodeFromResources("Copy.ExceededRetries", sourceFileState.Name,
                                                          destinationFileState.Name, Retries, GetLockedFileMessage(destinationFileState.Name));
                        throw;
                    }
                    else
                    {
                        throw;
                    }
                }

                if (retries < Retries)
                {
                    retries++;
                    Log.LogWarningWithCodeFromResources("Copy.Retrying", sourceFileState.Name,
                                                        destinationFileState.Name, retries, RetryDelayMilliseconds, String.Empty /* no details */,
                                                        GetLockedFileMessage(destinationFileState.Name));

                    // if we have to retry for some reason, wipe the state -- it may not be correct anymore.
                    destinationFileState.Reset();

                    Thread.Sleep(RetryDelayMilliseconds);
                }
                else if (Retries > 0)
                {
                    Log.LogErrorWithCodeFromResources("Copy.ExceededRetries", sourceFileState.Name,
                                                      destinationFileState.Name, Retries, GetLockedFileMessage(destinationFileState.Name));
                    return(false);
                }
                else
                {
                    return(false);
                }
            }

            // Canceling
            return(false);
        }
Exemple #6
0
        /// <summary>
        /// Copy source to destination, unless SkipUnchangedFiles is true and they are equivalent.
        /// </summary>
        /// <returns>True if the file was copied or, on SkipUnchangedFiles, the file was equivalent.</returns>
        private bool DoCopyIfNecessary(FileState sourceFileState, FileState destinationFileState, CopyFileWithState copyFile)
        {
            bool success = true;

            try
            {
                if (SkipUnchangedFiles && IsMatchingSizeAndTimeStamp(sourceFileState, destinationFileState))
                {
                    // If we got here, then the file's time and size match AND
                    // the user set the SkipUnchangedFiles flag which means we
                    // should skip matching files.
                    Log.LogMessageFromResources(
                        MessageImportance.Low,
                        "Copy.DidNotCopyBecauseOfFileMatch",
                        sourceFileState.Name,
                        destinationFileState.Name,
                        "SkipUnchangedFiles",
                        "true"
                        );
                }
                // We only do the cheap check for identicalness here, we try the more expensive check
                // of comparing the fullpaths of source and destination to see if they are identical,
                // in the exception handler lower down.
                else if (0 != String.Compare(
                             sourceFileState.Name,
                             destinationFileState.Name,
                             StringComparison.OrdinalIgnoreCase))
                {
                    success = DoCopyWithRetries(sourceFileState, destinationFileState, copyFile);
                }
            }
            catch (OperationCanceledException)
            {
                success = false;
            }
            catch (PathTooLongException e)
            {
                Log.LogErrorWithCodeFromResources("Copy.Error", sourceFileState.Name, destinationFileState.Name, e.Message);
                success = false;
            }
            catch (Exception e) when(ExceptionHandling.IsIoRelatedException(e))
            {
                Log.LogErrorWithCodeFromResources("Copy.Error", sourceFileState.Name, destinationFileState.Name, e.Message);
                success = false;
            }

            return(success);
        }
Exemple #7
0
        /// <summary>
        /// Parallelize I/O with the same semantics as the single-threaded copy method above.
        /// ResolveAssemblyReferences tends to generate longer and longer lists of files to send
        /// to CopyTask as we get further and further down the dependency graph.
        /// The OS can handle a lot of parallel I/O so let's minimize wall clock time to get
        /// it all done.
        /// </summary>
        private bool CopyParallel(
            CopyFileWithState copyFile,
            int parallelism,
            out List <ITaskItem> destinationFilesSuccessfullyCopied)
        {
            bool success = true;

            // We must supply the same semantics as the single-threaded version above:
            //
            // - For copy operations in the list that have the same destination, we must
            //   provide for in-order copy attempts that allow re-copying different files
            //   and avoiding copies for later files that match SkipUnchangedFiles semantics.
            //   We must also add a destination file copy item for each attempt.
            // - The order of entries in destinationFilesSuccessfullyCopied must match
            //   the order of entries passed in, along with copied metadata.
            // - Metadata must not be copied to destination item if the copy operation failed.
            //
            // We split the work into different Tasks:
            //
            // - Entries with unique destination file paths each get their own parallel operation.
            // - Each subset of copies into the same destination get their own Task to run
            //   the single-threaded logic in order.
            //
            // At the end we reassemble the result list in the same order as was passed in.

            // Map: Destination path -> indexes in SourceFiles/DestinationItems array indices (ordered low->high).
            var partitionsByDestination = new Dictionary <string, List <int> >(
                DestinationFiles.Length, // Set length to common case of 1:1 source->dest.
                StringComparer.OrdinalIgnoreCase);

            for (int i = 0; i < SourceFiles.Length && !_cancellationTokenSource.IsCancellationRequested; ++i)
            {
                ITaskItem destItem = DestinationFiles[i];
                string    destPath = destItem.ItemSpec;
                if (!partitionsByDestination.TryGetValue(destPath, out List <int> sourceIndices))
                {
                    // Use 1 for list length - common case is for no destination overlap.
                    sourceIndices = new List <int>(1);
                    partitionsByDestination[destPath] = sourceIndices;
                }
                sourceIndices.Add(i);
            }

            // Lockless flags updated from each thread - each needs to be a processor word for atomicity.
            var successFlags       = new IntPtr[DestinationFiles.Length];
            var actionBlockOptions = new ExecutionDataflowBlockOptions
            {
                MaxDegreeOfParallelism = parallelism,
                CancellationToken      = _cancellationTokenSource.Token
            };
            var partitionCopyActionBlock = new ActionBlock <List <int> >(
                async(List <int> partition) =>
            {
                // Break from synchronous thread context of caller to get onto thread pool thread.
                await System.Threading.Tasks.Task.Yield();

                for (int partitionIndex = 0; partitionIndex < partition.Count && !_cancellationTokenSource.IsCancellationRequested; partitionIndex++)
                {
                    int fileIndex        = partition[partitionIndex];
                    ITaskItem sourceItem = SourceFiles[fileIndex];
                    ITaskItem destItem   = DestinationFiles[fileIndex];
                    string sourcePath    = sourceItem.ItemSpec;

                    // Check if we just copied from this location to the destination, don't copy again.
                    bool copyComplete = partitionIndex > 0 &&
                                        String.Equals(
                        sourcePath,
                        SourceFiles[partition[partitionIndex - 1]].ItemSpec,
                        StringComparison.OrdinalIgnoreCase);

                    if (!copyComplete)
                    {
                        if (DoCopyIfNecessary(
                                new FileState(sourceItem.ItemSpec),
                                new FileState(destItem.ItemSpec),
                                copyFile))
                        {
                            copyComplete = true;
                        }
                        else
                        {
                            // Thread race to set outer variable but they race to set the same (false) value.
                            success = false;
                        }
                    }

                    if (copyComplete)
                    {
                        sourceItem.CopyMetadataTo(destItem);
                        successFlags[fileIndex] = (IntPtr)1;
                    }
                }
            },
                actionBlockOptions);

            foreach (List <int> partition in partitionsByDestination.Values)
            {
                bool partitionAccepted = partitionCopyActionBlock.Post(partition);
                if (!partitionAccepted)
                {
                    // Retail assert...
                    ErrorUtilities.VerifyThrow(false,
                                               "Failed posting a file copy to an ActionBlock. Should not happen with block at max int capacity.");
                }
            }

            partitionCopyActionBlock.Complete();
            partitionCopyActionBlock.Completion.GetAwaiter().GetResult();

            // Assemble an in-order list of destination items that succeeded.
            destinationFilesSuccessfullyCopied = new List <ITaskItem>(DestinationFiles.Length);
            for (int i = 0; i < successFlags.Length; i++)
            {
                if (successFlags[i] != (IntPtr)0)
                {
                    destinationFilesSuccessfullyCopied.Add(DestinationFiles[i]);
                }
            }

            return(success);
        }
Exemple #8
0
        /// <summary>
        /// Copy one file with the appropriate number of retries if it fails.
        /// </summary>
        private bool DoCopyWithRetries(FileState sourceFileState, FileState destinationFileState, CopyFileWithState copyFile)
        {
            bool? result = null;
            int retries = 0;

            while (true && !_canceling)
            {
                try
                {
                    result = copyFile(sourceFileState, destinationFileState);
                    if (result.HasValue)
                    {
                        return result.Value;
                    }
                }
                catch (Exception e) when (ExceptionHandling.IsIoRelatedException(e))
                {
                    if (e is ArgumentException ||  // Invalid chars
                        e is NotSupportedException || // Colon in the middle of the path
                        e is PathTooLongException)
                    {
                        // No use retrying these cases
                        throw;
                    }

                    if (e is UnauthorizedAccessException || e is IOException) // Not clear why we can get one and not the other
                    {
                        int code = Marshal.GetHRForException(e);

                        LogDiagnostic("Got {0} copying {1} to {2} and HR is {3}", e.ToString(), sourceFileState.Name, destinationFileState.Name, code);
                        if (code == Microsoft.Build.Tasks.NativeMethods.ERROR_ACCESS_DENIED)
                        {
                            // ERROR_ACCESS_DENIED can either mean there's an ACL preventing us, or the file has the readonly bit set.
                            // In either case, that's likely not a race, and retrying won't help.
                            // Retrying is mainly for ERROR_SHARING_VIOLATION, where someone else is using the file right now.
                            // However, there is a limited set of circumstances where a copy failure will show up as access denied due 
                            // to a failure to reset the readonly bit properly, in which case retrying will succeed.  This seems to be 
                            // a pretty edge scenario, but since some of our internal builds appear to be hitting it, provide a secret
                            // environment variable to allow overriding the default behavior and forcing retries in this circumstance as well. 
                            if (!s_alwaysRetryCopy)
                            {
                                throw;
                            }
                            else
                            {
                                LogDiagnostic("Retrying on ERROR_ACCESS_DENIED because MSBUILDALWAYSRETRY = 1");
                            }
                        }
                    }

                    if (e is IOException && DestinationFolder != null && File.Exists(DestinationFolder.ItemSpec))
                    {
                        // We failed to create the DestinationFolder because it's an existing file. No sense retrying.
                        // We don't check for this case upstream because it'd be another hit to the filesystem.
                        throw;
                    }

                    if (e is IOException)
                    {
                        // if this was just because the source and destination files are the
                        // same file, that's not a failure.
                        // Note -- we check this exceptional case here, not before the copy, for perf.
                        if (PathsAreIdentical(sourceFileState.Name, destinationFileState.Name))
                        {
                            return true;
                        }
                    }

                    if (retries < Retries)
                    {
                        retries++;
                        Log.LogWarningWithCodeFromResources("Copy.Retrying", sourceFileState.Name, destinationFileState.Name, retries, RetryDelayMilliseconds, e.Message);

                        // if we have to retry for some reason, wipe the state -- it may not be correct anymore. 
                        destinationFileState.Reset();

                        Thread.Sleep(RetryDelayMilliseconds);
                        continue;
                    }
                    else if (Retries > 0)
                    {
                        // Exception message is logged in caller
                        Log.LogErrorWithCodeFromResources("Copy.ExceededRetries", sourceFileState.Name, destinationFileState.Name, Retries);
                        throw;
                    }
                    else
                    {
                        throw;
                    }
                }

                if (retries < Retries)
                {
                    retries++;
                    Log.LogWarningWithCodeFromResources("Copy.Retrying", sourceFileState.Name, destinationFileState.Name, retries, RetryDelayMilliseconds, String.Empty /* no details */);

                    // if we have to retry for some reason, wipe the state -- it may not be correct anymore. 
                    destinationFileState.Reset();

                    Thread.Sleep(RetryDelayMilliseconds);
                }
                else if (Retries > 0)
                {
                    Log.LogErrorWithCodeFromResources("Copy.ExceededRetries", sourceFileState.Name, destinationFileState.Name, Retries);
                    return false;
                }
                else
                {
                    return false;
                }
            }

            // Canceling
            return false;
        }
Exemple #9
0
        /// <summary>
        /// Copy source to destination, unless SkipUnchangedFiles is true and they are equivalent.
        /// </summary>
        /// <param name="sourceFile"></param>
        /// <param name="destinationFile"></param>
        /// <param name="copyFile"></param>
        /// <returns></returns>
        private bool DoCopyIfNecessary(FileState sourceFileState, FileState destinationFileState, CopyFileWithState copyFile)
        {
            bool success = true;

            try
            {
                if (_skipUnchangedFiles && IsMatchingSizeAndTimeStamp(sourceFileState, destinationFileState))
                {
                    // If we got here, then the file's time and size match AND
                    // the user set the SkipUnchangedFiles flag which means we
                    // should skip matching files.
                    Log.LogMessageFromResources
                    (
                        MessageImportance.Low,
                        "Copy.DidNotCopyBecauseOfFileMatch",
                        sourceFileState.Name,
                        destinationFileState.Name,
                        "SkipUnchangedFiles",
                        "true"
                    );
                }
                // We only do the cheap check for identicalness here, we try the more expensive check
                // of comparing the fullpaths of source and destination to see if they are identical,
                // in the exception handler lower down.
                else if (0 != String.Compare(sourceFileState.Name, destinationFileState.Name, StringComparison.OrdinalIgnoreCase))
                {
                    success = DoCopyWithRetries(sourceFileState, destinationFileState, copyFile);
                }
            }
            catch (PathTooLongException e)
            {
                Log.LogErrorWithCodeFromResources("Copy.Error", sourceFileState.Name, destinationFileState.Name, e.Message);
                success = false;
            }
            catch (Exception e) when (ExceptionHandling.IsIoRelatedException(e))
            {
                Log.LogErrorWithCodeFromResources("Copy.Error", sourceFileState.Name, destinationFileState.Name, e.Message);
                success = false;
            }

            return success;
        }
Exemple #10
0
        /// <summary>
        /// Copy the files.
        /// </summary>
        /// <param name="copyFile">Delegate used to copy the files.</param>
        /// <returns></returns>
        internal bool Execute
        (
            CopyFileWithState copyFile
        )
        {
            // If there are no source files then just return success.
            if (_sourceFiles == null || _sourceFiles.Length == 0)
            {
                _destinationFiles = new TaskItem[0];
                _copiedFiles = new TaskItem[0];
                return true;
            }

            if (!(ValidateInputs() && InitializeDestinationFiles()))
            {
                return false;
            }

            bool success = true;

            // Environment variable stomps on user-requested value if it's set. 
            if (Environment.GetEnvironmentVariable("MSBUILDALWAYSOVERWRITEREADONLYFILES") != null)
            {
                _overwriteReadOnlyFiles = true;
            }

            // Build up the sucessfully copied subset
            var destinationFilesSuccessfullyCopied = new List<ITaskItem>();

            // Set of files we actually copied and the location from which they were originally copied.  The purpose
            // of this collection is to let us skip copying duplicate files.  We will only copy the file if it 
            // either has never been copied to this destination before (key doesn't exist) or if we have copied it but
            // from a different location (value is different.)
            // { dest -> source }
            Dictionary<string, string> filesActuallyCopied = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

            // Now that we have a list of destinationFolder files, copy from source to destinationFolder.
            for (int i = 0; i < _sourceFiles.Length && !_canceling; ++i)
            {
                bool copyComplete = false;
                string originalSource;
                if (filesActuallyCopied.TryGetValue(_destinationFiles[i].ItemSpec, out originalSource))
                {
                    if (String.Equals(originalSource, _sourceFiles[i].ItemSpec, StringComparison.OrdinalIgnoreCase))
                    {
                        // Already copied from this location, don't copy again.
                        copyComplete = true;
                    }
                }

                if (!copyComplete)
                {
                    if (DoCopyIfNecessary(new FileState(_sourceFiles[i].ItemSpec), new FileState(_destinationFiles[i].ItemSpec), copyFile))
                    {
                        filesActuallyCopied[_destinationFiles[i].ItemSpec] = _sourceFiles[i].ItemSpec;
                        copyComplete = true;
                    }
                    else
                    {
                        success = false;
                    }
                }

                if (copyComplete)
                {
                    _sourceFiles[i].CopyMetadataTo(_destinationFiles[i]);
                    destinationFilesSuccessfullyCopied.Add(_destinationFiles[i]);
                }
            }

            // copiedFiles contains only the copies that were successful.
            _copiedFiles = (ITaskItem[])destinationFilesSuccessfullyCopied.ToArray();

            return success && !_canceling;
        }
        private bool DoCopyIfNecessary(Microsoft.Build.Tasks.FileState sourceFileState, Microsoft.Build.Tasks.FileState destinationFileState, CopyFileWithState copyFile)
        {
            bool flag = true;

            try
            {
                if (this.skipUnchangedFiles && IsMatchingSizeAndTimeStamp(sourceFileState, destinationFileState))
                {
                    base.Log.LogMessageFromResources(MessageImportance.Low, "Copy.DidNotCopyBecauseOfFileMatch", new object[] { sourceFileState.Name, destinationFileState.Name, "SkipUnchangedFiles", "true" });
                    return(flag);
                }
                if (string.Compare(sourceFileState.Name, destinationFileState.Name, StringComparison.OrdinalIgnoreCase) != 0)
                {
                    flag = this.DoCopyWithRetries(sourceFileState, destinationFileState, copyFile);
                }
            }
            catch (PathTooLongException exception)
            {
                base.Log.LogErrorWithCodeFromResources("Copy.Error", new object[] { sourceFileState.Name, destinationFileState.Name, exception.Message });
                flag = false;
            }
            catch (IOException exception2)
            {
                if (this.PathsAreIdentical(sourceFileState.Name, destinationFileState.Name))
                {
                    return(flag);
                }
                if (Microsoft.Build.Shared.ExceptionHandling.NotExpectedException(exception2))
                {
                    throw;
                }
                base.Log.LogErrorWithCodeFromResources("Copy.Error", new object[] { sourceFileState.Name, destinationFileState.Name, exception2.Message });
                flag = false;
            }
            catch (Exception exception3)
            {
                if (Microsoft.Build.Shared.ExceptionHandling.NotExpectedException(exception3))
                {
                    throw;
                }
                base.Log.LogErrorWithCodeFromResources("Copy.Error", new object[] { sourceFileState.Name, destinationFileState.Name, exception3.Message });
                flag = false;
            }
            return(flag);
        }
        private bool DoCopyWithRetries(Microsoft.Build.Tasks.FileState sourceFileState, Microsoft.Build.Tasks.FileState destinationFileState, CopyFileWithState copyFile)
        {
            bool flag = false;
            int  num  = 0;

Label_0004:
            try
            {
                flag = copyFile(sourceFileState, destinationFileState);
            }
            catch (Exception exception)
            {
                if (Microsoft.Build.Shared.ExceptionHandling.NotExpectedException(exception))
                {
                    throw;
                }
                if (num >= this.Retries)
                {
                    if (this.Retries > 0)
                    {
                        base.Log.LogErrorWithCodeFromResources("Copy.ExceededRetries", new object[] { sourceFileState.Name, destinationFileState.Name, this.Retries });
                        throw;
                    }
                    throw;
                }
                num++;
                base.Log.LogWarningWithCodeFromResources("Copy.Retrying", new object[] { sourceFileState.Name, destinationFileState.Name, num, this.RetryDelayMilliseconds, exception.Message });
                Thread.Sleep(this.RetryDelayMilliseconds);
                goto Label_0004;
            }
            if (flag)
            {
                return(true);
            }
            if (num < this.Retries)
            {
                num++;
                base.Log.LogWarningWithCodeFromResources("Copy.Retrying", new object[] { sourceFileState.Name, destinationFileState.Name, num, this.RetryDelayMilliseconds, string.Empty });
                Thread.Sleep(this.RetryDelayMilliseconds);
                goto Label_0004;
            }
            if (this.Retries > 0)
            {
                base.Log.LogErrorWithCodeFromResources("Copy.ExceededRetries", new object[] { sourceFileState.Name, destinationFileState.Name, this.Retries });
                return(false);
            }
            return(false);
        }
Exemple #13
0
        /// <summary>
        /// Copy the files.
        /// </summary>
        /// <param name="copyFile">Delegate used to copy the files.</param>
        /// <returns></returns>
        internal bool Execute
        (
            CopyFileWithState copyFile
        )
        {
            // If there are no source files then just return success.
            if (_sourceFiles == null || _sourceFiles.Length == 0)
            {
                _destinationFiles = Array.Empty <TaskItem>();
                _copiedFiles      = Array.Empty <TaskItem>();
                return(true);
            }

            if (!(ValidateInputs() && InitializeDestinationFiles()))
            {
                return(false);
            }

            bool success = true;

            // Environment variable stomps on user-requested value if it's set.
            if (Environment.GetEnvironmentVariable("MSBUILDALWAYSOVERWRITEREADONLYFILES") != null)
            {
                _overwriteReadOnlyFiles = true;
            }

            // Build up the sucessfully copied subset
            var destinationFilesSuccessfullyCopied = new List <ITaskItem>();

            // Set of files we actually copied and the location from which they were originally copied.  The purpose
            // of this collection is to let us skip copying duplicate files.  We will only copy the file if it
            // either has never been copied to this destination before (key doesn't exist) or if we have copied it but
            // from a different location (value is different.)
            // { dest -> source }
            Dictionary <string, string> filesActuallyCopied = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);

            // Now that we have a list of destinationFolder files, copy from source to destinationFolder.
            for (int i = 0; i < _sourceFiles.Length && !_canceling; ++i)
            {
                bool   copyComplete = false;
                string originalSource;
                if (filesActuallyCopied.TryGetValue(_destinationFiles[i].ItemSpec, out originalSource))
                {
                    if (String.Equals(originalSource, _sourceFiles[i].ItemSpec, StringComparison.OrdinalIgnoreCase))
                    {
                        // Already copied from this location, don't copy again.
                        copyComplete = true;
                    }
                }

                if (!copyComplete)
                {
                    if (DoCopyIfNecessary(new FileState(_sourceFiles[i].ItemSpec), new FileState(_destinationFiles[i].ItemSpec), copyFile))
                    {
                        filesActuallyCopied[_destinationFiles[i].ItemSpec] = _sourceFiles[i].ItemSpec;
                        copyComplete = true;
                    }
                    else
                    {
                        success = false;
                    }
                }

                if (copyComplete)
                {
                    _sourceFiles[i].CopyMetadataTo(_destinationFiles[i]);
                    destinationFilesSuccessfullyCopied.Add(_destinationFiles[i]);
                }
            }

            // copiedFiles contains only the copies that were successful.
            _copiedFiles = (ITaskItem[])destinationFilesSuccessfullyCopied.ToArray();

            return(success && !_canceling);
        }
 internal bool Execute(CopyFileWithState copyFile)
 {
     if ((this.sourceFiles == null) || (this.sourceFiles.Length == 0))
     {
         this.destinationFiles = new TaskItem[0];
         this.copiedFiles = new TaskItem[0];
         return true;
     }
     if (!this.ValidateInputs() || !this.InitializeDestinationFiles())
     {
         return false;
     }
     bool flag = true;
     List<ITaskItem> list = new List<ITaskItem>();
     Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
     for (int i = 0; i < this.sourceFiles.Length; i++)
     {
         string str;
         bool flag2 = false;
         if (dictionary.TryGetValue(this.destinationFiles[i].ItemSpec, out str) && string.Equals(str, this.sourceFiles[i].ItemSpec, StringComparison.OrdinalIgnoreCase))
         {
             flag2 = true;
         }
         if (!flag2)
         {
             if (this.DoCopyIfNecessary(new Microsoft.Build.Tasks.FileState(this.sourceFiles[i].ItemSpec), new Microsoft.Build.Tasks.FileState(this.destinationFiles[i].ItemSpec), copyFile))
             {
                 dictionary[this.destinationFiles[i].ItemSpec] = this.sourceFiles[i].ItemSpec;
                 flag2 = true;
             }
             else
             {
                 flag = false;
             }
         }
         if (flag2)
         {
             this.sourceFiles[i].CopyMetadataTo(this.destinationFiles[i]);
             list.Add(this.destinationFiles[i]);
         }
     }
     this.copiedFiles = list.ToArray();
     return flag;
 }
 private bool DoCopyWithRetries(Microsoft.Build.Tasks.FileState sourceFileState, Microsoft.Build.Tasks.FileState destinationFileState, CopyFileWithState copyFile)
 {
     bool flag = false;
     int num = 0;
 Label_0004:
     try
     {
         flag = copyFile(sourceFileState, destinationFileState);
     }
     catch (Exception exception)
     {
         if (Microsoft.Build.Shared.ExceptionHandling.NotExpectedException(exception))
         {
             throw;
         }
         if (num >= this.Retries)
         {
             if (this.Retries > 0)
             {
                 base.Log.LogErrorWithCodeFromResources("Copy.ExceededRetries", new object[] { sourceFileState.Name, destinationFileState.Name, this.Retries });
                 throw;
             }
             throw;
         }
         num++;
         base.Log.LogWarningWithCodeFromResources("Copy.Retrying", new object[] { sourceFileState.Name, destinationFileState.Name, num, this.RetryDelayMilliseconds, exception.Message });
         Thread.Sleep(this.RetryDelayMilliseconds);
         goto Label_0004;
     }
     if (flag)
     {
         return true;
     }
     if (num < this.Retries)
     {
         num++;
         base.Log.LogWarningWithCodeFromResources("Copy.Retrying", new object[] { sourceFileState.Name, destinationFileState.Name, num, this.RetryDelayMilliseconds, string.Empty });
         Thread.Sleep(this.RetryDelayMilliseconds);
         goto Label_0004;
     }
     if (this.Retries > 0)
     {
         base.Log.LogErrorWithCodeFromResources("Copy.ExceededRetries", new object[] { sourceFileState.Name, destinationFileState.Name, this.Retries });
         return false;
     }
     return false;
 }