using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using LibGit2Sharp.Core;
namespace LibGit2Sharp
{
///
/// Global settings for libgit2 and LibGit2Sharp.
///
public static class GlobalSettings
{
private static readonly Lazy version = new Lazy(Version.Build);
private static readonly Dictionary registeredFilters;
private static LogConfiguration logConfiguration = LogConfiguration.None;
private static string nativeLibraryPath;
private static bool nativeLibraryPathLocked;
static GlobalSettings()
{
if (Platform.OperatingSystem == OperatingSystemType.Windows)
{
string managedPath = new Uri(Assembly.GetExecutingAssembly().EscapedCodeBase).LocalPath;
nativeLibraryPath = Path.Combine(Path.GetDirectoryName(managedPath), "NativeBinaries");
}
registeredFilters = new Dictionary();
}
///
/// Returns information related to the current LibGit2Sharp
/// library.
///
public static Version Version
{
get
{
return version.Value;
}
}
///
/// Registers a new as a custom
/// smart-protocol transport with libgit2. Any Git remote with
/// the scheme registered will delegate to the given transport
/// for all communication with the server. use this transport to communicate
/// with the server This is not commonly
/// used: some callers may want to re-use an existing connection to
/// perform fetch / push operations to a remote.
///
/// Note that this configuration is global to an entire process
/// and does not honor application domains.
///
/// The type of SmartSubtransport to register
/// The scheme (eg "http" or "gopher") to register
public static SmartSubtransportRegistration RegisterSmartSubtransport(string scheme)
where T : SmartSubtransport, new()
{
Ensure.ArgumentNotNull(scheme, "scheme");
var registration = new SmartSubtransportRegistration(scheme);
try
{
Proxy.git_transport_register(registration.Scheme,
registration.FunctionPointer,
registration.RegistrationPointer);
}
catch (Exception)
{
registration.Free();
throw;
}
return registration;
}
///
/// Unregisters a previously registered
/// as a custom smart-protocol transport with libgit2.
///
/// The type of SmartSubtransport to register
/// The previous registration
public static void UnregisterSmartSubtransport(SmartSubtransportRegistration registration)
where T : SmartSubtransport, new()
{
Ensure.ArgumentNotNull(registration, "registration");
Proxy.git_transport_unregister(registration.Scheme);
registration.Free();
}
///
/// Registers a new to receive
/// information logging information from libgit2 and LibGit2Sharp.
///
/// Note that this configuration is global to an entire process
/// and does not honor application domains.
///
public static LogConfiguration LogConfiguration
{
set
{
Ensure.ArgumentNotNull(value, "value");
logConfiguration = value;
if (logConfiguration.Level == LogLevel.None)
{
Proxy.git_trace_set(0, null);
}
else
{
Proxy.git_trace_set(value.Level, value.GitTraceCallback);
Log.Write(LogLevel.Info, "Logging enabled at level {0}", value.Level);
}
}
get
{
return logConfiguration;
}
}
///
/// Sets a hint path for searching for native binaries: when
/// specified, native binaries will first be searched in a
/// subdirectory of the given path corresponding to the architecture
/// (eg, "x86" or "amd64") before falling back to the default
/// path ("NativeBinaries\x86" or "NativeBinaries\amd64" next
/// to the application).
///
/// This must be set before any other calls to the library,
/// and is not available on Unix platforms: see your dynamic
/// library loader's documentation for details.
///
///
public static string NativeLibraryPath
{
get
{
if (Platform.OperatingSystem != OperatingSystemType.Windows)
{
throw new LibGit2SharpException("Querying the native hint path is only supported on Windows platforms");
}
return nativeLibraryPath;
}
set
{
if (Platform.OperatingSystem != OperatingSystemType.Windows)
{
throw new LibGit2SharpException("Setting the native hint path is only supported on Windows platforms");
}
if (nativeLibraryPathLocked)
{
throw new LibGit2SharpException("You cannot set the native library path after it has been loaded");
}
nativeLibraryPath = value;
}
}
internal static string GetAndLockNativeLibraryPath()
{
nativeLibraryPathLocked = true;
return nativeLibraryPath;
}
///
/// Takes a snapshot of the currently registered filters.
///
/// An array of .
public static IEnumerable GetRegisteredFilters()
{
lock (registeredFilters)
{
FilterRegistration[] array = new FilterRegistration[registeredFilters.Count];
registeredFilters.Values.CopyTo(array, 0);
return array;
}
}
///
/// Register a filter globally with a default priority of 200 allowing the custom filter
/// to imitate a core Git filter driver. It will be run last on checkout and first on checkin.
///
public static FilterRegistration RegisterFilter(Filter filter)
{
return RegisterFilter(filter, 200);
}
///
/// Registers a to be invoked when matches .gitattributes 'filter=name'
///
/// The filter to be invoked at run time.
/// The priroty of the filter to invoked.
/// A value of 0 () will be run first on checkout and last on checkin.
/// A value of 200 () will be run last on checkout and first on checkin.
///
/// A object used to manage the lifetime of the registration.
public static FilterRegistration RegisterFilter(Filter filter, int priority)
{
Ensure.ArgumentNotNull(filter, "filter");
if (priority < FilterRegistration.FilterPriorityMin || priority > FilterRegistration.FilterPriorityMax)
{
throw new ArgumentOutOfRangeException("priority",
priority,
String.Format(System.Globalization.CultureInfo.InvariantCulture,
"Filter priorities must be within the inclusive range of [{0}, {1}].",
FilterRegistration.FilterPriorityMin,
FilterRegistration.FilterPriorityMax));
}
FilterRegistration registration = null;
lock (registeredFilters)
{
// if the filter has already been registered
if (registeredFilters.ContainsKey(filter))
{
throw new EntryExistsException("The filter has already been registered.", GitErrorCode.Exists, GitErrorCategory.Filter);
}
// allocate the registration object
registration = new FilterRegistration(filter, priority);
// add the filter and registration object to the global tracking list
registeredFilters.Add(filter, registration);
}
return registration;
}
///
/// Unregisters the associated filter.
///
/// Registration object with an associated filter.
public static void DeregisterFilter(FilterRegistration registration)
{
Ensure.ArgumentNotNull(registration, "registration");
lock (registeredFilters)
{
var filter = registration.Filter;
// do nothing if the filter isn't registered
if (registeredFilters.ContainsKey(filter))
{
// remove the register from the global tracking list
registeredFilters.Remove(filter);
// clean up native allocations
registration.Free();
}
}
}
internal static void DeregisterFilter(Filter filter)
{
System.Diagnostics.Debug.Assert(filter != null);
// do nothing if the filter isn't registered
if (registeredFilters.ContainsKey(filter))
{
var registration = registeredFilters[filter];
// unregister the filter
DeregisterFilter(registration);
}
}
///
/// Get the paths under which libgit2 searches for the configuration file of a given level.
///
/// The level (global/system/XDG) of the config.
/// The paths that are searched
public static IEnumerable GetConfigSearchPaths(ConfigurationLevel level)
{
return Proxy.git_libgit2_opts_get_search_path(level).Split(Path.PathSeparator);
}
///
/// Set the paths under which libgit2 searches for the configuration file of a given level.
///
/// .
///
/// The level (global/system/XDG) of the config.
///
/// The new search paths to set.
/// Pass null to reset to the default.
/// The special string "$PATH" will be substituted with the current search path.
///
public static void SetConfigSearchPaths(ConfigurationLevel level, params string[] paths)
{
var pathString = (paths == null) ? null : string.Join(Path.PathSeparator.ToString(), paths);
Proxy.git_libgit2_opts_set_search_path(level, pathString);
}
}
}