|
1 | 1 | using System;
|
| 2 | +using System.Collections; |
2 | 3 | using System.Collections.Generic;
|
3 | 4 | using System.Globalization;
|
4 | 5 | using System.IO;
|
| 6 | +using System.Linq; |
5 | 7 | using LibGit2Sharp.Core;
|
6 | 8 | using LibGit2Sharp.Handlers;
|
7 | 9 |
|
@@ -318,5 +320,114 @@ internal static string BuildRelativePathFrom(this Repository repo, string path)
|
318 | 320 |
|
319 | 321 | return normalizedPath.Substring(repo.Info.WorkingDirectory.Length);
|
320 | 322 | }
|
| 323 | + |
| 324 | + private static ObjectId DereferenceToCommit(Repository repo, string identifier) |
| 325 | + { |
| 326 | + var options = LookUpOptions.DereferenceResultToCommit; |
| 327 | + |
| 328 | + if (!AllowOrphanReference(repo, identifier)) |
| 329 | + { |
| 330 | + options |= LookUpOptions.ThrowWhenNoGitObjectHasBeenFound; |
| 331 | + } |
| 332 | + |
| 333 | + // TODO: Should we check the type? Git-log allows TagAnnotation oid as parameter. But what about Blobs and Trees? |
| 334 | + GitObject commit = repo.Lookup(identifier, GitObjectType.Any, options); |
| 335 | + |
| 336 | + return commit != null ? commit.Id : null; |
| 337 | + } |
| 338 | + |
| 339 | + private static bool AllowOrphanReference(IRepository repo, string identifier) |
| 340 | + { |
| 341 | + return string.Equals(identifier, "HEAD", StringComparison.Ordinal) |
| 342 | + || string.Equals(identifier, repo.Head.CanonicalName, StringComparison.Ordinal); |
| 343 | + } |
| 344 | + |
| 345 | + /// <summary> |
| 346 | + /// Dereferences the passed identifier to a commit. If the identifier is enumerable, all items are dereferenced. |
| 347 | + /// </summary> |
| 348 | + /// <param name="repo">Repository to search</param> |
| 349 | + /// <param name="identifier">Committish to dereference</param> |
| 350 | + /// <param name="throwIfNotFound">If true, allow thrown exceptions to propagate. If false, exceptions will be swallowed and null returned.</param> |
| 351 | + /// <returns>A series of commit <see cref="ObjectId"/>s which identify commit objects.</returns> |
| 352 | + internal static IEnumerable<ObjectId> Committishes(this Repository repo, object identifier, bool throwIfNotFound = false) |
| 353 | + { |
| 354 | + ObjectId singleReturnValue = null; |
| 355 | + |
| 356 | + if (identifier is string) |
| 357 | + { |
| 358 | + singleReturnValue = DereferenceToCommit(repo, identifier as string); |
| 359 | + } |
| 360 | + |
| 361 | + if (identifier is ObjectId) |
| 362 | + { |
| 363 | + singleReturnValue = DereferenceToCommit(repo, ((ObjectId) identifier).Sha); |
| 364 | + } |
| 365 | + |
| 366 | + if (identifier is Commit) |
| 367 | + { |
| 368 | + singleReturnValue = ((Commit) identifier).Id; |
| 369 | + } |
| 370 | + |
| 371 | + if (identifier is TagAnnotation) |
| 372 | + { |
| 373 | + singleReturnValue = DereferenceToCommit(repo, ((TagAnnotation) identifier).Target.Id.Sha); |
| 374 | + } |
| 375 | + |
| 376 | + if (identifier is Tag) |
| 377 | + { |
| 378 | + singleReturnValue = DereferenceToCommit(repo, ((Tag) identifier).Target.Id.Sha); |
| 379 | + } |
| 380 | + |
| 381 | + if (identifier is Branch) |
| 382 | + { |
| 383 | + var branch = (Branch) identifier; |
| 384 | + if (branch.Tip != null || !branch.IsCurrentRepositoryHead) |
| 385 | + { |
| 386 | + Ensure.GitObjectIsNotNull(branch.Tip, branch.CanonicalName); |
| 387 | + singleReturnValue = branch.Tip.Id; |
| 388 | + } |
| 389 | + } |
| 390 | + |
| 391 | + if (identifier is Reference) |
| 392 | + { |
| 393 | + singleReturnValue = DereferenceToCommit(repo, ((Reference) identifier).CanonicalName); |
| 394 | + } |
| 395 | + |
| 396 | + if (singleReturnValue != null) |
| 397 | + { |
| 398 | + yield return singleReturnValue; |
| 399 | + yield break;
F438
span> |
| 400 | + } |
| 401 | + |
| 402 | + if (identifier is IEnumerable) |
| 403 | + { |
| 404 | + foreach (object entry in (IEnumerable)identifier) |
| 405 | + { |
| 406 | + foreach (ObjectId oid in Committishes(repo, entry)) |
| 407 | + { |
| 408 | + yield return oid; |
| 409 | + } |
| 410 | + } |
| 411 | + |
| 412 | + yield break; |
| 413 | + } |
| 414 | + |
| 415 | + if (throwIfNotFound) |
| 416 | + { |
| 417 | + throw new LibGit2SharpException(string.Format(CultureInfo.InvariantCulture, "Unexpected kind of identifier '{0}'.", identifier)); |
| 418 | + } |
| 419 | + yield return null; |
| 420 | + } |
| 421 | + |
| 422 | + /// <summary> |
| 423 | + /// Dereference the identifier to a commit. If the identifier is enumerable, dereference the first element. |
| 424 | + /// </summary> |
| 425 | + /// <param name="repo">The <see cref="Repository"/> to search</param> |
| 426 | + /// <param name="identifier">Committish to dereference</param> |
| 427 | + /// <returns>An <see cref="ObjectId"/> for a commit object.</returns> |
| 428 | + internal static ObjectId Committish(this Repository repo, object identifier) |
| 429 | + { |
| 430 | + return repo.Committishes(identifier, true).First(); |
| 431 | + } |
321 | 432 | }
|
322 | 433 | }
|
0 commit comments