/// <summary>Return the merge base of two commits.</summary> /// <remarks>Return the merge base of two commits.</remarks> /// <param name="aIdx"> /// index of the first commit in /// <see cref="sourceObjects">sourceObjects</see> /// . /// </param> /// <param name="bIdx"> /// index of the second commit in /// <see cref="sourceObjects">sourceObjects</see> /// . /// </param> /// <returns>the merge base of two commits</returns> /// <exception cref="NGit.Errors.IncorrectObjectTypeException">one of the input objects is not a commit. /// </exception> /// <exception cref="System.IO.IOException">objects are missing or multiple merge bases were found. /// </exception> public virtual RevCommit GetBaseCommit(int aIdx, int bIdx) { if (sourceCommits[aIdx] == null) { throw new IncorrectObjectTypeException(sourceObjects[aIdx], Constants.TYPE_COMMIT ); } if (sourceCommits[bIdx] == null) { throw new IncorrectObjectTypeException(sourceObjects[bIdx], Constants.TYPE_COMMIT ); } walk.Reset(); walk.SetRevFilter(RevFilter.MERGE_BASE); walk.MarkStart(sourceCommits[aIdx]); walk.MarkStart(sourceCommits[bIdx]); RevCommit @base = walk.Next(); if (@base == null) { return(null); } RevCommit base2 = walk.Next(); if (base2 != null) { throw new IOException(MessageFormat.Format(JGitText.Get().multipleMergeBasesFor, sourceCommits[aIdx].Name, sourceCommits[bIdx].Name, @base.Name, base2.Name)); } return(@base); }
/// <summary> /// Find commits that are reachable from <code>start</code> until a commit /// that is reachable from <code>end</code> is encountered. /// </summary> /// <remarks> /// Find commits that are reachable from <code>start</code> until a commit /// that is reachable from <code>end</code> is encountered. In other words, /// Find of commits that are in <code>start</code>, but not in /// <code>end</code>. /// <p> /// Note that this method calls /// <see cref="RevWalk.Reset()">RevWalk.Reset()</see> /// at the beginning. /// Also note that the existing rev filter on the walk is left as-is, so be /// sure to set the right rev filter before calling this method. /// </remarks> /// <param name="walk">the rev walk to use</param> /// <param name="start">the commit to start counting from</param> /// <param name="end"> /// the commit where counting should end, or null if counting /// should be done until there are no more commits /// </param> /// <returns>the commits found</returns> /// <exception cref="NGit.Errors.MissingObjectException">NGit.Errors.MissingObjectException /// </exception> /// <exception cref="NGit.Errors.IncorrectObjectTypeException">NGit.Errors.IncorrectObjectTypeException /// </exception> /// <exception cref="System.IO.IOException">System.IO.IOException</exception> public static IList <RevCommit> Find(RevWalk walk, RevCommit start, RevCommit end) { walk.Reset(); walk.MarkStart(start); if (end != null) { walk.MarkUninteresting(end); } IList <RevCommit> commits = new AList <RevCommit>(); foreach (RevCommit c in walk) { commits.AddItem(c); } return(commits); }
/// <summary> /// Compute the tracking status for the <code>branchName</code> in /// <code>repository</code>. /// </summary> /// <remarks> /// Compute the tracking status for the <code>branchName</code> in /// <code>repository</code>. /// </remarks> /// <param name="repository">the git repository to compute the status from</param> /// <param name="branchName">the local branch</param> /// <returns>the tracking status, or null if it is not known</returns> /// <exception cref="System.IO.IOException">System.IO.IOException</exception> public static NGit.BranchTrackingStatus Of(Repository repository, string branchName ) { BranchConfig branchConfig = new BranchConfig(repository.GetConfig(), branchName); string remoteTrackingBranch = branchConfig.GetRemoteTrackingBranch(); if (remoteTrackingBranch == null) { return(null); } Ref tracking = repository.GetRef(remoteTrackingBranch); if (tracking == null) { return(null); } Ref local = repository.GetRef(branchName); if (local == null) { return(null); } RevWalk walk = new RevWalk(repository); RevCommit localCommit = walk.ParseCommit(local.GetObjectId()); RevCommit trackingCommit = walk.ParseCommit(tracking.GetObjectId()); walk.SetRevFilter(RevFilter.MERGE_BASE); walk.MarkStart(localCommit); walk.MarkStart(trackingCommit); RevCommit mergeBase = walk.Next(); walk.Reset(); walk.SetRevFilter(RevFilter.ALL); int aheadCount = RevWalkUtils.Count(walk, localCommit, mergeBase); int behindCount = RevWalkUtils.Count(walk, trackingCommit, mergeBase); return(new NGit.BranchTrackingStatus(remoteTrackingBranch, aheadCount, behindCount )); }
/// <summary> /// Find commits that are reachable from <code>start</code> until a commit /// that is reachable from <code>end</code> is encountered. /// </summary> /// <remarks> /// Find commits that are reachable from <code>start</code> until a commit /// that is reachable from <code>end</code> is encountered. In other words, /// Find of commits that are in <code>start</code>, but not in /// <code>end</code>. /// <p> /// Note that this method calls /// <see cref="RevWalk.Reset()">RevWalk.Reset()</see> /// at the beginning. /// Also note that the existing rev filter on the walk is left as-is, so be /// sure to set the right rev filter before calling this method. /// </remarks> /// <param name="walk">the rev walk to use</param> /// <param name="start">the commit to start counting from</param> /// <param name="end"> /// the commit where counting should end, or null if counting /// should be done until there are no more commits /// </param> /// <returns>the commits found</returns> /// <exception cref="NGit.Errors.MissingObjectException">NGit.Errors.MissingObjectException /// </exception> /// <exception cref="NGit.Errors.IncorrectObjectTypeException">NGit.Errors.IncorrectObjectTypeException /// </exception> /// <exception cref="System.IO.IOException">System.IO.IOException</exception> public static IList<RevCommit> Find(RevWalk walk, RevCommit start, RevCommit end) { walk.Reset(); walk.MarkStart(start); if (end != null) { walk.MarkUninteresting(end); } IList<RevCommit> commits = new AList<RevCommit>(); foreach (RevCommit c in walk) { commits.AddItem(c); } return commits; }
// Utility class /// <summary> /// Count the number of commits that are reachable from <code>start</code> /// until a commit that is reachable from <code>end</code> is encountered. /// </summary> /// <remarks> /// Count the number of commits that are reachable from <code>start</code> /// until a commit that is reachable from <code>end</code> is encountered. In /// other words, count the number of commits that are in <code>start</code>, /// but not in <code>end</code>. /// <p> /// Note that this method calls /// <see cref="RevWalk.Reset()">RevWalk.Reset()</see> /// at the beginning. /// Also note that the existing rev filter on the walk is left as-is, so be /// sure to set the right rev filter before calling this method. /// </remarks> /// <param name="walk">the rev walk to use</param> /// <param name="start">the commit to start counting from</param> /// <param name="end"> /// the commit where counting should end, or null if counting /// should be done until there are no more commits /// </param> /// <returns>the number of commits</returns> /// <exception cref="NGit.Errors.MissingObjectException">NGit.Errors.MissingObjectException /// </exception> /// <exception cref="NGit.Errors.IncorrectObjectTypeException">NGit.Errors.IncorrectObjectTypeException /// </exception> /// <exception cref="System.IO.IOException">System.IO.IOException</exception> public static int Count(RevWalk walk, RevCommit start, RevCommit end) { walk.Reset(); walk.MarkStart(start); if (end != null) { walk.MarkUninteresting(end); } int count = 0; for (RevCommit c = walk.Next(); c != null; c = walk.Next()) { count++; } return count; }
/// <exception cref="System.IO.IOException"></exception> private void SendPack() { bool sideband = options.Contains(OPTION_SIDE_BAND) || options.Contains(OPTION_SIDE_BAND_64K ); ProgressMonitor pm = NullProgressMonitor.INSTANCE; OutputStream packOut = rawOut; SideBandOutputStream msgOut = null; if (sideband) { int bufsz = SideBandOutputStream.SMALL_BUF; if (options.Contains(OPTION_SIDE_BAND_64K)) { bufsz = SideBandOutputStream.MAX_BUF; } packOut = new SideBandOutputStream(SideBandOutputStream.CH_DATA, bufsz, rawOut); if (!options.Contains(OPTION_NO_PROGRESS)) { msgOut = new SideBandOutputStream(SideBandOutputStream.CH_PROGRESS, bufsz, rawOut ); pm = new SideBandProgressMonitor(msgOut); } } PackConfig cfg = packConfig; if (cfg == null) { cfg = new PackConfig(db); } PackWriter pw = new PackWriter(cfg, walk.GetObjectReader()); try { pw.SetUseCachedPacks(true); pw.SetReuseDeltaCommits(true); pw.SetDeltaBaseAsOffset(options.Contains(OPTION_OFS_DELTA)); pw.SetThin(options.Contains(OPTION_THIN_PACK)); pw.SetReuseValidatingObjects(false); if (commonBase.IsEmpty()) { ICollection <ObjectId> tagTargets = new HashSet <ObjectId>(); foreach (Ref @ref in refs.Values) { if (@ref.GetPeeledObjectId() != null) { tagTargets.AddItem(@ref.GetPeeledObjectId()); } else { if (@ref.GetObjectId() == null) { continue; } else { if (@ref.GetName().StartsWith(Constants.R_HEADS)) { tagTargets.AddItem(@ref.GetObjectId()); } } } } pw.SetTagTargets(tagTargets); } RevWalk rw = walk; if (wantAll.IsEmpty()) { pw.PreparePack(pm, wantIds, commonBase); } else { walk.Reset(); ObjectWalk ow = walk.ToObjectWalkWithSameObjects(); pw.PreparePack(pm, ow, wantAll, commonBase); rw = ow; } if (options.Contains(OPTION_INCLUDE_TAG)) { foreach (Ref vref in refs.Values) { Ref @ref = vref; ObjectId objectId = @ref.GetObjectId(); // If the object was already requested, skip it. if (wantAll.IsEmpty()) { if (wantIds.Contains(objectId)) { continue; } } else { RevObject obj = rw.LookupOrNull(objectId); if (obj != null && obj.Has(WANT)) { continue; } } if ([email protected]()) { @ref = db.Peel(@ref); } ObjectId peeledId = @ref.GetPeeledObjectId(); if (peeledId == null) { continue; } objectId = @ref.GetObjectId(); if (pw.WillInclude(peeledId) && !pw.WillInclude(objectId)) { pw.AddObject(rw.ParseAny(objectId)); } } } pw.WritePack(pm, NullProgressMonitor.INSTANCE, packOut); statistics = pw.GetStatistics(); if (msgOut != null) { string msg = pw.GetStatistics().GetMessage() + '\n'; msgOut.Write(Constants.Encode(msg)); msgOut.Flush(); } } finally { pw.Release(); } if (sideband) { pckOut.End(); } if (logger != null && statistics != null) { logger.OnPackStatistics(statistics); } }
/// <exception cref="System.IO.IOException"></exception> private void SendPack() { bool sideband = options.Contains(OPTION_SIDE_BAND) || options.Contains(OPTION_SIDE_BAND_64K ); if (!biDirectionalPipe) { // Ensure the request was fully consumed. Any remaining input must // be a protocol error. If we aren't at EOF the implementation is broken. int eof = rawIn.Read(); if (0 <= eof) { throw new CorruptObjectException(MessageFormat.Format(JGitText.Get().expectedEOFReceived , "\\x" + Sharpen.Extensions.ToHexString(eof))); } } ProgressMonitor pm = NullProgressMonitor.INSTANCE; OutputStream packOut = rawOut; SideBandOutputStream msgOut = null; if (sideband) { int bufsz = SideBandOutputStream.SMALL_BUF; if (options.Contains(OPTION_SIDE_BAND_64K)) { bufsz = SideBandOutputStream.MAX_BUF; } packOut = new SideBandOutputStream(SideBandOutputStream.CH_DATA, bufsz, rawOut); if (!options.Contains(OPTION_NO_PROGRESS)) { msgOut = new SideBandOutputStream(SideBandOutputStream.CH_PROGRESS, bufsz, rawOut ); pm = new SideBandProgressMonitor(msgOut); } } try { if (wantAll.IsEmpty()) { preUploadHook.OnSendPack(this, wantIds, commonBase); } else { preUploadHook.OnSendPack(this, wantAll, commonBase); } } catch (UploadPackMayNotContinueException noPack) { if (sideband && noPack.Message != null) { noPack.SetOutput(); SideBandOutputStream err = new SideBandOutputStream(SideBandOutputStream.CH_ERROR , SideBandOutputStream.SMALL_BUF, rawOut); err.Write(Constants.Encode(noPack.Message)); err.Flush(); } throw; } PackConfig cfg = packConfig; if (cfg == null) { cfg = new PackConfig(db); } PackWriter pw = new PackWriter(cfg, walk.GetObjectReader()); try { pw.SetUseCachedPacks(true); pw.SetReuseDeltaCommits(true); pw.SetDeltaBaseAsOffset(options.Contains(OPTION_OFS_DELTA)); pw.SetThin(options.Contains(OPTION_THIN_PACK)); pw.SetReuseValidatingObjects(false); if (commonBase.IsEmpty()) { ICollection <ObjectId> tagTargets = new HashSet <ObjectId>(); foreach (Ref @ref in refs.Values) { if (@ref.GetPeeledObjectId() != null) { tagTargets.AddItem(@ref.GetPeeledObjectId()); } else { if (@ref.GetObjectId() == null) { continue; } else { if (@ref.GetName().StartsWith(Constants.R_HEADS)) { tagTargets.AddItem(@ref.GetObjectId()); } } } } pw.SetTagTargets(tagTargets); } RevWalk rw = walk; if (wantAll.IsEmpty()) { pw.PreparePack(pm, wantIds, commonBase); } else { walk.Reset(); ObjectWalk ow = walk.ToObjectWalkWithSameObjects(); pw.PreparePack(pm, ow, wantAll, commonBase); rw = ow; } if (options.Contains(OPTION_INCLUDE_TAG)) { foreach (Ref vref in refs.Values) { Ref @ref = vref; ObjectId objectId = @ref.GetObjectId(); // If the object was already requested, skip it. if (wantAll.IsEmpty()) { if (wantIds.Contains(objectId)) { continue; } } else { RevObject obj = rw.LookupOrNull(objectId); if (obj != null && obj.Has(WANT)) { continue; } } if ([email protected]()) { @ref = db.Peel(@ref); } ObjectId peeledId = @ref.GetPeeledObjectId(); if (peeledId == null) { continue; } objectId = @ref.GetObjectId(); if (pw.WillInclude(peeledId) && !pw.WillInclude(objectId)) { pw.AddObject(rw.ParseAny(objectId)); } } } pw.WritePack(pm, NullProgressMonitor.INSTANCE, packOut); statistics = pw.GetStatistics(); if (msgOut != null) { string msg = pw.GetStatistics().GetMessage() + '\n'; msgOut.Write(Constants.Encode(msg)); msgOut.Flush(); } } finally { pw.Release(); } if (sideband) { pckOut.End(); } if (logger != null && statistics != null) { logger.OnPackStatistics(statistics); } }
/// <summary> /// Compute the tracking status for the <code>branchName</code> in /// <code>repository</code>. /// </summary> /// <remarks> /// Compute the tracking status for the <code>branchName</code> in /// <code>repository</code>. /// </remarks> /// <param name="repository">the git repository to compute the status from</param> /// <param name="branchName">the local branch</param> /// <returns>the tracking status, or null if it is not known</returns> /// <exception cref="System.IO.IOException">System.IO.IOException</exception> public static NGit.BranchTrackingStatus Of(Repository repository, string branchName ) { BranchConfig branchConfig = new BranchConfig(repository.GetConfig(), branchName); string trackingBranch = branchConfig.GetTrackingBranch(); if (trackingBranch == null) { return null; } Ref tracking = repository.GetRef(trackingBranch); if (tracking == null) { return null; } Ref local = repository.GetRef(branchName); if (local == null) { return null; } RevWalk walk = new RevWalk(repository); RevCommit localCommit = walk.ParseCommit(local.GetObjectId()); RevCommit trackingCommit = walk.ParseCommit(tracking.GetObjectId()); walk.SetRevFilter(RevFilter.MERGE_BASE); walk.MarkStart(localCommit); walk.MarkStart(trackingCommit); RevCommit mergeBase = walk.Next(); walk.Reset(); walk.SetRevFilter(RevFilter.ALL); int aheadCount = RevWalkUtils.Count(walk, localCommit, mergeBase); int behindCount = RevWalkUtils.Count(walk, trackingCommit, mergeBase); return new NGit.BranchTrackingStatus(trackingBranch, aheadCount, behindCount); }