8000 Fold ReferenceCollectionExtensions.cs into ReferenceCollection.cs · lofcz/libgit2sharp@b427862 · GitHub
[go: up one dir, main page]

Skip to content

Commit b427862

Browse files
committed
Fold ReferenceCollectionExtensions.cs into ReferenceCollection.cs
1 parent 697831a commit b427862

File tree

3 files changed

+340
-373
lines changed

3 files changed

+340
-373
lines changed

LibGit2Sharp/LibGit2Sharp.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,6 @@
245245
<Compile Include="NonFastForwardException.cs" />
246246
<Compile Include="PushResult.cs" />
247247
<Compile Include="PushStatusError.cs" />
248-
<Compile Include="ReferenceCollectionExtensions.cs" />
249248
<Compile Include="Core\GitRemoteCallbacks.cs" />
250249
<Compile Include="RemoteCallbacks.cs" />
251250
<Compile Include="RemoteCompletionType.cs" />

LibGit2Sharp/ReferenceCollection.cs

Lines changed: 340 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,106 @@ IEnumerator IEnumerable.GetEnumerator()
6666

6767
#endregion
6868

69+
/// <summary>
70+
/// Creates a direct or symbolic reference with the specified name and target
71+
/// </summary>
72+
/// <param name="name">The name of the reference to create.</param>
73+
/// <param name="canonicalRefNameOrObjectish">The target which can be either the canonical name of a reference or a revparse spec.</param>
74+
/// <param name="logMessage">The optional message to log in the <see cref="ReflogCollection"/> when adding the <see cref="Reference"/></param>
75+
/// <returns>A new <see cref="Reference"/>.</returns>
76+
public virtual Reference Add(string name, string canonicalRefNameOrObjectish,
77+
string logMessage)
78+
{
79+
return Add(name, canonicalRefNameOrObjectish, logMessage, false);
80+
}
81+
82+
private enum RefState
83+
{
84+
Exists,
85+
DoesNotExistButLooksValid,
86+
DoesNotLookValid,
87+
}
88+
89+
private static RefState TryResolveReference(out Reference reference, ReferenceCollection refsColl, string canonicalName)
90+
{
91+
if (!Reference.IsValidName(canonicalName))
92+
{
93+
reference = null;
94+
return RefState.DoesNotLookValid;
95+
}
96+
97+
reference = refsColl[canonicalName];
98+
99+
return reference != null ? RefState.Exists : RefState.DoesNotExistButLooksValid;
100+
}
101+
102+
/// <summary>
103+
/// Creates a direct or symbolic reference with the specified name and target
104+
/// </summary>
105+
/// <param name="name">The name of the reference to create.</param>
106+
/// <param name="canonicalRefNameOrObjectish">The target which can be either the canonical name of a reference or a revparse spec.</param>
107+
/// <param name="logMessage">The optional message to log in the <see cref="ReflogCollection"/> when adding the <see cref="Reference"/></param>
108+
/// <param name="allowOverwrite">True to allow silent overwriting a potentially existing reference, false otherwise.</param>
109+
/// <returns>A new <see cref="Reference"/>.</returns>
110+
public virtual Reference Add(string name, string canonicalRefNameOrObjectish, string logMessage, bool allowOverwrite)
111+
{
112+
Ensure.ArgumentNotNullOrEmptyString(name, "name");
113+
Ensure.ArgumentNotNullOrEmptyString(canonicalRefNameOrObjectish, "canonicalRefNameOrObjectish");
114+
115+
Reference reference;
116+
RefState refState = TryResolveReference(out reference, this, canonicalRefNameOrObjectish);
117+
118+
var gitObject = repo.Lookup(canonicalRefNameOrObjectish, GitObjectType.Any, LookUpOptions.None);
119+
120+
if (refState == RefState.Exists)
121+
{
122+
return Add(name, reference, logMessage, allowOverwrite);
123+
}
124+
125+
if (refState == RefState.DoesNotExistButLooksValid && gitObject == null)
126+
{
127+
using (ReferenceSafeHandle handle = Proxy.git_reference_symbolic_create(repo.Handle, name, canonicalRefNameOrObjectish, allowOverwrite,
128+
logMessage))
129+
{
130+
return Reference.BuildFromPtr<Reference>(handle, repo);
131+
}
132+
}
133+
134+
Ensure.GitObjectIsNotNull(gitObject, canonicalRefNameOrObjectish);
135+
136+
if (logMessage == null)
137+
{
138+
logMessage = string.Format(CultureInfo.InvariantCulture, "{0}: Created from {1}",
139+
name.LooksLikeLocalBranch() ? "branch" : "reference", canonicalRefNameOrObjectish);
140+
}
141+
142+
EnsureHasLog(name);
143+
return Add(name, gitObject.Id, logMessage, allowOverwrite);
144+
}
145+
146+
147+
/// <summary>
148+
/// Creates a direct or symbolic reference with the specified name and target
149+
/// </summary>
150+
/// <param name="name">The name of the reference to create.</param>
151+
/// <param name="canonicalRefNameOrObjectish">The target which can be either the canonical name of a reference or a revparse spec.</param>
152+
/// <returns>A new <see cref="Reference"/>.</returns>
153+
public virtual Reference Add(string name, string canonicalRefNameOrObjectish)
154+
{
155+
return Add(name, canonicalRefNameOrObjectish, null, false);
156+
}
157+
158+
/// <summary>
159+
/// Creates a direct or symbolic reference with the specified name and target
160+
/// </summary>
161+
/// <param name="name">The name of the reference to create.</param>
162+
/// <param name="canonicalRefNameOrObjectish">The target which can be either the canonical name of a reference or a revparse spec.</param>
163+
/// <param name="allowOverwrite">True to allow silent overwriting a potentially existing reference, false otherwise.</param>
164+
/// <returns>A new <see cref="Reference"/>.</returns>
165+
public virtual Reference Add(string name, string canonicalRefNameOrObjectish, bool allowOverwrite)
166+
{
167+
return Add(name, canonicalRefNameOrObjectish, null, allowOverwrite);
168+
}
69169
/// <summary>
70170
/// Creates a direct reference with the specified name and target
71171
/// </summary>
@@ -175,6 +275,24 @@ public virtual SymbolicReference Add(string name, Reference targetRef, bool allo
175275
return Add(name, targetRef, null, allowOverwrite);
176276
}
177277

