예제 #1
0
        /// <summary>
        /// Rename an existing local branch
        /// </summary>
        /// <param name="branch">The current local branch.</param>
        /// <param name="newName">The new name the existing branch should bear.</param>
        /// <param name="signature">Identity used for updating the reflog</param>
        /// <param name="logMessage">Message added to the reflog. If null, the default is "branch: renamed [old] to [new]".</param>
        /// <param name="allowOverwrite">True to allow silent overwriting a potentially existing branch, false otherwise.</param>
        /// <returns>A new <see cref="Branch"/>.</returns>
        public virtual Branch Rename(Branch branch, string newName, Signature signature, string logMessage = null, bool allowOverwrite = false)
        {
            Ensure.ArgumentNotNull(branch, "branch");
            Ensure.ArgumentNotNullOrEmptyString(newName, "newName");

            if (branch.IsRemote)
            {
                throw new LibGit2SharpException(
                          string.Format(CultureInfo.InvariantCulture,
                                        "Cannot rename branch '{0}'. It's a remote tracking branch.", branch.Name));
            }

            if (logMessage == null)
            {
                logMessage = string.Format(CultureInfo.InvariantCulture,
                                           "branch: renamed {0} to {1}", branch.CanonicalName, Reference.LocalBranchPrefix + newName);
            }

            using (ReferenceSafeHandle referencePtr = repo.Refs.RetrieveReferencePtr(Reference.LocalBranchPrefix + branch.Name))
            {
                using (Proxy.git_branch_move(referencePtr, newName, allowOverwrite, signature.OrDefault(repo.Config), logMessage))
                {
                }
            }

            var newBranch = this[newName];

            return(newBranch);
        }
예제 #2
0
        /// <summary>
        /// Fetch from the <see cref="Remote"/>.
        /// </summary>
        /// <param name="remote">The remote to fetch</param>
        /// <param name="options"><see cref="FetchOptions"/> controlling fetch behavior</param>
        /// <param name="signature">Identity for use when updating the reflog.</param>
        /// <param name="logMessage">Message to use when updating the reflog.</param>
        public virtual void Fetch(Remote remote, FetchOptions options = null,
                                  Signature signature = null,
                                  string logMessage   = null)
        {
            Ensure.ArgumentNotNull(remote, "remote");

            using (RemoteSafeHandle remoteHandle = Proxy.git_remote_load(repository.Handle, remote.Name, true))
            {
                DoFetch(remoteHandle, options, signature.OrDefault(repository.Config), logMessage);
            }
        }
예제 #3
0
        /// <summary>
        /// Fetch from the <see cref="Remote"/>, using custom refspecs.
        /// </summary>
        /// <param name="remote">The remote to fetch</param>
        /// <param name="refspecs">Refspecs to use, replacing the remote's fetch refspecs</param>
        /// <param name="options"><see cref="FetchOptions"/> controlling fetch behavior</param>
        /// <param name="signature">Identity for use when updating the reflog.</param>
        /// <param name="logMessage">Message to use when updating the reflog.</param>
        public virtual void Fetch(Remote remote, IEnumerable <string> refspecs, FetchOptions options = null,
                                  Signature signature = null,
                                  string logMessage   = null)
        {
            Ensure.ArgumentNotNull(remote, "remote");
            Ensure.ArgumentNotNull(refspecs, "refspecs");

            using (RemoteSafeHandle remoteHandle = Proxy.git_remote_lookup(repository.Handle, remote.Name, true))
            {
                Proxy.git_remote_set_fetch_refspecs(remoteHandle, refspecs);

                DoFetch(remoteHandle, options, signature.OrDefault(repository.Config), logMessage);
            }
        }
예제 #4
0
        /// <summary>
        /// Fetch from a url with a set of fetch refspecs
        /// </summary>
        /// <param name="url">The url to fetch from</param>
        /// <param name="refspecs">The list of resfpecs to use</param>
        /// <param name="options"><see cref="FetchOptions"/> controlling fetch behavior</param>
        /// <param name="signature">Identity for use when updating the reflog.</param>
        /// <param name="logMessage">Message to use when updating the reflog.</param>
        public virtual void Fetch(
            string url,
            IEnumerable <string> refspecs,
            FetchOptions options = null,
            Signature signature  = null,
            string logMessage    = null)
        {
            Ensure.ArgumentNotNull(url, "url");
            Ensure.ArgumentNotNull(refspecs, "refspecs");

            using (RemoteSafeHandle remoteHandle = Proxy.git_remote_create_anonymous(repository.Handle, url, null))
            {
                Proxy.git_remote_set_fetch_refspecs(remoteHandle, refspecs);

                DoFetch(remoteHandle, options, signature.OrDefault(repository.Config), logMessage);
            }
        }
