Skip to content

Code Quality: Moved implementation of Git operations into abstraction#18068

Open
Lamparter wants to merge 4 commits intofiles-community:mainfrom
Lamparter:libgit2/libgit2-impl
Open

Code Quality: Moved implementation of Git operations into abstraction#18068
Lamparter wants to merge 4 commits intofiles-community:mainfrom
Lamparter:libgit2/libgit2-impl

Conversation

@Lamparter
Copy link
Contributor

@Lamparter Lamparter commented Jan 17, 2026

Resolved / Related Issues

Steps used to test these changes

Not yet fully tested on my side, but no changes to the implementation have been made.


This PR continues the (previously removed parts of) #18040 by moving the implementation for GitHelpers via the LibGit2 library into its own separate file (and therefore making use of the IVersionControl interface introduced in the previous PR)

Copilot AI review requested due to automatic review settings January 17, 2026 08:34
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces an abstraction layer for Git operations to support future implementation of alternative Git backends (like git.exe), as part of the requirements outlined in issue #16738.

Changes:

  • Created IVersionControl interface defining the contract for version control operations
  • Extracted LibGit2Sharp implementation from GitHelpers static class into a new LibGit2 class implementing IVersionControl
  • Refactored GitHelpers to act as a static facade that delegates all operations to a singleton LibGit2 instance

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

File Description
src/Files.App/Utils/Git/IVersionControl.cs New interface defining the contract for version control operations with comprehensive documentation
src/Files.App/Utils/Git/LibGit2.cs New file containing the LibGit2Sharp implementation moved from GitHelpers, now implementing IVersionControl
src/Files.App/Utils/Git/GitHelpers.cs Refactored to be a thin static wrapper that delegates to IVersionControl implementation

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +682 to +689
foreach (TreeEntryChanges c in repository.Diff.Compare<TreeChanges>(repository.Commits.FirstOrDefault()?.Tree, DiffTargets.Index | DiffTargets.WorkingDirectory))
{
if (c.Path.StartsWith(relativePath))
{
changeKind = c.Status;
break;
}
}
Copy link

Copilot AI Jan 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This foreach loop implicitly filters its target sequence - consider filtering the sequence explicitly using '.Where(...)'.

Copilot uses AI. Check for mistakes.
public async Task RequireGitAuthenticationAsync()
{
var pending = true;
var client = new HttpClient();
Copy link

Copilot AI Jan 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disposable 'HttpClient' is created but not disposed.

Suggested change
var client = new HttpClient();
using var client = new HttpClient();

Copilot uses AI. Check for mistakes.
{
var codeResponse = await client.PostAsync(
$"https://github.com/login/device/code?client_id={_clientId}&scope=repo",
new StringContent(""));
Copy link

Copilot AI Jan 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disposable 'StringContent' is created but not disposed.

Copilot uses AI. Check for mistakes.
Comment on lines +592 to +594
var loginResponse = await client.PostAsync(
$"https://github.com/login/oauth/access_token?client_id={_clientId}&device_code={deviceCode}&grant_type=urn:ietf:params:oauth:grant-type:device_code",
new StringContent(""));
Copy link

Copilot AI Jan 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disposable 'StringContent' is created but not disposed.

Suggested change
var loginResponse = await client.PostAsync(
$"https://github.com/login/oauth/access_token?client_id={_clientId}&device_code={deviceCode}&grant_type=urn:ietf:params:oauth:grant-type:device_code",
new StringContent(""));
using var content = new StringContent("");
var loginResponse = await client.PostAsync(
$"https://github.com/login/oauth/access_token?client_id={_clientId}&device_code={deviceCode}&grant_type=urn:ietf:params:oauth:grant-type:device_code",
content);

Copilot uses AI. Check for mistakes.
Comment on lines 117 to 139
var (result, returnValue) = await DoGitOperationAsync<(GitOperationResult, BranchItem[])>(() =>
{
var branches = Array.Empty<BranchItem>();
var result = GitOperationResult.Success;
try
{
using var repository = new Repository(path);

branches = GetValidBranches(repository.Branches)
.Where(b => !b.IsRemote || b.RemoteName == "origin")
.OrderByDescending(b => b.Tip?.Committer.When)
.Take(MAX_NUMBER_OF_BRANCHES)
.OrderByDescending(b => b.IsCurrentRepositoryHead)
.Select(b => new BranchItem(b.FriendlyName, b.IsCurrentRepositoryHead, b.IsRemote, TryGetTrackingDetails(b)?.AheadBy ?? 0, TryGetTrackingDetails(b)?.BehindBy ?? 0))
.ToArray();
}
catch
{
result = GitOperationResult.GenericError;
}

return (result, branches);
});
Copy link

Copilot AI Jan 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assignment to result is useless, since its value is never read.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Comments