278+
/// <summary>
279+
/// Remove a reference with the specified name
280+
/// </summary>
281+
/// <param name="name">The canonical name of the reference to delete.</param>
282+
public virtual void Remove(string name)
283+
{
284+
Ensure.ArgumentNotNullOrEmptyString(name, "name");
285+
286+
Reference reference = this[name];
287+
288+
if (reference == null)
289+
{
290+
return;
291+
}
292+
293+
Remove(reference);
294+
}
295+
178296
/// <summary>
179297
/// Remove a reference from the repository
180298
/// </summary>
@@ -224,6 +342,68 @@ public virtual Reference Rename(Reference reference, string newName, string logM
224342
}
225343
}
226344

345+
/// <summary>
346+
/// Rename an existing reference with a new name
347+
/// </summary>
348+
/// <param name="currentName">The canonical name of the reference to rename.</param>
349+
/// <param name="newName">The new canonical name.</param>
350+
/// <returns>A new <see cref="Reference"/>.</returns>
351+
public virtual Reference Rename(string currentName, string newName)
352+
{
353+
return Rename(currentName, newName, null, false);
354+
}
355+
356+
/// <summary>
357+
/// Rename an existing reference with a new name
358+
/// </summary>
359+
/// <param name="currentName">The canonical name of the reference to rename.</param>
360+
/// <param name="newName">The new canonical name.</param>
361+
/// <param name="allowOverwrite">True to allow silent overwriting a potentially existing reference, false otherwise.</param>
362+
/// <returns>A new <see cref="Reference"/>.</returns>
363+
public virtual Reference Rename(string currentName, string newName,
364+
bool allowOverwrite)
365+
{
366+
return Rename(currentName, newName, null, allowOverwrite);
367+
}
368+
369+
/// <summary>
370+
/// Rename an existing reference with a new name
371+
/// </summary>
372+
/// <param name="currentName">The canonical name of the reference to rename.</param>
373+
/// <param name="newName">The new canonical name.</param>
374+
/// <param name="logMessage">The optional message to log in the <see cref="ReflogCollection"/></param>
375+
/// <returns>A new <see cref="Reference"/>.</returns>
376+
public virtual Reference Rename(string currentName, string newName,
377+
string logMessage)
378+
{
379+
return Rename(currentName, newName, logMessage, false);
380+
}
381+
382+
/// <summary>
383+
/// Rename an existing reference with a new name
384+
/// </summary>
385+
/// <param name="currentName">The canonical name of the reference to rename.</param>
386+
/// <param name="newName">The new canonical name.</param>
387+
/// <param name="logMessage">The optional message to log in the <see cref="ReflogCollection"/></param>
388+
/// <param name="allowOverwrite">True to allow silent overwriting a potentially existing reference, false otherwise.</param>
389+
/// <returns>A new <see cref="Reference"/>.</returns>
390+
public virtual Reference Rename(string currentName, string newName,
391+
string logMessage, bool allowOverwrite)
392+
{
393+
Ensure.ArgumentNotNullOrEmptyString(currentName, "currentName");
394+
395+
Reference reference = this[currentName];
396+
397+
if (reference == null)
398+
{
399+
throw new LibGit2SharpException(
400+
string.Format(CultureInfo.InvariantCulture,
401+
"Reference '{0}' doesn't exist. One cannot move a non existing reference.", currentName));
402+
}
403+
404+
return Rename(reference, newName, logMessage, allowOverwrite);
405+
}
406+
227407
/// <summary>
228408
/// Rename an existing reference with a new name
229409
/// </summary>
@@ -286,6 +466,93 @@ private Reference UpdateDirectReferenceTarget(Reference directRef, ObjectId targ
286466
}
287467
}
288468

