/// <exception cref="NGit.Errors.MissingObjectException"></exception>
        /// <exception cref="System.IO.IOException"></exception>
        private ObjectIdRef DoPeel(Ref leaf)
        {
            RevWalk rw = new RevWalk(GetRepository());

            try
            {
                RevObject obj = rw.ParseAny(leaf.GetObjectId());
                if (obj is RevTag)
                {
                    return(new ObjectIdRef.PeeledTag(leaf.GetStorage(), leaf.GetName(), leaf.GetObjectId
                                                         (), rw.Peel(obj).Copy()));
                }
                else
                {
                    return(new ObjectIdRef.PeeledNonTag(leaf.GetStorage(), leaf.GetName(), leaf.GetObjectId
                                                            ()));
                }
            }
            finally
            {
                rw.Release();
            }
        }
        /// <exception cref="NGit.Api.Errors.RefAlreadyExistsException">
        /// when trying to create (without force) a branch with a name
        /// that already exists
        /// </exception>
        /// <exception cref="NGit.Api.Errors.RefNotFoundException">if the start point can not be found
        ///     </exception>
        /// <exception cref="NGit.Api.Errors.InvalidRefNameException">
        /// if the provided name is <code>null</code> or otherwise
        /// invalid
        /// </exception>
        /// <returns>the newly created branch</returns>
        /// <exception cref="NGit.Api.Errors.GitAPIException"></exception>
        public override Ref Call()
        {
            CheckCallable();
            ProcessOptions();
            RevWalk revWalk = new RevWalk(repo);

            try
            {
                Ref  refToCheck = repo.GetRef(name);
                bool exists     = refToCheck != null && refToCheck.GetName().StartsWith(Constants.R_HEADS
                                                                                        );
                if (!force && exists)
                {
                    throw new RefAlreadyExistsException(MessageFormat.Format(JGitText.Get().refAlreadyExists1
                                                                             , name));
                }
                ObjectId startAt            = GetStartPoint();
                string   startPointFullName = null;
                if (startPoint != null)
                {
                    Ref baseRef = repo.GetRef(startPoint);
                    if (baseRef != null)
                    {
                        startPointFullName = baseRef.GetName();
                    }
                }
                // determine whether we are based on a commit,
                // a branch, or a tag and compose the reflog message
                string refLogMessage;
                string baseBranch = string.Empty;
                if (startPointFullName == null)
                {
                    string baseCommit;
                    if (startCommit != null)
                    {
                        baseCommit = startCommit.GetShortMessage();
                    }
                    else
                    {
                        RevCommit commit = revWalk.ParseCommit(repo.Resolve(startPoint));
                        baseCommit = commit.GetShortMessage();
                    }
                    if (exists)
                    {
                        refLogMessage = "branch: Reset start-point to commit " + baseCommit;
                    }
                    else
                    {
                        refLogMessage = "branch: Created from commit " + baseCommit;
                    }
                }
                else
                {
                    if (startPointFullName.StartsWith(Constants.R_HEADS) || startPointFullName.StartsWith
                            (Constants.R_REMOTES))
                    {
                        baseBranch = startPointFullName;
                        if (exists)
                        {
                            refLogMessage = "branch: Reset start-point to branch " + startPointFullName;
                        }
                        else
                        {
                            // TODO
                            refLogMessage = "branch: Created from branch " + baseBranch;
                        }
                    }
                    else
                    {
                        startAt = revWalk.Peel(revWalk.ParseAny(startAt));
                        if (exists)
                        {
                            refLogMessage = "branch: Reset start-point to tag " + startPointFullName;
                        }
                        else
                        {
                            refLogMessage = "branch: Created from tag " + startPointFullName;
                        }
                    }
                }
                RefUpdate updateRef = repo.UpdateRef(Constants.R_HEADS + name);
                updateRef.SetNewObjectId(startAt);
                updateRef.SetRefLogMessage(refLogMessage, false);
                RefUpdate.Result updateResult;
                if (exists && force)
                {
                    updateResult = updateRef.ForceUpdate();
                }
                else
                {
                    updateResult = updateRef.Update();
                }
                SetCallable(false);
                bool ok = false;
                switch (updateResult)
                {
                case RefUpdate.Result.NEW:
                {
                    ok = !exists;
                    break;
                }

                case RefUpdate.Result.NO_CHANGE:
                case RefUpdate.Result.FAST_FORWARD:
                case RefUpdate.Result.FORCED:
                {
                    ok = exists;
                    break;
                }

                default:
                {
                    break;
                    break;
                }
                }
                if (!ok)
                {
                    throw new JGitInternalException(MessageFormat.Format(JGitText.Get().createBranchUnexpectedResult
                                                                         , updateResult.ToString()));
                }
                Ref result = repo.GetRef(name);
                if (result == null)
                {
                    throw new JGitInternalException(JGitText.Get().createBranchFailedUnknownReason);
                }
                if (baseBranch.Length == 0)
                {
                    return(result);
                }
                // if we are based on another branch, see
                // if we need to configure upstream configuration: first check
                // whether the setting was done explicitly
                bool doConfigure;
                if (upstreamMode == CreateBranchCommand.SetupUpstreamMode.SET_UPSTREAM || upstreamMode
                    == CreateBranchCommand.SetupUpstreamMode.TRACK)
                {
                    // explicitly set to configure
                    doConfigure = true;
                }
                else
                {
                    if (upstreamMode == CreateBranchCommand.SetupUpstreamMode.NOTRACK)
                    {
                        // explicitly set to not configure
                        doConfigure = false;
                    }
                    else
                    {
                        // if there was no explicit setting, check the configuration
                        string autosetupflag = repo.GetConfig().GetString(ConfigConstants.CONFIG_BRANCH_SECTION
                                                                          , null, ConfigConstants.CONFIG_KEY_AUTOSETUPMERGE);
                        if ("false".Equals(autosetupflag))
                        {
                            doConfigure = false;
                        }
                        else
                        {
                            if ("always".Equals(autosetupflag))
                            {
                                doConfigure = true;
                            }
                            else
                            {
                                // in this case, the default is to configure
                                // only in case the base branch was a remote branch
                                doConfigure = baseBranch.StartsWith(Constants.R_REMOTES);
                            }
                        }
                    }
                }
                if (doConfigure)
                {
                    StoredConfig config   = repo.GetConfig();
                    string[]     tokens   = baseBranch.RegexSplit("/", 4);
                    bool         isRemote = tokens[1].Equals("remotes");
                    if (isRemote)
                    {
                        // refs/remotes/<remote name>/<branch>
                        string remoteName = tokens[2];
                        string branchName = tokens[3];
                        config.SetString(ConfigConstants.CONFIG_BRANCH_SECTION, name, ConfigConstants.CONFIG_KEY_REMOTE
                                         , remoteName);
                        config.SetString(ConfigConstants.CONFIG_BRANCH_SECTION, name, ConfigConstants.CONFIG_KEY_MERGE
                                         , Constants.R_HEADS + branchName);
                    }
                    else
                    {
                        // set "." as remote
                        config.SetString(ConfigConstants.CONFIG_BRANCH_SECTION, name, ConfigConstants.CONFIG_KEY_REMOTE
                                         , ".");
                        config.SetString(ConfigConstants.CONFIG_BRANCH_SECTION, name, ConfigConstants.CONFIG_KEY_MERGE
                                         , baseBranch);
                    }
                    config.Save();
                }
                return(result);
            }
            catch (IOException ioe)
            {
                throw new JGitInternalException(ioe.Message, ioe);
            }
            finally
            {
                revWalk.Release();
            }
        }
