using System;
using LibGit2Sharp.Core;
namespace LibGit2Sharp
{
///
/// A Repository is the primary interface into a git repository
///
public class Repository : IDisposable
{
private readonly BranchCollection branches;
private readonly CommitCollection commits;
private readonly RepositorySafeHandle handle;
private readonly Index index;
private readonly ReferenceCollection refs;
private readonly TagCollection tags;
///
/// Initializes a new instance of the class.
/// For a standard repository, should point to the ".git" folder. For a bare repository, should directly point to the repository folder.
///
/// The path to the git repository to open.
public Repository(string path)
{
Ensure.ArgumentNotNullOrEmptyString(path, "path");
var res = NativeMethods.git_repository_open(out handle, PosixPathHelper.ToPosix(path));
Ensure.Success(res);
string normalizedPath = NativeMethods.git_repository_path(handle);
string normalizedWorkDir = NativeMethods.git_repository_workdir(handle);
Info = new RepositoryInformation(this, normalizedPath, normalizedWorkDir, normalizedWorkDir == null);
if (!Info.IsBare)
index = new Index(this);
commits = new CommitCollection(this);
refs = new ReferenceCollection(this);
branches = new BranchCollection(this);
tags = new TagCollection(this);
}
internal RepositorySafeHandle Handle
{
get { return handle; }
}
///
/// Shortcut to return the reference to HEAD
///
///
public Reference Head
{
get { return Refs["HEAD"]; }
}
///
/// Gets the index.
///
public Index Index
{
get { return index; }
}
///
/// Lookup and enumerate references in the repository.
///
public ReferenceCollection Refs
{
get { return refs; }
}
///
/// Lookup and enumerate commits in the repository.
/// Iterating this collection directly starts walking from the HEAD.
///
public CommitCollection Commits
{
get { return commits.StartingAt(Head); }
}
///
/// Lookup and enumerate branches in the repository.
///
public BranchCollection Branches
{
get { return branches; }
}
///
/// Lookup and enumerate tags in the repository.
///
public TagCollection Tags
{
get { return tags; }
}
///
/// Provides high level information about this repository.
///
public RepositoryInformation Info { get; set; }
#region IDisposable Members
///
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
///
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
///
protected virtual void Dispose(bool disposing)
{
if (handle != null && !handle.IsInvalid)
{
handle.Dispose();
}
if (index != null)
{
index.Dispose();
}
}
#endregion
///
/// Tells if the specified sha exists in the repository.
///
/// Exceptions:
/// ArgumentException
/// ArgumentNullException
///
/// The sha.
///
public bool HasObject(string sha)
{
Ensure.ArgumentNotNullOrEmptyString(sha, "sha");
var id = new ObjectId(sha);
var odb = NativeMethods.git_repository_database(handle);
var oid = id.Oid;
return NativeMethods.git_odb_exists(odb, ref oid);
}
///
/// Init a repo at the specified .
///
/// The path to the working folder when initializing a standard ".git" repository. Otherwise, when initializing a bare repository, the path to the expected location of this later.
/// true to initialize a bare repository. False otherwise, to initialize a standard ".git" repository.
/// Path the git repository.
public static string Init(string path, bool bare = false)
{
Ensure.ArgumentNotNullOrEmptyString(path, "path");
RepositorySafeHandle repo;
var res = NativeMethods.git_repository_init(out repo, PosixPathHelper.ToPosix(path), bare);
Ensure.Success(res);
string normalizedPath = NativeMethods.git_repository_path(repo);
repo.Dispose();
return PosixPathHelper.ToNative(normalizedPath);
}
///
/// Try to lookup an object by its and . If no matching object is found, null will be returned.
///
/// The id to lookup.
/// The kind of GitObject being looked up
/// The or null if it was not found.
public GitObject Lookup(ObjectId id, GitObjectType type = GitObjectType.Any)
{
Ensure.ArgumentNotNull(id, "id");
var oid = id.Oid;
IntPtr obj;
var res = NativeMethods.git_object_lookup(out obj, handle, ref oid, type);
if (res == (int)GitErrorCode.GIT_ENOTFOUND || res == (int)GitErrorCode.GIT_EINVALIDTYPE)
{
return null;
}
Ensure.Success(res);
return GitObject.CreateFromPtr(obj, id, this);
}
///
/// Try to lookup an object by its sha or a reference canonical name and . If no matching object is found, null will be returned.
///
/// The sha or reference canonical name to lookup.
/// The kind of being looked up
/// The or null if it was not found.
public GitObject Lookup(string shaOrReferenceName, GitObjectType type = GitObjectType.Any)
{
ObjectId id = ObjectId.CreateFromMaybeSha(shaOrReferenceName);
if (id != null)
{
return Lookup(id, type);
}
var reference = Refs[shaOrReferenceName];
if (!IsReferencePeelable(reference))
{
return null;
}
return Lookup(reference.ResolveToDirectReference().TargetIdentifier, type);
}
private static bool IsReferencePeelable(Reference reference)
{
return reference != null && ((reference is DirectReference) ||(reference is SymbolicReference && ((SymbolicReference)reference).Target != null));
}
}
}