private static void UpdateRef(string refToUpdate, string refToUpdateTo) { Files.AssertInRepo(); // Get the hash that `refToUpdateTo` points at. var hash = Refs.Hash(refToUpdateTo); // Abort if `refToUpdateTo` does not point at a hash. if (!Objects.Exists(hash)) { throw new Exception(refToUpdateTo + " not a valid SHA1"); } // Abort if `refToUpdate` does not match the syntax of a ref. if (!Refs.IsRef(refToUpdate)) { throw new Exception("cannot lock the ref " + refToUpdate); } // Abort if `hash` points to an object in the `objects` directory // that is not a commit. if (Objects.Type(Objects.Read(hash)) != "commit") { var branch = Refs.TerminalRef(refToUpdate); throw new Exception(branch + " cannot refer to non-commit object " + hash + "\n"); } // Otherwise, set the contents of the file that the ref represents // to `hash`. Refs.Write(Refs.TerminalRef(refToUpdate), hash); }
/// <summary> /// records the commit that `branch` is at on `remote`. // It does not change the local branch. /// </summary> public static string Fetch(string remote, string branch) { Files.AssertInRepo(); // Abort if a `remote` or `branch` not passed. if (remote == null || branch == null) { throw new Exception("unsupported"); } // Abort if `remote` not recorded in config file. if (!Config.Read().Remotes.ContainsKey(remote)) { throw new Exception(remote + " does not appear to be a git repository"); } // Get the location of the remote. var remoteUrl = Files.Absolute(Config.Read().Remotes[remote].Url); // Turn the unqualified branch name into a qualified remote ref // eg `[branch] -> refs/remotes/[remote]/[branch]` var remoteRef = Refs.ToRemoteRef(remote, branch); // Go to the remote repository and get the hash of the commit // that `branch` is on. var newHash = Util.Remote <string>(remoteUrl)(() => Refs.Hash(branch)); // Abort if `branch` did not exist on the remote. if (newHash == null) { throw new Exception("couldn't find remote ref " + branch); } // Otherwise, perform the fetch. // Note down the hash of the commit this repository currently // thinks the remote branch is on. var oldHash = Refs.Hash(remoteRef); // Get all the objects in the remote `objects` directory and // write them. to the local `objects` directory. (This is an // inefficient way of getting all the objects required to // recreate locally the commit the remote branch is on.) var remoteObjects = Util.Remote <string[]>(remoteUrl)(Objects.AllObjects); foreach (var remoteObject in remoteObjects) { Objects.Write(remoteObject); } // Set the contents of the file at // `.gitlet/refs/remotes/[remote]/[branch]` to `newHash`, the // hash of the commit that the remote branch is on. Gitlet.UpdateRef(remoteRef, newHash); // Record the hash of the commit that the remote branch is on // in `FETCH_HEAD`. (The user can call `gitlet merge // FETCH_HEAD` to merge the remote version of the branch into // their local branch. For more details, see // [gitlet.merge()](#section-93).) Refs.Write("FETCH_HEAD", newHash + " branch " + branch + " of " + remoteUrl); // Report the result of the fetch. return (string.Format( "From {0}\nCount {1}\n{2} -> {3}/{2}{4}\n", remoteUrl, remoteObjects.Length, branch, remote, Core.Merge.IsAForceFetch(oldHash, newHash) ? " (forced)" : "")); }