Ejemplo n.º 3
0
        /// <exception cref="System.IO.IOException"></exception>
        private ObjectId ProcessHaveLines(IList <ObjectId> peerHas, ObjectId last)
        {
            if (peerHas.IsEmpty())
            {
                return(last);
            }
            IList <ObjectId>   toParse    = peerHas;
            HashSet <ObjectId> peerHasSet = null;
            bool needMissing = false;

            if (wantAll.IsEmpty() && !wantIds.IsEmpty())
            {
                // We have not yet parsed the want list. Parse it now.
                peerHasSet = new HashSet <ObjectId>(peerHas);
                int cnt = wantIds.Count + peerHasSet.Count;
                toParse = new AList <ObjectId>(cnt);
                Sharpen.Collections.AddAll(toParse, wantIds);
                Sharpen.Collections.AddAll(toParse, peerHasSet);
                needMissing = true;
            }
            AsyncRevObjectQueue q = walk.ParseAny(toParse.AsIterable(), needMissing);

            try
            {
                for (; ;)
                {
                    RevObject obj;
                    try
                    {
                        obj = q.Next();
                    }
                    catch (MissingObjectException notFound)
                    {
                        ObjectId id = notFound.GetObjectId();
                        if (wantIds.Contains(id))
                        {
                            string msg = MessageFormat.Format(JGitText.Get().wantNotValid, id.Name);
                            pckOut.WriteString("ERR " + msg);
                            throw new PackProtocolException(msg, notFound);
                        }
                        continue;
                    }
                    if (obj == null)
                    {
                        break;
                    }
                    // If the object is still found in wantIds, the want
                    // list wasn't parsed earlier, and was done in this batch.
                    //
                    if (wantIds.Remove(obj))
                    {
                        if (!advertised.Contains(obj))
                        {
                            string msg = MessageFormat.Format(JGitText.Get().wantNotValid, obj.Name);
                            pckOut.WriteString("ERR " + msg);
                            throw new PackProtocolException(msg);
                        }
                        if (!obj.Has(WANT))
                        {
                            obj.Add(WANT);
                            wantAll.AddItem(obj);
                        }
                        if (!(obj is RevCommit))
                        {
                            obj.Add(SATISFIED);
                        }
                        if (obj is RevTag)
                        {
                            RevObject target = walk.Peel(obj);
                            if (target is RevCommit)
                            {
                                if (!target.Has(WANT))
                                {
                                    target.Add(WANT);
                                    wantAll.AddItem(target);
                                }
                            }
                        }
                        if (!peerHasSet.Contains(obj))
                        {
                            continue;
                        }
                    }
                    last = obj;
                    if (obj is RevCommit)
                    {
                        RevCommit c = (RevCommit)obj;
                        if (oldestTime == 0 || c.CommitTime < oldestTime)
                        {
                            oldestTime = c.CommitTime;
                        }
                    }
                    if (obj.Has(PEER_HAS))
                    {
                        continue;
                    }
                    obj.Add(PEER_HAS);
                    if (obj is RevCommit)
                    {
                        ((RevCommit)obj).Carry(PEER_HAS);
                    }
                    AddCommonBase(obj);
                    switch (multiAck)
                    {
                    case BasePackFetchConnection.MultiAck.OFF:
                    {
                        // If both sides have the same object; let the client know.
                        //
                        if (commonBase.Count == 1)
                        {
                            pckOut.WriteString("ACK " + obj.Name + "\n");
                        }
                        break;
                    }

                    case BasePackFetchConnection.MultiAck.CONTINUE:
                    {
                        pckOut.WriteString("ACK " + obj.Name + " continue\n");
                        break;
                    }

                    case BasePackFetchConnection.MultiAck.DETAILED:
                    {
                        pckOut.WriteString("ACK " + obj.Name + " common\n");
                        break;
                    }
                    }
                }
            }
            finally
            {
                q.Release();
            }
            // If we don't have one of the objects but we're also willing to
            // create a pack at this point, let the client know so it stops
            // telling us about its history.
            //
            bool didOkToGiveUp = false;

            for (int i = peerHas.Count - 1; i >= 0; i--)
            {
                ObjectId id = peerHas[i];
                if (walk.LookupOrNull(id) == null)
                {
                    didOkToGiveUp = true;
                    if (OkToGiveUp())
                    {
                        switch (multiAck)
                        {
                        case BasePackFetchConnection.MultiAck.OFF:
                        {
                            break;
                        }

                        case BasePackFetchConnection.MultiAck.CONTINUE:
                        {
                            pckOut.WriteString("ACK " + id.Name + " continue\n");
                            break;
                        }

                        case BasePackFetchConnection.MultiAck.DETAILED:
                        {
                            pckOut.WriteString("ACK " + id.Name + " ready\n");
                            break;
                        }
                        }
                    }
                    break;
                }
            }
            if (multiAck == BasePackFetchConnection.MultiAck.DETAILED && !didOkToGiveUp && OkToGiveUp
                    ())
            {
                ObjectId id = peerHas[peerHas.Count - 1];
                pckOut.WriteString("ACK " + id.Name + " ready\n");
            }
            peerHas.Clear();
            return(last);
        }