예제 #5
0
        /// <summary>
        /// Updates the target of a symbolic reference
        /// </summary>
        /// <param name="symbolicRef">The symbolic reference which target should be updated.</param>
        /// <param name="targetRef">The new target.</param>
        /// <param name="signature">The identity used for updating the reflog.</param>
        /// <param name="logMessage">The optional message to log in the <see cref="ReflogCollection"/> of the <paramref name="symbolicRef"/> reference.</param>
        /// <returns>A new <see cref="Reference"/>.</returns>
        public virtual Reference UpdateTarget(Reference symbolicRef, Reference targetRef, Signature signature, string logMessage)
        {
            Ensure.ArgumentNotNull(symbolicRef, "symbolicRef");
            Ensure.ArgumentNotNull(targetRef, "targetRef");

            signature = signature.OrDefault(repo.Config);

            if (symbolicRef.CanonicalName == "HEAD")
            {
                return(UpdateHeadTarget(targetRef, signature, logMessage));
            }

            using (ReferenceSafeHandle referencePtr = RetrieveReferencePtr(symbolicRef.CanonicalName))
                using (ReferenceSafeHandle handle = Proxy.git_reference_symbolic_set_target(referencePtr, targetRef.CanonicalName, signature, logMessage))
                {
                    return(Reference.BuildFromPtr <Reference>(handle, repo));
                }
        }
예제 #6
0
        /// <summary>
        /// Push specified references to the <see cref="Remote"/>.
        /// </summary>
        /// <param name="remote">The <see cref="Remote"/> to push to.</param>
        /// <param name="pushRefSpecs">The pushRefSpecs to push.</param>
        /// <param name="pushOptions"><see cref="PushOptions"/> controlling push behavior</param>
        /// <param name="signature">Identity for use when updating the reflog.</param>
        /// <param name="logMessage">Message to use when updating the reflog.</param>
        public virtual void Push(
            Remote remote,
            IEnumerable <string> pushRefSpecs,
            PushOptions pushOptions = null,
            Signature signature     = null,
            string logMessage       = null)
        {
            Ensure.ArgumentNotNull(remote, "remote");
            Ensure.ArgumentNotNull(pushRefSpecs, "pushRefSpecs");

            // Return early if there is nothing to push.
            if (!pushRefSpecs.Any())
            {
                return;
            }

            if (pushOptions == null)
            {
                pushOptions = new PushOptions();
            }

            // Load the remote.
            using (RemoteSafeHandle remoteHandle = Proxy.git_remote_lookup(repository.Handle, remote.Name, true))
            {
                var callbacks = new RemoteCallbacks(pushOptions);
                GitRemoteCallbacks gitCallbacks = callbacks.GenerateCallbacks();
                Proxy.git_remote_set_callbacks(remoteHandle, ref gitCallbacks);

                try
                {
                    Proxy.git_remote_connect(remoteHandle, GitDirection.Push);
                    Proxy.git_remote_push(remoteHandle, pushRefSpecs,
                                          new GitPushOptions()
                    {
                        PackbuilderDegreeOfParallelism = pushOptions.PackbuilderDegreeOfParallelism
                    },
                                          signature.OrDefault(repository.Config), logMessage);
                }
                finally
                {
                    Proxy.git_remote_disconnect(remoteHandle);
                }
            }
        }
