/// <summary> /// Creates a new <see cref="VersionFileList"/>. /// </summary> /// <param name="rootDir">The root directory containing the files to include.</param> /// <param name="filters">The filters to include.</param> /// <returns>The <see cref="VersionFileList"/> created from the given parameters.</returns> public static VersionFileList Create(string rootDir, IEnumerable <string> filters) { if (log.IsDebugEnabled) { log.DebugFormat("VersionFileList.Create(rootDir: {0}, fiters: ...)", rootDir); } var addFiles = new List <VersionFileInfo>(); var files = Directory.GetFiles(rootDir, "*", SearchOption.AllDirectories); // Get the length of the root directory so we know how much to chop off so that each file starts relative to // the rootDir, and does not start with a path separator var rootDirLen = rootDir.Length; if (!rootDir.EndsWith(Path.DirectorySeparatorChar.ToString()) && !rootDir.EndsWith(Path.AltDirectorySeparatorChar.ToString())) { rootDirLen++; } foreach (var f in files) { // Get the file information var fi = new FileInfo(f); // Generate the properties we are interested in var relativePath = fi.FullName.Substring(rootDirLen); var hash = Hasher.GetFileHash(fi.FullName); var size = fi.Length; // Add to the list var vfi = new VersionFileInfo(relativePath, hash, size); addFiles.Add(vfi); } var vfl = new VersionFileList(addFiles, filters); return(vfl); }
/// <summary> /// Checks the files provided in the given <see cref="VersionFileList"/> and compares them to the local files /// to see what files need to be updated. /// </summary> /// <param name="vfl">The <see cref="VersionFileList"/> containing the files to be updated.</param> /// <returns>The relative paths to the files that need to be updated.</returns> IEnumerable <string> FindFilesToUpdate(VersionFileList vfl) { var ret = new List <string>(); // Loop through each file foreach (var updateFileInfo in vfl.Files) { // Get the local file path var localFilePath = PathHelper.CombineDifferentPaths(Settings.TargetPath, updateFileInfo.FilePath); // If the file does not exist, add it if (!File.Exists(localFilePath)) { ret.Add(updateFileInfo.FilePath); continue; } // Get the info for the local file try { var localFileInfo = new FileInfo(localFilePath); // If the size of the local file doesn't equal the size of the updated file, avoid // checking the hash and just update it if (localFileInfo.Length != updateFileInfo.Size) { if (log.IsDebugEnabled) { log.DebugFormat( "Update check on file `{0}`: File needs update - size mismatch (current: {1}, expected: {2}).", updateFileInfo.FilePath, localFileInfo.Length, updateFileInfo.Size); } ret.Add(updateFileInfo.FilePath); continue; } // File exists and is of the correct size, so compare the hash of the local file to the expected hash var localFileHash = Hasher.GetFileHash(localFilePath); if (!StringComparer.Ordinal.Equals(localFileHash, updateFileInfo.Hash)) { if (log.IsDebugEnabled) { log.DebugFormat( "Update check on file `{0}`: File needs update - hash mismatch (current: {1}, expected: {2}).", updateFileInfo.FilePath, localFileHash, updateFileInfo.Hash); } ret.Add(updateFileInfo.FilePath); continue; } } catch (IOException ex) { const string errmsg = "Failed to analyze file `{0}` to see if it needs to be updated. Will assume update is required. Exception: {1}"; if (log.IsErrorEnabled) { log.ErrorFormat(errmsg, updateFileInfo.FilePath, ex); } Debug.Fail(string.Format(errmsg, updateFileInfo.FilePath, ex)); // On an IOException, assume the file needs to be updated ret.Add(updateFileInfo.FilePath); continue; } if (log.IsDebugEnabled) { log.DebugFormat("Update check on file `{0}`: file is up-to-date.", updateFileInfo.FilePath); } } if (log.IsInfoEnabled) { log.InfoFormat("Found `{0}` files needing to be updated.", ret.Count); } return(ret); }