Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions docs_new/mdsource/script_variables_repository.generated.source.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ This module contains the following methods, variables and/or constants:

- [`repository.branch`](#branch)
- [`repository.branches`](#branches)
- [`repository.is_bare`](#is_bare)
- [`repository.linux_path`](#linux_path)
- [`repository.local_branches`](#local_branches)
- [`repository.location`](#location)
Expand Down Expand Up @@ -34,6 +35,26 @@ Gets the current branch of the repository

The name of the current branch.

## is_bare

`repository.is_bare`

Gets the information if the repository is a bare repository.

### Returns

If the repository is cloned as bare repository.

### Example

#### Usage


```
repository.is_bare
```


## linux_path

`repository.linux_path`
Expand Down
21 changes: 21 additions & 0 deletions docs_new/script_variables_repository.generated.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ This module contains the following methods, variables and/or constants:

- [`repository.branch`](#branch)
- [`repository.branches`](#branches)
- [`repository.is_bare`](#is_bare)
- [`repository.linux_path`](#linux_path)
- [`repository.local_branches`](#local_branches)
- [`repository.location`](#location)
Expand Down Expand Up @@ -34,6 +35,26 @@ Gets the current branch of the repository

The name of the current branch.

## is_bare

`repository.is_bare`

Gets the information if the repository is a bare repository.

### Returns

If the repository is cloned as bare repository.

### Example

#### Usage


```
repository.is_bare
```


## linux_path

`repository.linux_path`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@ public RepositoryFunctions(IRepository repository)
[ActionMenuContextMember("name")]
public string Name => _repository.Name;

/// <summary>
/// Gets the information if the repository is a bare repository.
/// </summary>
/// <returns>If the repository is cloned as bare repository.</returns>
/// <example>
/// <usage/>
/// <code>
/// repository.is_bare
/// </code>
/// </example>
[ActionMenuContextMember("is_bare")]
public bool IsBare => _repository.IsBare;


/// <summary>
/// Gets the path of the repository. The path is windows or linux based (depending on the running OS) and does NOT end with a (back)slash.
/// </summary>
Expand Down
1 change: 1 addition & 0 deletions src/RepoM.ActionMenu.Core/RepoMCodeGen.generated.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ protected sealed override void RegisterFunctions()
{
RegisterConstant("branch", CurrentBranch);
RegisterConstant("branches", Branches);
RegisterConstant("is_bare", IsBare);
RegisterConstant("linux_path", LinuxPath);
RegisterConstant("local_branches", LocalBranches);
RegisterConstant("location", Location);
Expand Down
25 changes: 17 additions & 8 deletions src/RepoM.Api/Git/DefaultRepositoryMonitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -246,17 +246,22 @@ public bool IsPinned(IRepository repository)

private void CreateRepositoryObserver(IRepository repo, string path)
{
if (!_repositoryObservers.ContainsKey(path))
if (_repositoryObservers.TryGetValue(path, out IRepositoryObserver? observer))
{
IRepositoryObserver observer = _repositoryObserverFactory.Create();
observer.Setup(repo, DelayGitStatusAfterFileOperationMilliseconds);
_repositoryObservers.Add(path, observer);
return;
}

observer = _repositoryObserverFactory.Create();

observer.OnChange += OnRepositoryObserverChange;
if (!_repositoryObservers.TryAdd(path, observer))
{
observer.Dispose();
return;
}

_repositoryObservers[path].Start();
_logger.LogDebug("{Method} - repo {Repo}, path: {Path} (total length: {RepositoryObserversLength})", nameof(CreateRepositoryObserver), repo.Name, path, _repositoryObservers.Count);
observer.Setup(repo, DelayGitStatusAfterFileOperationMilliseconds);
observer.OnChange += OnRepositoryObserverChange;
observer.Start();
}

private void OnRepositoryChangeDetected(IRepository repo)
Expand Down Expand Up @@ -303,8 +308,12 @@ private void DestroyRepositoryObserver(string path)
return;
}

if (!_repositoryObservers.Remove(path))
{
return;
}

observer.Stop();
_repositoryObservers.Remove(path);
}

private void OnRepositoryDeletionDetected(string repoPath)
Expand Down
16 changes: 9 additions & 7 deletions src/RepoM.Api/Git/DefaultRepositoryObserver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,16 @@ public void Stop()

public void Dispose()
{
if (_watcher != null)
IFileSystemWatcher? watcher = _watcher;
_watcher = null;

if (watcher != null)
{
_watcher.Created -= FileSystemUpdated;
_watcher.Changed -= FileSystemUpdated;
_watcher.Deleted -= FileSystemUpdated;
_watcher.Renamed -= FileSystemUpdated;
_watcher.Dispose();
_watcher = null;
watcher.Created -= FileSystemUpdated;
watcher.Changed -= FileSystemUpdated;
watcher.Deleted -= FileSystemUpdated;
watcher.Renamed -= FileSystemUpdated;
watcher.Dispose();
}

LibGit2Sharp.Repository? gr = _gitRepo;
Expand Down
11 changes: 9 additions & 2 deletions src/RepoM.Api/Git/DefaultRepositoryReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,16 @@ public DefaultRepositoryReader(IRepositoryTagsFactory resolver, ILogger logger)
try
{
using var repo = new LibGit2Sharp.Repository(repoPath);
RepositoryStatus status = repo.RetrieveStatus();

var workingDirectory = new DirectoryInfo(repo.Info.WorkingDirectory);
RepositoryStatus? status = null;
var workingDirectory = new DirectoryInfo(repoPath);

if (!repo.Info.IsBare)
{
status = repo.RetrieveStatus();
workingDirectory = new DirectoryInfo(repo.Info.WorkingDirectory);
}

if (string.IsNullOrWhiteSpace(workingDirectory.Parent?.FullName))
{
_logger.LogError("WorkingDirectory.Parent.Fullname was null or empty for repository found in '{Path}'. Return null", repoPath);
Expand All @@ -99,6 +105,7 @@ public DefaultRepositoryReader(IRepositoryTagsFactory resolver, ILogger logger)

var repository = new Repository(workingDirectory.FullName)
{
IsBare = repo.Info.IsBare,
Name = workingDirectory.Name,
Location = workingDirectory.Parent.FullName,
Branches = repo.Branches.Select(b => b.FriendlyName).ToArray(),
Expand Down
3 changes: 3 additions & 0 deletions src/RepoM.Api/Git/Repository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class Repository : IRepository

public Repository(string path)
{
IsBare = false;
Name = string.Empty;
Branches = Array.Empty<string>();
LocalBranches = Array.Empty<string>();
Expand Down Expand Up @@ -44,6 +45,8 @@ public override int GetHashCode()
return Path.GetHashCode();
}

public bool IsBare { get; init; }

public string Name { get; set; }

public string Path { get; }
Expand Down
2 changes: 2 additions & 0 deletions src/RepoM.Core.Plugin/Repository/IRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ public interface IRepository
{
string Name { get; }

bool IsBare { get; }

string Path { get; }

string WindowsPath { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public EverythingGitRepositoryFinder(IPathSkipper pathSkipper)

public List<string> Find(string root, Action<string>? onFoundAction)
{
const string SEARCH = "file: .git\\HEAD";
const string SEARCH = "file:\"HEAD\" endwith:\"HEAD\" startwith:\"HEAD\"";

var result = Everything64Api.Search($"\"{root}\" {SEARCH}")
.Where(item => !string.IsNullOrWhiteSpace(item))
Expand Down
2 changes: 2 additions & 0 deletions tests/RepoM.ActionMenu.Core.Tests/DummyRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public class DummyRepository : IRepository

public string Name => "dummy name";

public bool IsBare => false;

public string Path => WindowsPath;

public string WindowsPath=> @"C:\Projects\Github\RepoM";
Expand Down
60 changes: 60 additions & 0 deletions tests/RepoM.Api.Tests/Git/DefaultRepositoryReaderTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
namespace RepoM.Api.Tests.Git;

using System;
using System.IO;
using System.Threading.Tasks;
using FakeItEasy;
using FluentAssertions;
using Microsoft.Extensions.Logging;
using RepoM.Api.Git;
using RepoM.Api.IO.ModuleBasedRepositoryActionProvider;
using Xunit;

public class DefaultRepositoryReaderTests
{
private readonly IRepositoryTagsFactory _resolver = A.Fake<IRepositoryTagsFactory>();
private readonly ILogger _logger = A.Dummy<ILogger>();

[Fact]
public void Ctor_ShouldThrow_WhenArgumentNull()
{
// arrange

// act
Func<DefaultRepositoryReader> act1 = () => new DefaultRepositoryReader(_resolver, null!);
Func<DefaultRepositoryReader> act2 = () => new DefaultRepositoryReader(null!, _logger);

// assert
act1.Should().Throw<ArgumentNullException>();
act2.Should().Throw<ArgumentNullException>();
}

[Theory]
[InlineData(null)]
[InlineData("")]
public async Task ReadRepositoryAsync_ShouldReturnNull_WhenPathIsNullOrEmpty(string? path)
{
// arrange
var sut = new DefaultRepositoryReader(_resolver, _logger);

// act
Repository? result = await sut.ReadRepositoryAsync(path!);

// assert
result.Should().BeNull();
}

[Fact]
public async Task ReadRepositoryAsync_ShouldReturnNull_WhenPathDoesNotExist()
{
// arrange
var path = Path.Combine("C:", Guid.NewGuid().ToString(), Guid.NewGuid().ToString());
var sut = new DefaultRepositoryReader(_resolver, _logger);

// act
Repository? result = await sut.ReadRepositoryAsync(path);

// assert
result.Should().BeNull(because:$"Path '{path}' is generated and should not exists.");
}
}