예제 #7
0
        /// <summary>
        /// Updates the target of a reference
        /// </summary>
        /// <param name="refsColl">The <see cref="ReferenceCollection"/> being worked with.</param>
        /// <param name="name">The canonical name of the reference.</param>
        /// <param name="canonicalRefNameOrObjectish">The target which can be either the canonical name of a reference or a revparse spec.</param>
        /// <param name="signature">The identity used for updating the reflog</param>
        /// <param name="logMessage">The optional message to log in the <see cref="ReflogCollection"/> of the <paramref name="name"/> reference.</param>
        /// <returns>A new <see cref="Reference"/>.</returns>
        public static Reference UpdateTarget(this ReferenceCollection refsColl, string name, string canonicalRefNameOrObjectish, Signature signature, string logMessage)
        {
            Ensure.ArgumentNotNullOrEmptyString(name, "name");
            Ensure.ArgumentNotNullOrEmptyString(canonicalRefNameOrObjectish, "canonicalRefNameOrObjectish");

            signature = signature.OrDefault(refsColl.repo.Config);

            if (name == "HEAD")
            {
                return(refsColl.UpdateHeadTarget(canonicalRefNameOrObjectish, signature, logMessage));
            }

            Reference reference = refsColl[name];

            var directReference = reference as DirectReference;

            if (directReference != null)
            {
                return(refsColl.UpdateTarget(directReference, canonicalRefNameOrObjectish, signature, logMessage));
            }

            var symbolicReference = reference as SymbolicReference;

            if (symbolicReference != null)
            {
                Reference targetRef;

                RefState refState = TryResolveReference(out targetRef, refsColl, canonicalRefNameOrObjectish);

                if (refState == RefState.DoesNotLookValid)
                {
                    throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "The reference specified by {0} is a Symbolic reference, you must provide a reference canonical name as the target.", name), "canonicalRefNameOrObjectish");
                }

                return(refsColl.UpdateTarget(symbolicReference, targetRef, signature, logMessage));
            }

            throw new LibGit2SharpException(string.Format(CultureInfo.InvariantCulture, "Reference '{0}' has an unexpected type ('{1}').", name, reference.GetType()));
        }
예제 #8
0
        /// <summary>
        /// Create a new local branch with the specified name
        /// </summary>
        /// <param name="name">The name of the branch.</param>
        /// <param name="commit">The target commit.</param>
        /// <param name="signature">Identity used for updating the reflog</param>
        /// <param name="logMessage">Message added to the reflog. If null, the default is "branch: Created from [sha]".</param>
        /// <param name="allowOverwrite">True to allow silent overwriting a potentially existing branch, false otherwise.</param>
        /// <returns>A new <see cref="Branch"/>.</returns>
        public virtual Branch Add(string name, Commit commit, Signature signature, string logMessage = null, bool allowOverwrite = false)
        {
            Ensure.ArgumentNotNullOrEmptyString(name, "name");
            Ensure.ArgumentNotNull(commit, "commit");

            if (logMessage == null)
            {
                logMessage = "branch: Created from " + commit.Id;
            }

            using (Proxy.git_branch_create(repo.Handle, name, commit.Id, allowOverwrite, signature.OrDefault(repo.Config), logMessage)) {}

            var branch = this[ShortToLocalName(name)];

            return(branch);
        }
예제 #9
0
        /// <summary>
        /// Creates a direct reference with the specified name and target
        /// </summary>
        /// <param name="name">The canonical name of the reference to create.</param>
        /// <param name="targetId">Id of the target object.</param>
        /// <param name="signature">Identity used for updating the reflog.</param>
        /// <param name="logMessage">The optional message to log in the <see cref="ReflogCollection"/> when adding the <see cref="DirectReference"/></param>
        /// <param name="allowOverwrite">True to allow silent overwriting a potentially existing reference, false otherwise.</param>
        /// <returns>A new <see cref="Reference"/>.</returns>
        public virtual DirectReference Add(string name, ObjectId targetId, Signature signature, string logMessage, bool allowOverwrite = false)
        {
            Ensure.ArgumentNotNullOrEmptyString(name, "name");
            Ensure.ArgumentNotNull(targetId, "targetId");

            using (ReferenceSafeHandle handle = Proxy.git_reference_create(repo.Handle, name, targetId, allowOverwrite, signature.OrDefault(repo.Config), logMessage))
            {
                return((DirectReference)Reference.BuildFromPtr <Reference>(handle, repo));
            }
        }
