Skip to content

Commit

Permalink
Extend RepositoryOptions to accept path to alternate System and Globa…
Browse files Browse the repository at this point in the history
…l configuration files

Fix #157
  • Loading branch information
nulltoken committed May 26, 2012
1 parent 0690be7 commit f24fbe6
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 46 deletions.
7 changes: 0 additions & 7 deletions LibGit2Sharp.Tests/ConfigurationFixture.cs
Expand Up @@ -14,13 +14,6 @@ private static void AssertValueInLocalConfigFile(string repoPath, string regex)
AssertValueInConfigFile(configFilePath, regex);
}

private static void AssertValueInConfigFile(string configFilePath, string regex)
{
var text = File.ReadAllText(configFilePath);
var r = new Regex(regex, RegexOptions.Multiline).Match(text);
Assert.True(r.Success, text);
}

private static string RetrieveGlobalConfigLocation()
{
string[] variables = { "HOME", "USERPROFILE", };
Expand Down
44 changes: 34 additions & 10 deletions LibGit2Sharp.Tests/RepositoryOptionsFixture.cs
@@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Text;
using LibGit2Sharp.Tests.TestHelpers;
using Xunit;

Expand Down Expand Up @@ -101,16 +102,6 @@ public void OpeningABareRepoWithoutProvidingBothWorkDirAndIndexThrows()
Assert.Throws<ArgumentException>(() => repo = new Repository(BareTestRepoPath, new RepositoryOptions { WorkingDirectoryPath = newWorkdir }));
}

[Fact]
public void OpeningARepoWithAnEmptyRepositoryOptionsThrows()
{
var options = new RepositoryOptions();
Repository repo;

Assert.Throws<ArgumentException>(() => repo = new Repository(BareTestRepoPath, options));
Assert.Throws<ArgumentException>(() => repo = new Repository(StandardTestRepoPath, options));
}

[Fact]
public void CanSneakAdditionalCommitsIntoAStandardRepoWithoutAlteringTheWorkdirOrTheIndex()
{
Expand Down Expand Up @@ -150,5 +141,38 @@ private string MeanwhileInAnotherDimensionAnEvilMastermindIsAtWork(string workin
return sneakyRepo.Commit("Tadaaaa!", DummySignature, DummySignature).Sha;
}
}

[Fact]
public void CanProvideDifferentConfigurationFilesToARepository()
{
string globalLocation = Path.Combine(newWorkdir, "my-global-config");
string systemLocation = Path.Combine(newWorkdir, "my-system-config");

const string name = "Adam 'aroben' Roben";
const string email = "adam@github.com";

StringBuilder sb = new StringBuilder()
.AppendLine("[user]")
.AppendFormat("name = {0}{1}", name, Environment.NewLine)
.AppendFormat("email = {0}{1}", email, Environment.NewLine);

File.WriteAllText(globalLocation, sb.ToString());

var options = new RepositoryOptions {
GlobalConfigurationLocation = globalLocation,
SystemConfigurationLocation = systemLocation,
};

using (var repo = new Repository(BareTestRepoPath, options))
{
Assert.True(repo.Config.HasGlobalConfig);
Assert.Equal(name, repo.Config.Get<string>("user", "name", null));
Assert.Equal(email, repo.Config.Get<string>("user", "email", null));

repo.Config.Set("help.link", "https://twitter.com/xpaulbettsx/status/205761932626636800", ConfigurationLevel.System);
}

AssertValueInConfigFile(systemLocation, "xpaulbettsx");
}
}
}
9 changes: 9 additions & 0 deletions LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using Xunit;

namespace LibGit2Sharp.Tests.TestHelpers
{
Expand Down Expand Up @@ -94,5 +96,12 @@ protected void InconclusiveIf(Func<bool> predicate, string message)

throw new SkipException(message);
}

