static IEnumerable <ObjectHash> FindCommitsWithDuplicateTreeEntries(string vcsPath) { foreach (var commit in CommitWalker .CommitsRandomOrder(vcsPath) .AsParallel() .AsUnordered() .Select(commit => (commit.Hash, Defective: HasDefectiveTree(vcsPath, commit)))) { if (commit.Defective) { yield return(commit.Hash); } } }
static void Main(string[] args) { if (!CommandLineOptions.TryParse(args, out var options)) { return; } PackReader.InitializePackFiles(options.RepositoryPath); if (options.FixTrees) { var defectiveCommits = FindCommitsWithDuplicateTreeEntries(options.RepositoryPath).ToList(); var rewrittenCommits = FixDefectiveCommits(options.RepositoryPath, defectiveCommits); if (rewrittenCommits.Any()) { Refs.Update(options.RepositoryPath, rewrittenCommits); } } else if (options.FilesToDelete.Any() || options.FoldersToDelete.Any()) { using (var task = new DeletionTask(options.RepositoryPath, options.FilesToDelete, options.FoldersToDelete, options.ProtectRefs)) task.Run(); } else if (options.RemoveEmptyCommits) { using (var removeEmptyCommitsTask = new RemoveEmptyCommitsTask(options.RepositoryPath)) removeEmptyCommitsTask.Run(); } else if (!string.IsNullOrWhiteSpace(options.ContributorMappingFile)) { using (var rewriteContributorTask = new RewriteContributorTask(options.RepositoryPath, options.ContributorMappingFile)) rewriteContributorTask.Run(); } else if (options.ListContributorNames) { foreach (var contributor in CommitWalker.CommitsRandomOrder(options.RepositoryPath) .SelectMany(commit => new[] { commit.GetAuthorName(), commit.GetCommitterName() }) .Distinct() .AsParallel() .OrderBy(x => x)) { Console.WriteLine(contributor); } } }
static Dictionary <ObjectHash, ObjectHash> FixDefectiveCommits(string vcsPath, List <ObjectHash> defectiveCommits) { var rewrittenCommitHashes = new Dictionary <ObjectHash, ObjectHash>(); foreach (var commit in CommitWalker.CommitsInOrder(vcsPath)) { if (rewrittenCommitHashes.ContainsKey(commit.Hash)) { continue; } // Rewrite this commit byte[] newCommitBytes; if (defectiveCommits.Contains(commit.Hash)) { var fixedTreeHash = WriteFixedTree(vcsPath, GitObjectFactory.ReadTree(vcsPath, commit.TreeHash)); newCommitBytes = Commit.GetSerializedCommitWithChangedTreeAndParents(commit, fixedTreeHash, CorrectParents(commit.Parents, rewrittenCommitHashes).ToList()); } else { newCommitBytes = Commit.GetSerializedCommitWithChangedTreeAndParents(commit, commit.TreeHash, CorrectParents(commit.Parents, rewrittenCommitHashes).ToList()); } var fileObjectBytes = GitObjectFactory.GetBytesWithHeader(GitObjectType.Commit, newCommitBytes); var newCommitHash = new ObjectHash(Hash.Create(fileObjectBytes)); if (newCommitHash != commit.Hash && !rewrittenCommitHashes.ContainsKey(commit.Hash)) { HashContent.WriteFile(vcsPath, fileObjectBytes, newCommitHash.ToString()); rewrittenCommitHashes.Add(commit.Hash, newCommitHash); } } return(rewrittenCommitHashes); }