예제 #10
0
        /// <summary>
        /// Rename an existing reference with a new name, and update the reflog
        /// </summary>
        /// <param name="reference">The reference to rename.</param>
        /// <param name="newName">The new canonical name.</param>
        /// <param name="signature">Identity used for updating the reflog.</param>
        /// <param name="logMessage">Message added to the reflog.</param>
        /// <param name="allowOverwrite">True to allow silent overwriting a potentially existing reference, false otherwise.</param>
        /// <returns>A new <see cref="Reference"/>.</returns>
        public virtual Reference Rename(Reference reference, string newName, Signature signature, string logMessage = null, bool allowOverwrite = false)
        {
            Ensure.ArgumentNotNull(reference, "reference");
            Ensure.ArgumentNotNullOrEmptyString(newName, "newName");

            if (logMessage == null)
            {
                logMessage = string.Format(CultureInfo.InvariantCulture, "{0}: renamed {1} to {2}",
                                           reference.IsLocalBranch() ? "branch" : "reference", reference.CanonicalName, newName);
            }

            using (ReferenceSafeHandle referencePtr = RetrieveReferencePtr(reference.CanonicalName))
                using (ReferenceSafeHandle handle = Proxy.git_reference_rename(referencePtr, newName, allowOverwrite, signature.OrDefault(repo.Config), logMessage))
                {
                    return(Reference.BuildFromPtr <Reference>(handle, repo));
                }
        }
예제 #11
0
        /// <summary>
        /// Creates a symbolic reference with the specified name and target
        /// </summary>
        /// <param name="name">The canonical name of the reference to create.</param>
        /// <param name="targetRef">The target reference.</param>
        /// <param name="signature">Identity used for updating the reflog.</param>
        /// <param name="logMessage">The optional message to log in the <see cref="ReflogCollection"/> when adding the <see cref="SymbolicReference"/></param>
        /// <param name="allowOverwrite">True to allow silent overwriting a potentially existing reference, false otherwise.</param>
        /// <returns>A new <see cref="Reference"/>.</returns>
        public virtual SymbolicReference Add(string name, Reference targetRef, Signature signature, string logMessage, bool allowOverwrite = false)
        {
            Ensure.ArgumentNotNullOrEmptyString(name, "name");
            Ensure.ArgumentNotNull(targetRef, "targetRef");

            using (ReferenceSafeHandle handle = Proxy.git_reference_symbolic_create(repo.Handle, name, targetRef.CanonicalName,
                                                                                    allowOverwrite, signature.OrDefault(repo.Config), logMessage))
            {
                return((SymbolicReference)Reference.BuildFromPtr <Reference>(handle, repo));
            }
        }
예제 #12
0
        /// <summary>
        /// Push specified references to the <see cref="Remote"/>.
        /// </summary>
        /// <param name="remote">The <see cref="Remote"/> to push to.</param>
        /// <param name="pushRefSpecs">The pushRefSpecs to push.</param>
        /// <param name="pushOptions"><see cref="PushOptions"/> controlling push behavior</param>
        /// <param name="signature">Identity for use when updating the reflog.</param>
        /// <param name="logMessage">Message to use when updating the reflog.</param>
        public virtual void Push(
            Remote remote,
            IEnumerable <string> pushRefSpecs,
            PushOptions pushOptions = null,
            Signature signature     = null,
            string logMessage       = null)
        {
            Ensure.ArgumentNotNull(remote, "remote");
            Ensure.ArgumentNotNull(pushRefSpecs, "pushRefSpecs");

            // The following local variables are protected from garbage collection
            // by a GC.KeepAlive call at the end of the method. Otherwise,
            // random crashes during push progress reporting could occur.
            PushTransferCallbacks pushTransferCallbacks;
            PackbuilderCallbacks  packBuilderCallbacks;

            NativeMethods.git_push_transfer_progress pushProgress;
            NativeMethods.git_packbuilder_progress   packBuilderProgress;

            // Return early if there is nothing to push.
            if (!pushRefSpecs.Any())
            {
                return;
            }

            if (pushOptions == null)
            {
                pushOptions = new PushOptions();
            }

            PushCallbacks pushStatusUpdates = new PushCallbacks(pushOptions.OnPushStatusError);

            // Load the remote.
            using (RemoteSafeHandle remoteHandle = Proxy.git_remote_load(repository.Handle, remote.Name, true))
            {
                var callbacks = new RemoteCallbacks(null, null, null, pushOptions.Credentials);
                GitRemoteCallbacks gitCallbacks = callbacks.GenerateCallbacks();
                Proxy.git_remote_set_callbacks(remoteHandle, ref gitCallbacks);

                try
                {
                    Proxy.git_remote_connect(remoteHandle, GitDirection.Push);

                    // Perform the actual push.
                    using (PushSafeHandle pushHandle = Proxy.git_push_new(remoteHandle))
                    {
                        pushTransferCallbacks = new PushTransferCallbacks(pushOptions.OnPushTransferProgress);
                        packBuilderCallbacks  = new PackbuilderCallbacks(pushOptions.OnPackBuilderProgress);

                        pushProgress        = pushTransferCallbacks.GenerateCallback();
                        packBuilderProgress = packBuilderCallbacks.GenerateCallback();

                        Proxy.git_push_set_callbacks(pushHandle, pushProgress, packBuilderProgress);

                        // Set push options.
                        Proxy.git_push_set_options(pushHandle,
                                                   new GitPushOptions()
                        {
                            PackbuilderDegreeOfParallelism = pushOptions.PackbuilderDegreeOfParallelism
                        });

                        // Add refspecs.
                        foreach (string pushRefSpec in pushRefSpecs)
                        {
                            Proxy.git_push_add_refspec(pushHandle, pushRefSpec);
                        }

                        Proxy.git_push_finish(pushHandle);

                        if (!Proxy.git_push_unpack_ok(pushHandle))
                        {
                            throw new LibGit2SharpException("Push failed - remote did not successfully unpack.");
                        }

                        Proxy.git_push_status_foreach(pushHandle, pushStatusUpdates.Callback);
                        Proxy.git_push_update_tips(pushHandle, signature.OrDefault(repository.Config), logMessage);
                    }
                }
                finally
                {
                    Proxy.git_remote_disconnect(remoteHandle);
                }
            }

            GC.KeepAlive(pushProgress);
            GC.KeepAlive(packBuilderProgress);
            GC.KeepAlive(pushTransferCallbacks);
            GC.KeepAlive(packBuilderCallbacks);
        }