protected static void AssertValueInConfigFile(string configFilePath, string regex)
{
var text = File.ReadAllText(configFilePath);
var r = new Regex(regex, RegexOptions.Multiline).Match(text);
Assert.True(r.Success, text);
}
}
}
69 changes: 46 additions & 23 deletions LibGit2Sharp/Configuration.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using LibGit2Sharp.Core;
using LibGit2Sharp.Core.Handles;

Expand All @@ -20,21 +21,61 @@ public class Configuration : IDisposable
private ConfigurationSafeHandle globalHandle;
private ConfigurationSafeHandle localHandle;

internal Configuration(Repository repository)
internal Configuration(Repository repository, string globalConfigurationFileLocation, string systemConfigurationFileLocation)
{
this.repository = repository;

globalConfigPath = ConvertPath(NativeMethods.git_config_find_global);
systemConfigPath = ConvertPath(NativeMethods.git_config_find_system);
globalConfigPath = globalConfigurationFileLocation ?? ConvertPath(NativeMethods.git_config_find_global);
systemConfigPath = systemConfigurationFileLocation ?? ConvertPath(NativeMethods.git_config_find_system);

Init();
}

private void Init()
{
if (repository != null)
{
//TODO: push back this logic into libgit2.
// As stated by @carlosmn "having a helper function to load the defaults and then allowing you
// to modify it before giving it to git_repository_open_ext() would be a good addition, I think."
// -- Agreed :)

Ensure.Success(NativeMethods.git_config_new(out localHandle));

string repoConfigLocation = Path.Combine(repository.Info.Path, "config");
Ensure.Success(NativeMethods.git_config_add_file_ondisk(localHandle, repoConfigLocation, 3));

if (globalConfigPath != null)
{
Ensure.Success(NativeMethods.git_config_add_file_ondisk(localHandle, globalConfigPath, 2));
}

if (systemConfigPath != null)
{
Ensure.Success(NativeMethods.git_config_add_file_ondisk(localHandle, systemConfigPath, 1));
}

NativeMethods.git_repository_set_config(repository.Handle, localHandle);
}

if (globalConfigPath != null)
{
Ensure.Success(NativeMethods.git_config_open_ondisk(out globalHandle, globalConfigPath));
}

if (systemConfigPath != null)
{
Ensure.Success(NativeMethods.git_config_open_ondisk(out systemHandle, systemConfigPath));
}
}

/// <summary>
/// Access configuration values without a repository. Generally you want to access configuration via an instance of <see cref = "Repository" /> instead.
/// </summary>
public Configuration()
: this(null)
/// <param name="globalConfigurationFileLocation">Path to a Global configuration file. If null, the default path for a global configuration file will be probed.</param>
/// <param name="systemConfigurationFileLocation">Path to a System configuration file. If null, the default path for a system configuration file will be probed.</param>
public Configuration(string globalConfigurationFileLocation = null, string systemConfigurationFileLocation = null)
: this(null, globalConfigurationFileLocation, systemConfigurationFileLocation)
{
}

Expand Down Expand Up @@ -246,24 +287,6 @@ public T Get<T>(string[] keyParts, T defaultValue)
return Get(string.Join(".", keyParts), defaultValue);
}

private void Init()
{
if (repository != null)
{
Ensure.Success(NativeMethods.git_repository_config(out localHandle, repository.Handle));
}

if (globalConfigPath != null)
{
Ensure.Success(NativeMethods.git_config_open_ondisk(out globalHandle, globalConfigPath));
}

if (systemConfigPath != null)
{
Ensure.Success(NativeMethods.git_config_open_ondisk(out systemHandle, systemConfigPath));
}
}

private void Save()
{
Dispose(true);
Expand Down
14 changes: 14 additions & 0 deletions LibGit2Sharp/Core/NativeMethods.cs
Expand Up @@ -181,6 +181,15 @@ public static bool RepositoryStateChecker(RepositorySafeHandle repositoryPtr, Fu
ConfigurationSafeHandle cfg,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string name);

[DllImport(libgit2)]
public static extern int git_config_add_file_ondisk(
ConfigurationSafeHandle cfg,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(FilePathMarshaler))] FilePath path,
int priority);

