public List <ModManifest> Generate(string modPath)
        {
            if (!Directory.Exists(modPath))
            {
                throw new DirectoryNotFoundException();
            }

            int           i         = 0;
            var           result    = new List <ModManifest>();
            List <string> fileIndex = Directory.EnumerateFiles(modPath, "*", SearchOption.AllDirectories)
                                      .Where(x => !string.IsNullOrEmpty(x) &&
                                             !Path.GetFileName(x).Equals("mod.manifest", StringComparison.InvariantCultureIgnoreCase) &&
                                             !Path.GetFileName(x).Equals("mod.version", StringComparison.InvariantCultureIgnoreCase))
                                      .ToList();

            if (fileIndex.Count < 1)
            {
                return(result);
            }

            OnFilesIndexed(new FilesIndexedEventArgs(fileIndex.Count));

            foreach (var f in fileIndex)
            {
                var      relativePath = f.Substring(modPath.Length + 1);
                FileInfo file         = GetFileInfo(f);

                ++i;

                var args = new FileHashEventArgs(relativePath, i, fileIndex.Count);
                OnFileHashStart(args);

                if (args.Cancel)
                {
                    return(null);
                }

                string hash = GetFileHash(f);

                args = new FileHashEventArgs(relativePath, i, fileIndex.Count);
                OnFileHashEnd(args);

                if (args.Cancel)
                {
                    return(null);
                }

                result.Add(new ModManifest
                {
                    FilePath = relativePath,
                    FileSize = file.Length,
                    Checksum = hash
                });
            }

            return(result);
        }
        /// <summary>
        /// Generates a manifest for a given mod.
        /// </summary>
        /// <param name="modPath">The path to the mod directory.</param>
        /// <returns>A list of <see cref="ModManifestEntry"/>.</returns>
        public List <ModManifestEntry> Generate(string modPath)
        {
            if (!Directory.Exists(modPath))
            {
                throw new DirectoryNotFoundException();
            }

            var result = new List <ModManifestEntry>();

            List <string> fileIndex = Directory.EnumerateFiles(modPath, "*", SearchOption.AllDirectories)
                                      .Where(x => !string.IsNullOrEmpty(x) &&
                                             !Path.GetFileName(x).Equals("mod.manifest") &&
                                             !Path.GetFileName(x).Equals("mod.version"))
                                      .ToList();

            if (fileIndex.Count < 1)
            {
                return(result);
            }

            OnFilesIndexed(new FilesIndexedEventArgs(fileIndex.Count));

            int index = 0;

            foreach (string f in fileIndex)
            {
                string   relativePath = f.Substring(modPath.Length + 1);
                FileInfo file         = GetFileInfo(f);

                ++index;

                var args = new FileHashEventArgs(relativePath, index, fileIndex.Count);
                OnFileHashStart(args);

                if (args.Cancel)
                {
                    return(null);
                }

                string hash = GetFileHash(f);

                args = new FileHashEventArgs(relativePath, index, fileIndex.Count);
                OnFileHashEnd(args);

                if (args.Cancel)
                {
                    return(null);
                }

                result.Add(new ModManifestEntry(relativePath, file.Length, hash));
            }

            return(result);
        }
 private void OnFileHashEnd(FileHashEventArgs e)
 {
     FileHashEnd?.Invoke(this, e);
 }
 private void OnFileHashStart(FileHashEventArgs e)
 {
     FileHashStart?.Invoke(this, e);
 }
        /// <summary>
        /// Verifies the integrity of a mod against a mod manifest.
        /// </summary>
        /// <param name="modPath">Path to the mod to verify.</param>
        /// <param name="manifest">Manifest to check against.</param>
        /// <returns>A list of <see cref="ModManifestDiff"/> containing change information.</returns>
        public List <ModManifestDiff> Verify(string modPath, List <ModManifestEntry> manifest)
        {
            var result = new List <ModManifestDiff>();
            int index  = 0;

            foreach (ModManifestEntry m in manifest)
            {
                string filePath = Path.Combine(modPath, m.FilePath);

                ++index;

                var args = new FileHashEventArgs(m.FilePath, index, manifest.Count);
                OnFileHashStart(args);

                if (args.Cancel)
                {
                    return(null);
                }

                try
                {
                    if (!File.Exists(filePath))
                    {
                        result.Add(new ModManifestDiff(ModManifestState.Removed, m, null));
                        continue;
                    }

                    FileInfo info;

                    try
                    {
                        info = GetFileInfo(filePath);
                    }
                    catch (FileNotFoundException)
                    {
                        result.Add(new ModManifestDiff(ModManifestState.Removed, m, null));
                        continue;
                    }

                    if (info.Length != m.FileSize)
                    {
                        result.Add(new ModManifestDiff(ModManifestState.Changed, m, null));
                        continue;
                    }

                    string hash = GetFileHash(filePath);
                    if (!hash.Equals(m.Checksum, StringComparison.InvariantCultureIgnoreCase))
                    {
                        result.Add(new ModManifestDiff(ModManifestState.Changed, m, null));
                        continue;
                    }

                    result.Add(new ModManifestDiff(ModManifestState.Unchanged, m, null));
                }
                finally
                {
                    args = new FileHashEventArgs(m.FilePath, index, manifest.Count);
                    OnFileHashEnd(args);
                }

                if (args.Cancel)
                {
                    return(null);
                }
            }

            return(result);
        }