예제 #13
0
        /// <summary>
        /// Creates a direct or symbolic reference with the specified name and target
        /// </summary>
        /// <param name="refsColl">The <see cref="ReferenceCollection"/> being worked with.</param>
        /// <param name="name">The name of the reference to create.</param>
        /// <param name="canonicalRefNameOrObjectish">The target which can be either the canonical name of a reference or a revparse spec.</param>
        /// <param name="signature">The identity used for updating the reflog</param>
        /// <param name="logMessage">The optional message to log in the <see cref="ReflogCollection"/> when adding the <see cref="Reference"/></param>
        /// <param name="allowOverwrite">True to allow silent overwriting a potentially existing reference, false otherwise.</param>
        /// <returns>A new <see cref="Reference"/>.</returns>
        public static Reference Add(this ReferenceCollection refsColl, string name, string canonicalRefNameOrObjectish, Signature signature, string logMessage, bool allowOverwrite = false)
        {
            Ensure.ArgumentNotNullOrEmptyString(name, "name");
            Ensure.ArgumentNotNullOrEmptyString(canonicalRefNameOrObjectish, "canonicalRefNameOrObjectish");

            Reference reference;
            RefState  refState = TryResolveReference(out reference, refsColl, canonicalRefNameOrObjectish);

            var gitObject = refsColl.repo.Lookup(canonicalRefNameOrObjectish, GitObjectType.Any, LookUpOptions.None);

            if (refState == RefState.Exists)
            {
                return(refsColl.Add(name, reference, signature, logMessage, allowOverwrite));
            }

            if (refState == RefState.DoesNotExistButLooksValid && gitObject == null)
            {
                using (ReferenceSafeHandle handle = Proxy.git_reference_symbolic_create(refsColl.repo.Handle, name, canonicalRefNameOrObjectish, allowOverwrite,
                                                                                        signature.OrDefault(refsColl.repo.Config), logMessage))
                {
                    return(Reference.BuildFromPtr <Reference>(handle, refsColl.repo));
                }
            }

            Ensure.GitObjectIsNotNull(gitObject, canonicalRefNameOrObjectish);

            if (logMessage == null)
            {
                logMessage = string.Format(CultureInfo.InvariantCulture, "{0}: Created from {1}",
                                           name.LooksLikeLocalBranch() ? "branch" : "reference", canonicalRefNameOrObjectish);
            }

            refsColl.EnsureHasLog(name);
            return(refsColl.Add(name, gitObject.Id, signature, logMessage, allowOverwrite));
        }