[DllImport(libgit2)]
public static extern int git_config_new(out ConfigurationSafeHandle cfg);

[DllImport(libgit2)]
public static extern int git_config_open_global(out ConfigurationSafeHandle cfg);

Expand Down Expand Up @@ -547,6 +556,11 @@ public static bool RepositoryStateChecker(RepositorySafeHandle repositoryPtr, Fu
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(FilePathMarshaler))]
public static extern FilePath git_repository_path(RepositorySafeHandle repository);

[DllImport(libgit2)]
public static extern void git_repository_set_config(
RepositorySafeHandle repository,
ConfigurationSafeHandle index);

[DllImport(libgit2)]
public static extern void git_repository_set_index(
RepositorySafeHandle repository,
Expand Down
13 changes: 7 additions & 6 deletions LibGit2Sharp/Repository.cs
Expand Up @@ -51,16 +51,14 @@ public Repository(string path, RepositoryOptions options = null)

Func<Index> indexBuilder = () => new Index(this);

string configurationGlobalFilePath = null;
string configurationSystemFilePath = null;

if (options != null)
{
bool isWorkDirNull = string.IsNullOrEmpty(options.WorkingDirectoryPath);
bool isIndexNull = string.IsNullOrEmpty(options.IndexPath);

if (isWorkDirNull && isIndexNull)
{
throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "At least one member of the {0} instance has to be provided.", typeof(RepositoryOptions).Name));
}

if (isBare && (isWorkDirNull ^ isIndexNull))
{
throw new ArgumentException("When overriding the opening of a bare repository, both RepositoryOptions.WorkingDirectoryPath an RepositoryOptions.IndexPath have to be provided.");
Expand All @@ -77,6 +75,9 @@ public Repository(string path, RepositoryOptions options = null)
{
Ensure.Success(NativeMethods.git_repository_set_workdir(handle, options.WorkingDirectoryPath));
}

configurationGlobalFilePath = options.GlobalConfigurationLocation;
configurationSystemFilePath = options.SystemConfigurationLocation;
}

if (!isBare)
Expand All @@ -89,7 +90,7 @@ public Repository(string path, RepositoryOptions options = null)
branches = new BranchCollection(this);
tags = new TagCollection(this);
info = new Lazy<RepositoryInformation>(() => new RepositoryInformation(this, isBare));
config = new Lazy<Configuration>(() => RegisterForCleanup(new Configuration(this)));
config = new Lazy<Configuration>(() => RegisterForCleanup(new Configuration(this, configurationGlobalFilePath, configurationSystemFilePath)));
remotes = new Lazy<RemoteCollection>(() => new RemoteCollection(this));
odb = new Lazy<ObjectDatabase>(() => new ObjectDatabase(this));
diff = new Diff(this);
Expand Down
18 changes: 18 additions & 0 deletions LibGit2Sharp/RepositoryOptions.cs
Expand Up @@ -25,5 +25,23 @@ public class RepositoryOptions
/// </para>
/// </summary>
public string IndexPath { get; set; }

/// <summary>
/// Overrides the probed location of the Global configuration file of a repository.
/// <para>
/// The path has either to lead to an existing valid configuration file,
/// or to a non existent configuration file which will be eventually created.
/// </para>
/// </summary>
public string GlobalConfigurationLocation { get; set; }

/// <summary>
/// Overrides the probed location of the System configuration file of a repository.
/// <para>
/// The path has to lead to an existing valid configuration file,
/// or to a non existent configuration file which will be eventually created.
/// </para>
/// </summary>
public string SystemConfigurationLocation { get; set; }
}
}

0 comments on commit f24fbe6

Please sign in to comment.