private ObjectId DereferenceToCommit(string identifier) { // TODO: Should we check the type? Git-log allows TagAnnotation oid as parameter. But what about Blobs and Trees? GitObject commit = repo.Lookup(identifier, GitObjectType.Any, LookUpOptions.ThrowWhenNoGitObjectHasBeenFound | LookUpOptions.DereferenceResultToCommit); return(commit != null ? commit.Id : null); }
private static Commit LookUpCommit(IRepository repository, string committish) { GitObject obj = repository.Lookup(committish); Ensure.GitObjectIsNotNull(obj, committish); return(obj.DereferenceToCommit(true)); }
/// <summary> /// Sets the current <see cref="Head"/> to the specified commit and optionally resets the <see cref="Index"/> and /// the content of the working tree to match. /// </summary> /// <param name = "resetOptions">Flavor of reset operation to perform.</param> /// <param name = "shaOrReferenceName">The sha or reference canonical name of the target commit object.</param> public void Reset(ResetOptions resetOptions, string shaOrReferenceName) { Ensure.ArgumentNotNullOrEmptyString(shaOrReferenceName, "shaOrReferenceName"); if (resetOptions.Has(ResetOptions.Mixed) && Info.IsBare) { throw new LibGit2Exception("Mixed reset is not allowed in a bare repository"); } GitObject commit = Lookup(shaOrReferenceName, GitObjectType.Any, LookUpOptions.ThrowWhenNoGitObjectHasBeenFound | LookUpOptions.DereferenceResultToCommit | LookUpOptions.ThrowWhenCanNotBeDereferencedToACommit); //TODO: Check for unmerged entries string refToUpdate = Info.IsHeadDetached ? "HEAD" : Head.CanonicalName; Refs.UpdateTarget(refToUpdate, commit.Sha); if (resetOptions == ResetOptions.Soft) { return; } Index.ReplaceContentWithTree(((Commit)commit).Tree); if (resetOptions == ResetOptions.Mixed) { return; } throw new NotImplementedException(); }
/// <summary> /// Try to lookup an object by its <see cref = "ObjectId" /> and <see cref = "GitObjectType" />. If no matching object is found, null will be returned. /// </summary> /// <param name = "id">The id to lookup.</param> /// <param name = "type">The kind of GitObject being looked up</param> /// <returns>The <see cref = "GitObject" /> or null if it was not found.</returns> public GitObject Lookup(ObjectId id, GitObjectType type = GitObjectType.Any) { Ensure.ArgumentNotNull(id, "id"); GitOid oid = id.Oid; IntPtr obj; int res; if (id is AbbreviatedObjectId) { res = NativeMethods.git_object_lookup_prefix(out obj, handle, ref oid, (uint)((AbbreviatedObjectId)id).Length, type); } else { res = NativeMethods.git_object_lookup(out obj, handle, ref oid, type); } if (res == (int)GitErrorCode.GIT_ENOTFOUND || res == (int)GitErrorCode.GIT_EINVALIDTYPE) { return(null); } Ensure.Success(res); if (id is AbbreviatedObjectId) { id = GitObject.ObjectIdOf(obj); } return(GitObject.CreateFromPtr(obj, id, this)); }
/// <summary> /// Inserts a <see cref = "TagAnnotation"/> into the object database, pointing to a specific <see cref = "GitObject"/>. /// </summary> /// <param name="name">The name.</param> /// <param name="target">The <see cref="GitObject"/> being pointed at.</param> /// <param name="tagger">The tagger.</param> /// <param name="message">The message.</param> /// <returns>The created <see cref = "Commit"/>.</returns> public virtual TagAnnotation CreateTag(string name, GitObject target, Signature tagger, string message) { string prettifiedMessage = Proxy.git_message_prettify(message); ObjectId tagId = Proxy.git_tag_annotation_create(repo.Handle, name, target, tagger, prettifiedMessage); return(repo.Lookup <TagAnnotation>(tagId)); }
/// <summary> /// Creates a lightweight tag with the specified name. /// </summary> /// <param name = "name">The name.</param> /// <param name = "objectish">Revparse spec for the target object.</param> /// <param name = "allowOverwrite">True to allow silent overwriting a potentially existing tag, false otherwise.</param> /// <param name = "tags">The <see cref="TagCollection"/> being worked with.</param> public static Tag Add(this TagCollection tags, string name, string objectish, bool allowOverwrite = false) { Ensure.ArgumentNotNullOrEmptyString(objectish, "objectish"); GitObject objectToTag = tags.repo.Lookup(objectish, GitObjectType.Any, LookUpOptions.ThrowWhenNoGitObjectHasBeenFound); return(tags.Add(name, objectToTag, allowOverwrite)); }
/// <summary> /// Creates an annotated tag with the specified name. /// </summary> /// <param name="name">The name.</param> /// <param name="objectish">Revparse spec for the target object.</param> /// <param name="tagger">The tagger.</param> /// <param name="message">The message.</param> /// <param name="allowOverwrite">True to allow silent overwriting a potentially existing tag, false otherwise.</param> public virtual Tag Add(string name, string objectish, Signature tagger, string message, bool allowOverwrite) { Ensure.ArgumentNotNullOrEmptyString(objectish, "target"); GitObject objectToTag = repo.Lookup(objectish, GitObjectType.Any, LookUpOptions.ThrowWhenNoGitObjectHasBeenFound); return(Add(name, objectToTag, tagger, message, allowOverwrite)); }
private GitObject RetreiveTreeEntryTarget() { GitObject treeEntryTarget = repo.Lookup(targetOid); //TODO: Warning submodules will appear as targets of type Commit Ensure.ArgumentConformsTo(treeEntryTarget.GetType(), t => typeof(Blob).IsAssignableFrom(t) || typeof(Tree).IsAssignableFrom(t), "treeEntryTarget"); return(treeEntryTarget); }
/// <summary> /// Creates a lightweight tag with the specified name. /// </summary> /// <param name="name">The name.</param> /// <param name="target">The target <see cref="GitObject"/>.</param> /// <param name="allowOverwrite">True to allow silent overwriting a potentially existing tag, false otherwise.</param> /// <returns>The added <see cref="Tag"/>.</returns> public virtual Tag Add(string name, GitObject target, bool allowOverwrite = false) { Ensure.ArgumentNotNullOrEmptyString(name, "name"); Ensure.ArgumentNotNull(target, "target"); Proxy.git_tag_create_lightweight(repo.Handle, name, target, allowOverwrite); return(this[name]); }
private GitObject RetrieveObject(string shaOrReferenceName) { GitObject gitObj = repo.Lookup(shaOrReferenceName); // TODO: Should we check the type? Git-log allows TagAnnotation oid as parameter. But what about Blobs and Trees? EnsureGitObjectNotNull(shaOrReferenceName, gitObj); return(gitObj); }
private GitObject RetrieveTreeEntryTarget() { if (!Type.HasAny(new[] { GitObjectType.Tree, GitObjectType.Blob })) { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "TreeEntry target of type '{0}' are not supported.", Type)); } return(GitObject.BuildFrom(repo, targetOid, Type, Path)); }
private static void EnsureGitObjectNotNull(string shaOrReferenceName, GitObject gitObj) { if (gitObj != null) { return; } throw new LibGit2Exception(string.Format(CultureInfo.InvariantCulture, "No valid git object pointed at by '{0}' exists in the repository.", shaOrReferenceName)); }
/// <summary> /// Updates the target of a direct reference. /// </summary> /// <param name="directRef">The direct reference which target should be updated.</param> /// <param name="objectish">The revparse spec of the target.</param> /// <param name="refsColl">The <see cref="ReferenceCollection"/> being worked with.</param> /// <param name="logMessage">The optional message to log in the <see cref="ReflogCollection"/> of the <paramref name="directRef"/> reference.</param> /// <returns>A new <see cref="Reference"/>.</returns> public static Reference UpdateTarget(this ReferenceCollection refsColl, Reference directRef, string objectish, string logMessage = null) { Ensure.ArgumentNotNull(directRef, "directRef"); Ensure.ArgumentNotNull(objectish, "objectish"); GitObject target = refsColl.repo.Lookup(objectish); Ensure.GitObjectIsNotNull(target, objectish); return(refsColl.UpdateTarget(directRef, target.Id, logMessage)); }
private GitObject RetrieveTreeEntryTarget() { if (!Type.HasAny(new[] { GitObjectType.Tree, GitObjectType.Blob })) { throw new InvalidOperationException(string.Format("TreeEntry target of type '{0}' are not supported.", Type)); } GitObject treeEntryTarget = repo.LookupTreeEntryTarget(targetOid, Path); return(treeEntryTarget); }
private GitObject RetrieveObjectToTag(string target) { GitObject objectToTag = repo.Lookup(target); if (objectToTag == null) { throw new LibGit2Exception(String.Format(CultureInfo.InvariantCulture, "No object identified by '{0}' can be found in the repository.", target)); } return(objectToTag); }
/// <summary> /// Updates the target of a direct reference. /// </summary> /// <param name="directRef">The direct reference which target should be updated.</param> /// <param name="objectish">The revparse spec of the target.</param> /// <param name="logMessage">The optional message to log in the <see cref="ReflogCollection"/></param> /// <returns>A new <see cref="Reference"/>.</returns> public virtual Reference UpdateTarget(Reference directRef, string objectish, string logMessage) { Ensure.ArgumentNotNull(directRef, "directRef"); Ensure.ArgumentNotNull(objectish, "objectish"); GitObject target = repo.Lookup(objectish); Ensure.GitObjectIsNotNull(target, objectish); return(UpdateTarget(directRef, target.Id, logMessage)); }
/// <summary> /// Checkout the specified <see cref="Branch"/>, reference or SHA. /// <para> /// If the committishOrBranchSpec parameter resolves to a branch name, then the checked out HEAD will /// will point to the branch. Otherwise, the HEAD will be detached, pointing at the commit sha. /// </para> /// </summary> /// <param name="repository">The repository to act on</param> /// <param name="committishOrBranchSpec">A revparse spec for the commit or branch to checkout.</param> /// <param name="options"><see cref="CheckoutOptions"/> controlling checkout behavior.</param> /// <returns>The <see cref="Branch"/> that was checked out.</returns> public static Branch Checkout(IRepository repository, string committishOrBranchSpec, CheckoutOptions options) { Ensure.ArgumentNotNull(repository, "repository"); Ensure.ArgumentNotNullOrEmptyString(committishOrBranchSpec, "committishOrBranchSpec"); Ensure.ArgumentNotNull(options, "options"); Reference reference = null; GitObject obj = null; Branch branch = null; try { repository.RevParse(committishOrBranchSpec, out reference, out obj); } catch (NotFoundException) { // If committishOrBranchSpec is not a local branch but matches a tracking branch // in exactly one remote, use it. This is the "git checkout" command's default behavior. // https://git-scm.com/docs/git-checkout#Documentation/git-checkout.txt-emgitcheckoutemltbranchgt var remoteBranches = repository.Network.Remotes .SelectMany(r => repository.Branches.Where(b => b.IsRemote && b.CanonicalName == $"refs/remotes/{r.Name}/{committishOrBranchSpec}")) .ToList(); if (remoteBranches.Count == 1) { branch = repository.CreateBranch(committishOrBranchSpec, remoteBranches[0].Tip); repository.Branches.Update(branch, b => b.TrackedBranch = remoteBranches[0].CanonicalName); return(Checkout(repository, branch, options)); } if (remoteBranches.Count > 1) { throw new AmbiguousSpecificationException($"'{committishOrBranchSpec}' matched multiple ({remoteBranches.Count}) remote tracking branches"); } throw; } if (reference != null && reference.IsLocalBranch) { branch = repository.Branches[reference.CanonicalName]; return(Checkout(repository, branch, options)); } Commit commit = obj.Peel <Commit>(true); Checkout(repository, commit.Tree, options, committishOrBranchSpec); return(repository.Head); }
/// <summary> /// Creates an annotated tag with the specified name. /// </summary> /// <param name="name">The name.</param> /// <param name="target">The target <see cref="GitObject"/>.</param> /// <param name="tagger">The tagger.</param> /// <param name="message">The message.</param> /// <param name="allowOverwrite">True to allow silent overwriting a potentially existing tag, false otherwise.</param> /// <returns>The added <see cref="Tag"/>.</returns> public virtual Tag Add(string name, GitObject target, Signature tagger, string message, bool allowOverwrite = false) { Ensure.ArgumentNotNullOrEmptyString(name, "name"); Ensure.ArgumentNotNull(target, "target"); Ensure.ArgumentNotNull(tagger, "tagger"); Ensure.ArgumentNotNull(message, "message"); string prettifiedMessage = Proxy.git_message_prettify(message, null); Proxy.git_tag_create(repo.Handle, name, target, tagger, prettifiedMessage, allowOverwrite); return(this[name]); }
/// <summary> /// Gets the <see cref="Stash"/> corresponding to the specified index (0 being the most recent one). /// </summary> public virtual Stash this[int index] { get { if (index < 0) { throw new ArgumentOutOfRangeException("index", "The passed index must be a positive integer."); } GitObject stashCommit = repo.Lookup(string.Format("stash@{{{0}}}", index), GitObjectType.Commit, LookUpOptions.None); return(stashCommit == null ? null : new Stash(repo, stashCommit.Id, index)); } }
private static ObjectId DereferenceToCommit(Repository repo, string identifier) { var options = LookUpOptions.DereferenceResultToCommit; if (!AllowOrphanReference(repo, identifier)) { options |= LookUpOptions.ThrowWhenNoGitObjectHasBeenFound; } // TODO: Should we check the type? Git-log allows TagAnnotation oid as parameter. But what about Blobs and Trees? GitObject commit = repo.Lookup(identifier, GitObjectType.Any, options); return(commit != null ? commit.Id : null); }
private ObjectId Unabbreviate(ObjectId targetId) { if (!(targetId is AbbreviatedObjectId)) { return(targetId); } GitObject obj = repo.Lookup(targetId); if (obj == null) { Ensure.Success((int)GitErrorCode.GIT_ENOTFOUND); } return(obj.Id); }
private GitObject RetrieveTreeEntryTarget() { switch (TargetType) { case TreeEntryTargetType.GitLink: return(new GitLink(repo, targetOid)); case TreeEntryTargetType.Blob: case TreeEntryTargetType.Tree: return(GitObject.BuildFrom(repo, targetOid, TargetType.ToGitObjectType(), Path)); default: throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "TreeEntry target of type '{0}' is not supported.", TargetType)); } }
/// <summary> /// Creates a lightweight tag with the specified name. /// </summary> /// <param name = "name">The name.</param> /// <param name = "target">The target which can be sha or a canonical reference name.</param> /// <param name = "allowOverwrite">True to allow silent overwriting a potentially existing tag, false otherwise.</param> /// <returns></returns> public Tag Create(string name, string target, bool allowOverwrite = false) { Ensure.ArgumentNotNullOrEmptyString(name, "name"); Ensure.ArgumentNotNullOrEmptyString(target, "target"); GitObject objectToTag = repo.Lookup(target, GitObjectType.Any, LookUpOptions.ThrowWhenNoGitObjectHasBeenFound); int res; using (var objectPtr = new ObjectSafeWrapper(objectToTag.Id, repo)) { GitOid oid; res = NativeMethods.git_tag_create_lightweight(out oid, repo.Handle, name, objectPtr.ObjectPtr, allowOverwrite); } Ensure.Success(res); return(this[name]); }
/// <summary> /// Checkout the specified <see cref="Branch"/>, reference or SHA. /// <para> /// If the committishOrBranchSpec parameter resolves to a branch name, then the checked out HEAD will /// will point to the branch. Otherwise, the HEAD will be detached, pointing at the commit sha. /// </para> /// </summary> /// <param name="committishOrBranchSpec">A revparse spec for the commit or branch to checkout.</param> /// <param name="checkoutModifiers"><see cref="CheckoutModifiers"/> controlling checkout behavior.</param> /// <param name="onCheckoutProgress"><see cref="CheckoutProgressHandler"/> that checkout progress is reported through.</param> /// <param name="checkoutNotifications"><see cref="CheckoutNotificationOptions"/> to manage checkout notifications.</param> /// <returns>The <see cref="Branch"/> that was checked out.</returns> public Branch Checkout(string committishOrBranchSpec, CheckoutModifiers checkoutModifiers, CheckoutProgressHandler onCheckoutProgress, CheckoutNotificationOptions checkoutNotifications) { Ensure.ArgumentNotNullOrEmptyString(committishOrBranchSpec, "committishOrBranchSpec"); var handles = Proxy.git_revparse_ext(Handle, committishOrBranchSpec); if (handles == null) { Ensure.GitObjectIsNotNull(null, committishOrBranchSpec); } var objH = handles.Item1; var refH = handles.Item2; GitObject obj; try { if (!refH.IsInvalid) { var reference = Reference.BuildFromPtr <Reference>(refH, this); if (reference.IsLocalBranch()) { Branch branch = Branches[reference.CanonicalName]; return(Checkout(branch, checkoutModifiers, onCheckoutProgress, checkoutNotifications)); } } obj = GitObject.BuildFrom(this, Proxy.git_object_id(objH), Proxy.git_object_type(objH), PathFromRevparseSpec(committishOrBranchSpec)); } finally { objH.Dispose(); refH.Dispose(); } Commit commit = obj.DereferenceToCommit(true); Checkout(commit.Tree, checkoutModifiers, onCheckoutProgress, checkoutNotifications, commit.Id.Sha, committishOrBranchSpec, committishOrBranchSpec != "HEAD"); return(Head); }
/// <summary> /// Creates an annotated tag with the specified name. /// </summary> /// <param name = "name">The name.</param> /// <param name = "target">The target which can be sha or a canonical reference name.</param> /// <param name = "tagger">The tagger.</param> /// <param name = "message">The message.</param> /// <param name = "allowOverwrite">True to allow silent overwriting a potentially existing tag, false otherwise.</param> /// <returns></returns> public Tag Create(string name, string target, Signature tagger, string message, bool allowOverwrite = false) { Ensure.ArgumentNotNullOrEmptyString(name, "name"); Ensure.ArgumentNotNullOrEmptyString(target, "target"); Ensure.ArgumentNotNull(tagger, "tagger"); Ensure.ArgumentNotNull(message, "message"); GitObject objectToTag = RetrieveObjectToTag(target); int res; using (var objectPtr = new ObjectSafeWrapper(objectToTag.Id, repo)) { GitOid oid; res = NativeMethods.git_tag_create(out oid, repo.Handle, name, objectPtr.ObjectPtr, tagger.Handle, message, allowOverwrite); } Ensure.Success(res); return(this[name]); }
internal GitObject Lookup(string shaOrReferenceName, GitObjectType type, LookUpOptions lookUpOptions) { ObjectId id; Reference reference = Refs[shaOrReferenceName]; if (reference != null) { id = reference.PeelToTargetObjectId(); } else { ObjectId.TryParse(shaOrReferenceName, out id); } if (id == null) { if (lookUpOptions.Has(LookUpOptions.ThrowWhenNoGitObjectHasBeenFound)) { Ensure.GitObjectIsNotNull(null, shaOrReferenceName); } return(null); } GitObject gitObj = Lookup(id, type); if (lookUpOptions.Has(LookUpOptions.ThrowWhenNoGitObjectHasBeenFound)) { Ensure.GitObjectIsNotNull(gitObj, shaOrReferenceName); } if (!lookUpOptions.Has(LookUpOptions.DereferenceResultToCommit)) { return(gitObj); } return(gitObj.DereferenceToCommit(shaOrReferenceName, lookUpOptions.Has(LookUpOptions.ThrowWhenCanNotBeDereferencedToACommit))); }
internal Reference UpdateHeadTarget <T>(T target, Signature signature, string logMessage) { Debug.Assert(signature != null); if (target is ObjectId) { Proxy.git_repository_set_head_detached(repo.Handle, target as ObjectId, signature, logMessage); } else if (target is DirectReference || target is SymbolicReference) { Proxy.git_repository_set_head(repo.Handle, (target as Reference).CanonicalName, signature, logMessage); } else if (target is string) { var targetIdentifier = target as string; if (Reference.IsValidName(targetIdentifier)) { Proxy.git_repository_set_head(repo.Handle, targetIdentifier, signature, logMessage); } else { GitObject commit = repo.Lookup(targetIdentifier, GitObjectType.Any, LookUpOptions.ThrowWhenNoGitObjectHasBeenFound | LookUpOptions.DereferenceResultToCommit | LookUpOptions.ThrowWhenCanNotBeDereferencedToACommit); Proxy.git_repository_set_head_detached(repo.Handle, commit.Id, signature, logMessage); } } else { throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "'{0}' is not a valid target type.", typeof(T))); } return(repo.Refs.Head); }
internal GitObject LookupInternal(ObjectId id, GitObjectType type, FilePath knownPath) { Ensure.ArgumentNotNull(id, "id"); GitObjectSafeHandle obj = null; try { obj = Proxy.git_object_lookup(handle, id, type); if (obj == null) { return(null); } return(GitObject.BuildFrom(this, id, Proxy.git_object_type(obj), knownPath)); } finally { obj.SafeDispose(); } }
internal GitObject LookupInternal(ObjectId id, GitObjectType type, FilePath knownPath) { Ensure.ArgumentNotNull(id, "id"); GitOid oid = id.Oid; GitObjectSafeHandle obj = null; try { int res; if (id is AbbreviatedObjectId) { res = NativeMethods.git_object_lookup_prefix(out obj, handle, ref oid, (uint)((AbbreviatedObjectId)id).Length, type); } else { res = NativeMethods.git_object_lookup(out obj, handle, ref oid, type); } if (res == (int)GitErrorCode.GIT_ENOTFOUND) { return(null); } Ensure.Success(res); if (id is AbbreviatedObjectId) { id = GitObject.ObjectIdOf(obj); } return(GitObject.CreateFromPtr(obj, id, this, knownPath)); } finally { obj.SafeDispose(); } }
private ObjectId DereferenceToCommit(string identifier) { GitObject obj = RetrieveObject(identifier); if (obj is Commit) { return(obj.Id); } if (obj is TagAnnotation) { return(DereferenceToCommit(((TagAnnotation)obj).Target.Sha)); } if (obj is Blob || obj is Tree) { return(null); } throw new LibGit2Exception(string.Format(CultureInfo.InvariantCulture, "The Git object pointed at by '{0}' can not be dereferenced to a commit.", identifier)); }