public static ObjectHash WriteFixedTree(string vcsPath, Tree tree) { var resultingTreeLines = new List <Tree.TreeLine>(); bool fixRequired = false; foreach (var treeLine in tree.Lines) { if (!treeLine.IsDirectory()) { resultingTreeLines.Add(treeLine); continue; } var childTree = GitObjectFactory.ReadTree(vcsPath, treeLine.Hash); var fixedTreeHash = WriteFixedTree(vcsPath, childTree); resultingTreeLines.Add(new Tree.TreeLine(treeLine.TextBytes, fixedTreeHash)); if (fixedTreeHash != childTree.Hash) { fixRequired = true; } } if (fixRequired || Tree.HasDuplicateLines(resultingTreeLines)) { tree = Tree.GetFixedTree(resultingTreeLines); HashContent.WriteObject(vcsPath, tree); } return(tree.Hash); }
public static GitObjectBase ReadGitObject(string repositoryPath, ObjectHash hash) { var gitObject = PackReader.GetObject(hash); if (gitObject != null) { return(gitObject); } var fileContent = HashContent.FromFile(repositoryPath, hash.ToString()); var contentIndex = fileContent.AsSpan(7).IndexOf <byte>(0) + 8; if (IsCommit(fileContent)) { return(new Commit(hash, fileContent.AsSpan(contentIndex).ToArray())); } if (IsTree(fileContent)) { return(new Tree(hash, fileContent.AsMemory(contentIndex))); } if (IsTag(fileContent)) { return(new Tag(hash, fileContent.AsMemory(contentIndex))); } // TODO blobs probably not working atm if (IsBlob(fileContent)) { return(new Blob(hash, fileContent.AsMemory(contentIndex))); } return(null); }
public static Tree ReadTree(string repositoryPath, ObjectHash hash) { var tree = PackReader.GetTree(hash); if (tree != null) { return(tree); } var fileContent = HashContent.FromFile(repositoryPath, hash.ToString()); if (IsTree(fileContent)) { return(new Tree(hash, fileContent.AsMemory(fileContent.AsSpan(5).IndexOf <byte>(0) + 6))); } return(null); }
public static Commit ReadCommit(string repositoryPath, ObjectHash hash) { var commit = PackReader.GetCommit(repositoryPath, hash); if (commit != null) { return(commit); } var fileContent = HashContent.FromFile(repositoryPath, hash.ToString()); if (IsCommit(fileContent)) { return(new Commit(hash, fileContent.AsMemory(fileContent.AsSpan(7).IndexOf <byte>(0) + 8).ToArray())); } throw new ArgumentException("Not a commit: " + hash); }
private static ObjectHash RewriteRef(string vcsPath, string hash, string refName, Dictionary <ObjectHash, ObjectHash> rewrittenCommits) { var gitObject = GitObjectFactory.ReadGitObject(vcsPath, new ObjectHash(hash)); if (gitObject.Type == GitObjectType.Commit) { var path = Path.Combine(vcsPath, refName); var correctedHash = GetRewrittenCommitHash(new ObjectHash(hash), rewrittenCommits); Directory.CreateDirectory(Path.GetDirectoryName(path)); File.WriteAllText(path, correctedHash.ToString()); return(correctedHash); } if (gitObject.Type == GitObjectType.Tag) { var tag = (Tag)gitObject; if (tag.PointsToTree) { // Do not touch tags pointing to trees right now as this is not properly implemented yet return(tag.Hash); } var rewrittenObjectHash = tag.PointsToTag ? RewriteRef(vcsPath, tag.Object, "", rewrittenCommits) : GetRewrittenCommitHash(new ObjectHash(tag.Object), rewrittenCommits); // points to commit var rewrittenTag = tag.WithNewObject(rewrittenObjectHash.ToString()); HashContent.WriteObject(vcsPath, rewrittenTag); var path = Path.Combine(vcsPath, "refs/tags", rewrittenTag.TagName); File.WriteAllText(path, rewrittenTag.Hash.ToString()); return(rewrittenTag.Hash); } throw new NotImplementedException(); }
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); }