469+
/// <summary>
470+
/// Updates the target of a direct reference.
471+
/// </summary>
472+
/// <param name="directRef">The direct reference which target should be updated.</param>
473+
/// <param name="objectish">The revparse spec of the target.</param>
474+
/// <param name="logMessage">The optional message to log in the <see cref="ReflogCollection"/></param>
475+
/// <returns>A new <see cref="Reference"/>.</returns>
476+
public virtual Reference UpdateTarget(Reference directRef, string objectish, string logMessage)
477+
{
478+
Ensure.ArgumentNotNull(directRef, "directRef");
479+
Ensure.ArgumentNotNull(objectish, "objectish");
480+
481+
GitObject target = repo.Lookup(objectish);
482+
483+
Ensure.GitObjectIsNotNull(target, objectish);
484+
485+
return UpdateTarget(directRef, target.Id, logMessage);
486+
}
487+
488+
/// <summary>
489+
/// Updates the target of a direct reference
490+
/// </summary>
491+
/// <param name="directRef">The direct reference which target should be updated.</param>
492+
/// <param name="objectish">The revparse spec of the target.</param>
493+
/// <returns>A new <see cref="Reference"/>.</returns>
494+
public virtual Reference UpdateTarget(Reference directRef, string objectish)
495+
{
496+
return UpdateTarget(directRef, objectish, null);
497< 10000 code class="diff-text syntax-highlighted-line addition">+
}
498+
499+
/// <summary>
500+
/// Updates the target of a reference
501+
/// </summary>
502+
/// <param name="name">The canonical name of the reference.</param>
503+
/// <param name="canonicalRefNameOrObjectish">The target which can be either the canonical name of a reference or a revparse spec.</param>
504+
/// <param name="logMessage">The optional message to log in the <see cref="ReflogCollection"/> of the <paramref name="name"/> reference.</param>
505+
/// <returns>A new <see cref="Reference"/>.</returns>
506+
public virtual Reference UpdateTarget(string name, string canonicalRefNameOrObjectish, string logMessage)
507+
{
508+
Ensure.ArgumentNotNullOrEmptyString(name, "name");
509+
Ensure.ArgumentNotNullOrEmptyString(canonicalRefNameOrObjectish, "canonicalRefNameOrObjectish");
510+
511+
if (name == "HEAD")
512+
{
513+
return UpdateHeadTarget(canonicalRefNameOrObjectish, logMessage);
514+
}
515+
516+
Reference reference = this[name];
517+
518+
var directReference = reference as DirectReference;
519+
if (directReference != null)
520+
{
521+
return UpdateTarget(directReference, canonicalRefNameOrObjectish, logMessage);
522+
}
523+
524+
var symbolicReference = reference as SymbolicReference;
525+
if (symbolicReference != null)
526+
{
527+
Reference targetRef;
528+
529+
RefState refState = TryResolveReference(out targetRef, this, canonicalRefNameOrObjectish);
530+
531+
if (refState == RefState.DoesNotLookValid)
532+
{
533+
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");
534+
}
535+
536+
return UpdateTarget(symbolicReference, targetRef, logMessage);
537+
}
538+
539+
throw new LibGit2SharpException(CultureInfo.InvariantCulture,
540+
"Reference '{0}' has an unexpected type ('{1}').",
541+
name,
542+
reference.GetType());
543+
}
544+
545+
/// <summary>
546+
/// Updates the target of a reference
547+
/// </summary>
548+
/// <param name="name">The canonical name of the reference.</param>
549+
/// <param name="canonicalRefNameOrObjectish">The target which can be either the canonical name of a reference or a revparse spec.</param>
550+
/// <returns>A new <see cref="Reference"/>.</returns>
551+
public virtual Reference UpdateTarget(string name, string canonicalRefNameOrObjectish)
552+
{
553+
return UpdateTarget(name, canonicalRefNameOrObjectish, null);
554+
}
555+
289556
/// <summary>
290557
/// Updates the target of a direct reference
291558
/// </summary>
@@ -427,6 +694,79 @@ public virtual Reference Head
427694
get { return this["HEAD"]; }
428695
}
429696

