/// <summary>
        /// Calculates the hash for a given directory.
        /// </summary>
        /// <param name="directoryPath">The directory path.</param>
        /// <param name="pattern">The glob pattern to match.</param>
        /// <param name="hashAlgorithm">The hash algorithm to use.</param>
        /// <returns>A <see cref="DirectoryHash"/> instance representing the calculated hash.</returns>
        /// <example>
        /// <code>
        /// Information(
        ///     "Cake It calculates the hashes from all cs files in all subdirectories using a MD5 hash: {0}",
        ///     CalculateDirectoryHash("C:\directoryToHash", "./**/*.cs", HashAlgorithm.MD5).ToHex());
        /// </code>
        /// </example>
        public DirectoryHash Calculate(
            DirectoryPath directoryPath,
            IEnumerable <GlobPattern> pattern,
            HashAlgorithm hashAlgorithm)
        {
            if (directoryPath == null)
            {
                throw new ArgumentNullException(nameof(directoryPath));
            }

            if (pattern == null)
            {
                throw new ArgumentNullException(nameof(pattern));
            }

            using (var incrementalDirectoryHash = _hashAlgorithmBuilder.CreateHashAlgorithm(hashAlgorithm))
            {
                var fileHashList = new List <FileHash>();
                var files        = GetDirectoryFiles(directoryPath, pattern).OrderBy(file => file.FullPath);
                if (files.Any())
                {
                    var lastFile = files.LastOrDefault();
                    foreach (var file in GetDirectoryFiles(directoryPath, pattern))
                    {
                        var fileContentAndNameHash = CalculateFileContentAndNameHash(file, directoryPath, hashAlgorithm);
                        fileHashList.Add(fileContentAndNameHash);
                        if (file == lastFile)
                        {
                            incrementalDirectoryHash.TransformFinalBlock(
                                fileContentAndNameHash.ComputedHash, 0,
                                fileContentAndNameHash.ComputedHash.Length);
                        }
                        else
                        {
                            incrementalDirectoryHash.TransformBlock(
                                fileContentAndNameHash.ComputedHash, 0,
                                fileContentAndNameHash.ComputedHash.Length,
                                fileContentAndNameHash.ComputedHash, 0);
                        }
                    }

                    var directoryHash = incrementalDirectoryHash.Hash;
                    return(new DirectoryHash(directoryPath, directoryHash, hashAlgorithm, fileHashList));
                }

                // No files found.
                return(null);
            }
        }
        /// <summary>
        /// Calculates the hash for a file using the given algorithm.
        /// </summary>
        /// <param name="filePath">The file path.</param>
        /// <param name="hashAlgorithm">The algorithm to use.</param>
        /// <returns>A <see cref="FileHash"/> instance representing the calculated hash.</returns>
        public FileHash Calculate(FilePath filePath, HashAlgorithm hashAlgorithm)
        {
            if (filePath == null)
            {
                throw new ArgumentNullException(nameof(filePath));
            }

            var file = _fileSystem.GetFile(filePath);

            if (!file.Exists)
            {
                const string format  = "File '{0}' does not exist.";
                var          message = string.Format(CultureInfo.InvariantCulture, format, filePath.FullPath);
                throw new CakeException(message);
            }

            using (var hashAlgo = _hashAlgorithmBuilder.CreateHashAlgorithm(hashAlgorithm))
                using (var readStream = file.OpenRead())
                {
                    var hash = hashAlgo.ComputeHash(readStream);
                    return(new FileHash(filePath, hash, hashAlgorithm));
                }
        }