/// <exception cref="NGit.Errors.TransportException"></exception> protected internal override void DoFetch(ProgressMonitor monitor, ICollection <Ref > want, ICollection <ObjectId> have) { MarkLocalRefsComplete(have); QueueWants(want); while (!monitor.IsCancelled() && !workQueue.IsEmpty()) { ObjectId id = workQueue.RemoveFirst(); if (!(id is RevObject) || !((RevObject)id).Has(COMPLETE)) { DownloadObject(monitor, id); } Process(id); } }
/// <exception cref="System.IO.IOException"></exception> public override void Write(byte[] b, int off, int len) { while (0 < len) { int n = Math.Min(len, BYTES_TO_WRITE_BEFORE_CANCEL_CHECK); count += n; if (checkCancelAt <= count) { if (writeMonitor.IsCancelled()) { throw new IOException(JGitText.Get().packingCancelledDuringObjectsWriting); } checkCancelAt = count + BYTES_TO_WRITE_BEFORE_CANCEL_CHECK; } @out.Write(b, off, n); crc.Update(b, off, n); md.Update(b, off, n); off += n; len -= n; } }
/// <exception cref="System.IO.IOException"></exception> private void WriteCommands(ICollection <RemoteRefUpdate> refUpdates, ProgressMonitor monitor) { string capabilities = EnableCapabilities(monitor); foreach (RemoteRefUpdate rru in refUpdates) { if (!capableDeleteRefs && rru.IsDelete()) { rru.SetStatus(RemoteRefUpdate.Status.REJECTED_NODELETE); continue; } StringBuilder sb = new StringBuilder(); Ref advertisedRef = GetRef(rru.GetRemoteName()); ObjectId oldId = (advertisedRef == null ? ObjectId.ZeroId : advertisedRef.GetObjectId ()); sb.Append(oldId.Name); sb.Append(' '); sb.Append(rru.GetNewObjectId().Name); sb.Append(' '); sb.Append(rru.GetRemoteName()); if (!sentCommand) { sentCommand = true; sb.Append(capabilities); } pckOut.WriteString(sb.ToString()); rru.SetStatus(RemoteRefUpdate.Status.AWAITING_REPORT); if (!rru.IsDelete()) { writePack = true; } } if (monitor.IsCancelled()) { throw new TransportException(uri, JGitText.Get().pushCancelled); } pckOut.End(); outNeedsEnd = false; }
/// <summary> /// Executes the /// <code>Rebase</code> /// command with all the options and parameters /// collected by the setter methods of this class. Each instance of this /// class should only be used for one invocation of the command. Don't call /// this method twice on an instance. /// </summary> /// <returns>an object describing the result of this command</returns> /// <exception cref="NGit.Api.Errors.NoHeadException"></exception> /// <exception cref="NGit.Api.Errors.RefNotFoundException"></exception> /// <exception cref="NGit.Api.Errors.JGitInternalException"></exception> /// <exception cref="NGit.Api.Errors.GitAPIException"></exception> public override RebaseResult Call() { RevCommit newHead = null; bool lastStepWasForward = false; CheckCallable(); CheckParameters(); try { switch (operation) { case RebaseCommand.Operation.ABORT: { try { return(Abort()); } catch (IOException ioe) { throw new JGitInternalException(ioe.Message, ioe); } goto case RebaseCommand.Operation.SKIP; } case RebaseCommand.Operation.SKIP: case RebaseCommand.Operation.CONTINUE: { // fall through string upstreamCommitName = ReadFile(rebaseDir, ONTO); this.upstreamCommit = walk.ParseCommit(repo.Resolve(upstreamCommitName)); break; } case RebaseCommand.Operation.BEGIN: { RebaseResult res = InitFilesAndRewind(); if (res != null) { return(res); } break; } } if (monitor.IsCancelled()) { return(Abort()); } if (this.operation == RebaseCommand.Operation.CONTINUE) { newHead = ContinueRebase(); } if (this.operation == RebaseCommand.Operation.SKIP) { newHead = CheckoutCurrentHead(); } ObjectReader or = repo.NewObjectReader(); IList <RebaseCommand.Step> steps = LoadSteps(); foreach (RebaseCommand.Step step in steps) { PopSteps(1); ICollection <ObjectId> ids = or.Resolve(step.commit); if (ids.Count != 1) { throw new JGitInternalException("Could not resolve uniquely the abbreviated object ID" ); } RevCommit commitToPick = walk.ParseCommit(ids.Iterator().Next()); if (monitor.IsCancelled()) { return(new RebaseResult(commitToPick)); } monitor.BeginTask(MessageFormat.Format(JGitText.Get().applyingCommit, commitToPick .GetShortMessage()), ProgressMonitor.UNKNOWN); // if the first parent of commitToPick is the current HEAD, // we do a fast-forward instead of cherry-pick to avoid // unnecessary object rewriting newHead = TryFastForward(commitToPick); lastStepWasForward = newHead != null; if (!lastStepWasForward) { // TODO if the content of this commit is already merged here // we should skip this step in order to avoid confusing // pseudo-changed newHead = new Git(repo).CherryPick().Include(commitToPick).Call(); } monitor.EndTask(); if (newHead == null) { return(Stop(commitToPick)); } } if (newHead != null) { // point the previous head (if any) to the new commit string headName = ReadFile(rebaseDir, HEAD_NAME); if (headName.StartsWith(Constants.R_REFS)) { RefUpdate rup = repo.UpdateRef(headName); rup.SetNewObjectId(newHead); RefUpdate.Result res_1 = rup.ForceUpdate(); switch (res_1) { case RefUpdate.Result.FAST_FORWARD: case RefUpdate.Result.FORCED: case RefUpdate.Result.NO_CHANGE: { break; } default: { throw new JGitInternalException("Updating HEAD failed"); } } rup = repo.UpdateRef(Constants.HEAD); res_1 = rup.Link(headName); switch (res_1) { case RefUpdate.Result.FAST_FORWARD: case RefUpdate.Result.FORCED: case RefUpdate.Result.NO_CHANGE: { break; } default: { throw new JGitInternalException("Updating HEAD failed"); } } } FileUtils.Delete(rebaseDir, FileUtils.RECURSIVE); if (lastStepWasForward) { return(new RebaseResult(RebaseResult.Status.FAST_FORWARD)); } return(new RebaseResult(RebaseResult.Status.OK)); } return(new RebaseResult(RebaseResult.Status.UP_TO_DATE)); } catch (IOException ioe) { throw new JGitInternalException(ioe.Message, ioe); } }
/// <exception cref="System.IO.IOException"></exception> /// <exception cref="NGit.Transport.BasePackFetchConnection.CancelledException"></exception> private void Negotiate(ProgressMonitor monitor) { MutableObjectId ackId = new MutableObjectId(); int resultsPending = 0; int havesSent = 0; int havesSinceLastContinue = 0; bool receivedContinue = false; bool receivedAck = false; bool receivedReady = false; if (statelessRPC) { state.WriteTo(@out, null); } NegotiateBegin(); while (!receivedReady) { RevCommit c = walk.Next(); if (c == null) { goto SEND_HAVES_break; } pckOut.WriteString("have " + c.Id.Name + "\n"); havesSent++; havesSinceLastContinue++; if ((31 & havesSent) != 0) { // We group the have lines into blocks of 32, each marked // with a flush (aka end). This one is within a block so // continue with another have line. // continue; } if (monitor.IsCancelled()) { throw new BasePackFetchConnection.CancelledException(); } pckOut.End(); resultsPending++; // Each end will cause a result to come back. if (havesSent == 32 && !statelessRPC) { // On the first block we race ahead and try to send // more of the second block while waiting for the // remote to respond to our first block request. // This keeps us one block ahead of the peer. // continue; } for (; ;) { PacketLineIn.AckNackResult anr = pckIn.ReadACK(ackId); switch (anr) { case PacketLineIn.AckNackResult.NAK: { // More have lines are necessary to compute the // pack on the remote side. Keep doing that. // resultsPending--; goto READ_RESULT_break; } case PacketLineIn.AckNackResult.ACK: { // The remote side is happy and knows exactly what // to send us. There is no further negotiation and // we can break out immediately. // multiAck = BasePackFetchConnection.MultiAck.OFF; resultsPending = 0; receivedAck = true; if (statelessRPC) { state.WriteTo(@out, null); } goto SEND_HAVES_break; } case PacketLineIn.AckNackResult.ACK_CONTINUE: case PacketLineIn.AckNackResult.ACK_COMMON: case PacketLineIn.AckNackResult.ACK_READY: { // The server knows this commit (ackId). We don't // need to send any further along its ancestry, but // we need to continue to talk about other parts of // our local history. // MarkCommon(walk.ParseAny(ackId), anr); receivedAck = true; receivedContinue = true; havesSinceLastContinue = 0; if (anr == PacketLineIn.AckNackResult.ACK_READY) { receivedReady = true; } break; } } if (monitor.IsCancelled()) { throw new BasePackFetchConnection.CancelledException(); } READ_RESULT_continue :; } READ_RESULT_break :; if (statelessRPC) { state.WriteTo(@out, null); } if (receivedContinue && havesSinceLastContinue > MAX_HAVES) { // Our history must be really different from the remote's. // We just sent a whole slew of have lines, and it did not // recognize any of them. Avoid sending our entire history // to them by giving up early. // goto SEND_HAVES_break; } SEND_HAVES_continue :; } SEND_HAVES_break :; // Tell the remote side we have run out of things to talk about. // if (monitor.IsCancelled()) { throw new BasePackFetchConnection.CancelledException(); } if (!receivedReady || !noDone) { // When statelessRPC is true we should always leave SEND_HAVES // loop above while in the middle of a request. This allows us // to just write done immediately. // pckOut.WriteString("done\n"); pckOut.Flush(); } if (!receivedAck) { // Apparently if we have never received an ACK earlier // there is one more result expected from the done we // just sent to the remote. // multiAck = BasePackFetchConnection.MultiAck.OFF; resultsPending++; } while (resultsPending > 0 || multiAck != BasePackFetchConnection.MultiAck.OFF) { PacketLineIn.AckNackResult anr = pckIn.ReadACK(ackId); resultsPending--; switch (anr) { case PacketLineIn.AckNackResult.NAK: { // A NAK is a response to an end we queued earlier // we eat it and look for another ACK/NAK message. // break; } case PacketLineIn.AckNackResult.ACK: { // A solitary ACK at this point means the remote won't // speak anymore, but is going to send us a pack now. // goto READ_RESULT_break2; } case PacketLineIn.AckNackResult.ACK_CONTINUE: case PacketLineIn.AckNackResult.ACK_COMMON: case PacketLineIn.AckNackResult.ACK_READY: { // We will expect a normal ACK to break out of the loop. // multiAck = BasePackFetchConnection.MultiAck.CONTINUE; break; } } if (monitor.IsCancelled()) { throw new BasePackFetchConnection.CancelledException(); } READ_RESULT_continue :; } READ_RESULT_break2 :; }
/// <summary> /// Executes the /// <code>Pull</code> /// command with all the options and parameters /// collected by the setter methods (e.g. /// <see cref="SetProgressMonitor(NGit.ProgressMonitor)">SetProgressMonitor(NGit.ProgressMonitor) /// </see> /// ) of this class. Each /// instance of this class should only be used for one invocation of the /// command. Don't call this method twice on an instance. /// </summary> /// <returns>the result of the pull</returns> /// <exception cref="NGit.Api.Errors.WrongRepositoryStateException">NGit.Api.Errors.WrongRepositoryStateException /// </exception> /// <exception cref="NGit.Api.Errors.InvalidConfigurationException">NGit.Api.Errors.InvalidConfigurationException /// </exception> /// <exception cref="NGit.Api.Errors.DetachedHeadException">NGit.Api.Errors.DetachedHeadException /// </exception> /// <exception cref="NGit.Api.Errors.InvalidRemoteException">NGit.Api.Errors.InvalidRemoteException /// </exception> /// <exception cref="NGit.Api.Errors.CanceledException">NGit.Api.Errors.CanceledException /// </exception> /// <exception cref="NGit.Api.Errors.RefNotFoundException">NGit.Api.Errors.RefNotFoundException /// </exception> /// <exception cref="NGit.Api.Errors.NoHeadException">NGit.Api.Errors.NoHeadException /// </exception> /// <exception cref="NGit.Api.Errors.TransportException">NGit.Api.Errors.TransportException /// </exception> /// <exception cref="NGit.Api.Errors.GitAPIException">NGit.Api.Errors.GitAPIException /// </exception> public override PullResult Call() { CheckCallable(); monitor.BeginTask(JGitText.Get().pullTaskName, 2); string branchName; try { string fullBranch = repo.GetFullBranch(); if (fullBranch == null) { throw new NoHeadException(JGitText.Get().pullOnRepoWithoutHEADCurrentlyNotSupported ); } if (!fullBranch.StartsWith(Constants.R_HEADS)) { // we can not pull if HEAD is detached and branch is not // specified explicitly throw new DetachedHeadException(); } branchName = Sharpen.Runtime.Substring(fullBranch, Constants.R_HEADS.Length); } catch (IOException e) { throw new JGitInternalException(JGitText.Get().exceptionCaughtDuringExecutionOfPullCommand , e); } if (!repo.GetRepositoryState().Equals(RepositoryState.SAFE)) { throw new WrongRepositoryStateException(MessageFormat.Format(JGitText.Get().cannotPullOnARepoWithState , repo.GetRepositoryState().Name())); } // get the configured remote for the currently checked out branch // stored in configuration key branch.<branch name>.remote Config repoConfig = repo.GetConfig(); string remote = repoConfig.GetString(ConfigConstants.CONFIG_BRANCH_SECTION, branchName , ConfigConstants.CONFIG_KEY_REMOTE); if (remote == null) { // fall back to default remote remote = Constants.DEFAULT_REMOTE_NAME; } // get the name of the branch in the remote repository // stored in configuration key branch.<branch name>.merge string remoteBranchName = repoConfig.GetString(ConfigConstants.CONFIG_BRANCH_SECTION , branchName, ConfigConstants.CONFIG_KEY_MERGE); // check if the branch is configured for pull-rebase bool doRebase = repoConfig.GetBoolean(ConfigConstants.CONFIG_BRANCH_SECTION, branchName , ConfigConstants.CONFIG_KEY_REBASE, false); if (remoteBranchName == null) { string missingKey = ConfigConstants.CONFIG_BRANCH_SECTION + DOT + branchName + DOT + ConfigConstants.CONFIG_KEY_MERGE; throw new InvalidConfigurationException(MessageFormat.Format(JGitText.Get().missingConfigurationForKey , missingKey)); } bool isRemote = !remote.Equals("."); string remoteUri; FetchResult fetchRes; if (isRemote) { remoteUri = repoConfig.GetString(ConfigConstants.CONFIG_REMOTE_SECTION, remote, ConfigConstants .CONFIG_KEY_URL); if (remoteUri == null) { string missingKey = ConfigConstants.CONFIG_REMOTE_SECTION + DOT + remote + DOT + ConfigConstants.CONFIG_KEY_URL; throw new InvalidConfigurationException(MessageFormat.Format(JGitText.Get().missingConfigurationForKey , missingKey)); } if (monitor.IsCancelled()) { throw new CanceledException(MessageFormat.Format(JGitText.Get().operationCanceled , JGitText.Get().pullTaskName)); } FetchCommand fetch = new FetchCommand(repo); fetch.SetRemote(remote); fetch.SetProgressMonitor(monitor); Configure(fetch); fetchRes = fetch.Call(); } else { // we can skip the fetch altogether remoteUri = "local repository"; fetchRes = null; } monitor.Update(1); if (monitor.IsCancelled()) { throw new CanceledException(MessageFormat.Format(JGitText.Get().operationCanceled , JGitText.Get().pullTaskName)); } // we check the updates to see which of the updated branches // corresponds // to the remote branch name AnyObjectId commitToMerge; if (isRemote) { Ref r = null; if (fetchRes != null) { r = fetchRes.GetAdvertisedRef(remoteBranchName); if (r == null) { r = fetchRes.GetAdvertisedRef(Constants.R_HEADS + remoteBranchName); } } if (r == null) { throw new JGitInternalException(MessageFormat.Format(JGitText.Get().couldNotGetAdvertisedRef , remoteBranchName)); } else { commitToMerge = r.GetObjectId(); } } else { try { commitToMerge = repo.Resolve(remoteBranchName); if (commitToMerge == null) { throw new RefNotFoundException(MessageFormat.Format(JGitText.Get().refNotResolved , remoteBranchName)); } } catch (IOException e) { throw new JGitInternalException(JGitText.Get().exceptionCaughtDuringExecutionOfPullCommand , e); } } string upstreamName = "branch \'" + Repository.ShortenRefName(remoteBranchName) + "\' of " + remoteUri; PullResult result; if (doRebase) { RebaseCommand rebase = new RebaseCommand(repo); RebaseResult rebaseRes = rebase.SetUpstream(commitToMerge).SetUpstreamName(upstreamName ).SetProgressMonitor(monitor).SetOperation(RebaseCommand.Operation.BEGIN).Call(); result = new PullResult(fetchRes, remote, rebaseRes); } else { MergeCommand merge = new MergeCommand(repo); merge.Include(upstreamName, commitToMerge); MergeCommandResult mergeRes = merge.Call(); monitor.Update(1); result = new PullResult(fetchRes, remote, mergeRes); } monitor.EndTask(); return result; }
/// <exception cref="NGit.Errors.TransportException"></exception> private bool DownloadPackedObject(ProgressMonitor monitor, AnyObjectId id) { // Search for the object in a remote pack whose index we have, // but whose pack we do not yet have. // Iterator <WalkFetchConnection.RemotePack> packItr = unfetchedPacks.Iterator(); while (packItr.HasNext() && !monitor.IsCancelled()) { WalkFetchConnection.RemotePack pack = packItr.Next(); try { pack.OpenIndex(monitor); } catch (IOException err) { // If the index won't open its either not found or // its a format we don't recognize. In either case // we may still be able to obtain the object from // another source, so don't consider it a failure. // RecordError(id, err); packItr.Remove(); continue; } if (monitor.IsCancelled()) { // If we were cancelled while the index was opening // the open may have aborted. We can't search an // unopen index. // return(false); } if (!pack.index.HasObject(id)) { // Not in this pack? Try another. // continue; } // It should be in the associated pack. Download that // and attach it to the local repository so we can use // all of the contained objects. // try { pack.DownloadPack(monitor); } catch (IOException err) { // If the pack failed to download, index correctly, // or open in the local repository we may still be // able to obtain this object from another pack or // an alternate. // RecordError(id, err); continue; } finally { // If the pack was good its in the local repository // and Repository.hasObject(id) will succeed in the // future, so we do not need this data anymore. If // it failed the index and pack are unusable and we // shouldn't consult them again. // try { if (pack.tmpIdx != null) { FileUtils.Delete(pack.tmpIdx); } } catch (IOException e) { throw new TransportException(e.Message, e); } packItr.Remove(); } if (!AlreadyHave(id)) { // What the hell? This pack claimed to have // the object, but after indexing we didn't // actually find it in the pack. // RecordError(id, new FileNotFoundException(MessageFormat.Format(JGitText.Get().objectNotFoundIn , id.Name, pack.packName))); continue; } // Complete any other objects that we can. // Iterator <ObjectId> pending = SwapFetchQueue(); while (pending.HasNext()) { ObjectId p = pending.Next(); if (pack.index.HasObject(p)) { pending.Remove(); Process(p); } else { workQueue.AddItem(p); } } return(true); } return(false); }
/// <exception cref="System.IO.IOException"></exception> internal virtual void OpenIndex(ProgressMonitor pm) { if (this.index != null) { return; } if (this.tmpIdx == null) { this.tmpIdx = FilePath.CreateTempFile("jgit-walk-", ".idx"); } else { if (this.tmpIdx.IsFile()) { try { this.index = PackIndex.Open(this.tmpIdx); return; } catch (FileNotFoundException) { } } } // Fall through and get the file. WalkRemoteObjectDatabase.FileStream s; s = this.connection.Open("pack/" + this.idxName); pm.BeginTask("Get " + Sharpen.Runtime.Substring(this.idxName, 0, 12) + "..idx", s .length < 0 ? ProgressMonitor.UNKNOWN : (int)(s.length / 1024)); try { FileOutputStream fos = new FileOutputStream(this.tmpIdx); try { byte[] buf = new byte[2048]; int cnt; while (!pm.IsCancelled() && (cnt = [email protected](buf)) >= 0) { fos.Write(buf, 0, cnt); pm.Update(cnt / 1024); } } finally { fos.Close(); } } catch (IOException err) { FileUtils.Delete(this.tmpIdx); throw; } finally { [email protected](); } pm.EndTask(); if (pm.IsCancelled()) { FileUtils.Delete(this.tmpIdx); return; } try { this.index = PackIndex.Open(this.tmpIdx); } catch (IOException e) { FileUtils.Delete(this.tmpIdx); throw; } }
/// <summary> /// Executes the /// <code>Rebase</code> /// command with all the options and parameters /// collected by the setter methods of this class. Each instance of this /// class should only be used for one invocation of the command. Don't call /// this method twice on an instance. /// </summary> /// <returns>an object describing the result of this command</returns> /// <exception cref="NGit.Api.Errors.NoHeadException"></exception> /// <exception cref="NGit.Api.Errors.RefNotFoundException"></exception> /// <exception cref="NGit.Api.Errors.JGitInternalException"></exception> /// <exception cref="NGit.Api.Errors.GitAPIException"></exception> public override RebaseResult Call() { RevCommit newHead = null; bool lastStepWasForward = false; CheckCallable(); CheckParameters(); try { switch (operation) { case RebaseCommand.Operation.ABORT: { try { return(Abort(RebaseResult.ABORTED_RESULT)); } catch (IOException ioe) { throw new JGitInternalException(ioe.Message, ioe); } goto case RebaseCommand.Operation.SKIP; } case RebaseCommand.Operation.SKIP: case RebaseCommand.Operation.CONTINUE: { // fall through string upstreamCommitName = ReadFile(rebaseDir, ONTO); this.upstreamCommit = walk.ParseCommit(repo.Resolve(upstreamCommitName)); break; } case RebaseCommand.Operation.BEGIN: { RebaseResult res = InitFilesAndRewind(); if (res != null) { return(res); } break; } } if (monitor.IsCancelled()) { return(Abort(RebaseResult.ABORTED_RESULT)); } if (operation == RebaseCommand.Operation.CONTINUE) { newHead = ContinueRebase(); } if (operation == RebaseCommand.Operation.SKIP) { newHead = CheckoutCurrentHead(); } ObjectReader or = repo.NewObjectReader(); IList <RebaseCommand.Step> steps = LoadSteps(); foreach (RebaseCommand.Step step in steps) { PopSteps(1); ICollection <ObjectId> ids = or.Resolve(step.commit); if (ids.Count != 1) { throw new JGitInternalException("Could not resolve uniquely the abbreviated object ID" ); } RevCommit commitToPick = walk.ParseCommit(ids.Iterator().Next()); if (monitor.IsCancelled()) { return(new RebaseResult(commitToPick)); } try { monitor.BeginTask(MessageFormat.Format(JGitText.Get().applyingCommit, commitToPick .GetShortMessage()), ProgressMonitor.UNKNOWN); // if the first parent of commitToPick is the current HEAD, // we do a fast-forward instead of cherry-pick to avoid // unnecessary object rewriting newHead = TryFastForward(commitToPick); lastStepWasForward = newHead != null; if (!lastStepWasForward) { // TODO if the content of this commit is already merged // here we should skip this step in order to avoid // confusing pseudo-changed CherryPickResult cherryPickResult = new Git(repo).CherryPick().Include(commitToPick ).Call(); switch (cherryPickResult.GetStatus()) { case CherryPickResult.CherryPickStatus.FAILED: { if (operation == RebaseCommand.Operation.BEGIN) { return(Abort(new RebaseResult(cherryPickResult.GetFailingPaths()))); } else { return(Stop(commitToPick)); } goto case CherryPickResult.CherryPickStatus.CONFLICTING; } case CherryPickResult.CherryPickStatus.CONFLICTING: { return(Stop(commitToPick)); } case CherryPickResult.CherryPickStatus.OK: { newHead = cherryPickResult.GetNewHead(); break; } } } } finally { monitor.EndTask(); } } if (newHead != null) { string headName = ReadFile(rebaseDir, HEAD_NAME); UpdateHead(headName, newHead); FileUtils.Delete(rebaseDir, FileUtils.RECURSIVE); if (lastStepWasForward) { return(RebaseResult.FAST_FORWARD_RESULT); } return(RebaseResult.OK_RESULT); } return(RebaseResult.FAST_FORWARD_RESULT); } catch (IOException ioe) { throw new JGitInternalException(ioe.Message, ioe); } }