697+
698+
/// <summary>
699+
/// Find the <see cref="Reference"/>s among <paramref name="refSubset"/>
700+
/// that can reach at least one <see cref="Commit"/> in the specified <paramref name="targets"/>.
701+
/// </summary>
702+
/// <param name="refSubset">The set of <see cref="Reference"/>s to examine.</param>
703+
/// <param name="targets">The set of <see cref="Commit"/>s that are interesting.</param>
704+
/// <returns>A subset of <paramref name="refSubset"/> that can reach at least one <see cref="Commit"/> within <paramref name="targets"/>.</returns>
705+
public virtual IEnumerable<Reference> ReachableFrom(
706+
IEnumerable<Reference> refSubset,
707+
IEnumerable<Commit> targets)
708+
{
709+
Ensure.ArgumentNotNull(refSubset, "refSubset");
710+
Ensure.ArgumentNotNull(targets, "targets");
711+
712+
var refs = new List<Reference>(refSubset);
713+
if (refs.Count == 0)
714+
{
715+
return Enumerable.Empty<Reference>();
716+
}
717+
718+
List<ObjectId> targetsSet = targets.Select(c => c.Id).Distinct().ToList();
719+
if (targetsSet.Count == 0)
720+
{
721+
return Enumerable.Empty<Reference>();
722+
}
723+
724+
var result = new List<Reference>();
725+
726+
foreach (var reference in refs)
727+
{
728+
var peeledTargetCommit = reference
729+
.ResolveToDirectReference()
730+
.Target.DereferenceToCommit(false);
731+
732+
if (peeledTargetCommit == null)
733+
{
734+
continue;
735+
}
736+
737+
var commitId = peeledTargetCommit.Id;
738+
739+
foreach (var potentialAncestorId in targetsSet)
740+
{
741+
if (potentialAncestorId == commitId)
742+
{
743+
result.Add(reference);
744+
break;
745+
}
746+
747+
if (Proxy.git_graph_descendant_of(repo.Handle, commitId, potentialAncestorId))
748+
{
749+
result.Add(reference);
750+
break;
751+
}
752+
}
753+
}
754+
755+
return result;
756+
}
757+
758+
/// <summary>
759+
/// Find the <see cref="Reference"/>s
760+
/// that can reach at least one <see cref="Commit"/> in the specified <paramref name="targets"/>.
761+
/// </summary>
762+
/// <param name="targets">The set of <see cref="Commit"/>s that are interesting.</param>
763+
/// <returns>The list of <see cref="Reference"/> that can reach at least one <see cref="Commit"/> within <paramref name="targets"/>.</returns>
764+
public virtual IEnumerable<Reference> ReachableFrom(
765+
IEnumerable<Commit> targets)
766+
{
767+
return ReachableFrom(this, targets);
768+
}
769+
430770
private string DebuggerDisplay
431771
{
432772
get

0 commit comments

Comments
 (0)
0