/// <summary> /// Creates a commit object that represents the current /// state of the index, writes the commit to the `objects` directory /// and points `HEAD` at the commit. /// </summary> public static string Commit(CommitOptions options) { Files.AssertInRepo(); Config.AssertNotBare(); // Write a tree object that represents the current state of the // index. var treeHash = WriteTree(); var headDesc = Refs.IsHeadDetached() ? "detached HEAD" : Refs.HeadBranchName(); // If the hash of the new tree is the same as the hash of the tree // that the `HEAD` commit points at, abort because there is // nothing new to commit. if (Refs.Hash("HEAD") != null && treeHash == Objects.TreeHash(Objects.Read(Refs.Hash("HEAD")))) { throw new Exception("# On " + headDesc + "\nnothing to commit, working directory clean"); } // Abort if the repository is in the merge state and there are // unresolved merge conflicts. string[] conflictedPaths = Index.ConflictedPaths(); if (Core.Merge.IsMergeInProgress() && conflictedPaths.Length > 0) { throw new Exception( string.Join("\n", conflictedPaths.Select(p => "U " + p)) + "\ncannot commit because you have unmerged files"); } // Otherwise, do the commit. // If the repository is in the merge state, use a pre-written // merge commit message. If the repository is not in the // merge state, use the message passed with `-m`. var m = Core.Merge.IsMergeInProgress() ? Files.Read(Path.Combine(Files.GitletPath(), "MERGE_MSG")) : options.m; // Write the new commit to the `objects` directory. var commitHash = Objects.WriteCommit(treeHash, m, Refs.CommitParentHashes()); // Point `HEAD` at new commit. UpdateRef("HEAD", commitHash); // If `MERGE_HEAD` exists, the repository was in the merge // state. Remove `MERGE_HEAD` and `MERGE_MSG`to exit the merge // state. Report that the merge is complete. if (Core.Merge.IsMergeInProgress()) { File.Delete(Path.Combine(Files.GitletPath(), "MERGE_MSG")); Refs.Rm("MERGE_HEAD"); return("Merge made by the three-way strategy"); } // Repository was not in the merge state, so just report that // the commit is complete. return("[" + headDesc + " " + commitHash + "] " + m); }