Skip to content

Fix: Fixed issue where repository names lost casing and retained .git suffix #17421

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 10, 2025
Merged
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
26 changes: 13 additions & 13 deletions src/Files.App/Utils/Git/GitHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
using System.Net.Http;
using System.Net.Http.Json;
using System.Text;
using System.Text.RegularExpressions;

namespace Files.App.Utils.Git
{
internal static class GitHelpers
internal static partial class GitHelpers
{
private static readonly StatusCenterViewModel StatusCenterViewModel = Ioc.Default.GetRequiredService<StatusCenterViewModel>();

Expand Down Expand Up @@ -864,20 +865,16 @@ private static bool IsAuthorizationException(Exception ex)
/// <returns></returns>
public static (string RepoUrl, string RepoName) GetRepoInfo(string url)
{
// Remove protocol and normalize slashes
var normalizedUrl = url.ToLower().Replace("https://", "").Replace("http://", "").Replace("//", "");
var match = GitHubRepositoryRegex().Match(url);

string[] parts = normalizedUrl.Split('/');
if (!match.Success)
return (string.Empty, string.Empty);

// Check if the URL includes an organization or user name + repo (github.com/username/repo)
if (parts.Length >= 3 && parts[0] == "github.com")
{
// Construct the repo URL from the first three parts
string repoUrl = $"https://{parts[0]}/{parts[1]}/{parts[2]}";
return (repoUrl, parts[2]);
}
string userOrOrg = match.Groups["user"].Value;
string repoName = match.Groups["repo"].Value;

return (string.Empty, string.Empty);
string repoUrl = $"https://github.com/{userOrOrg}/{repoName}";
return (repoUrl, repoName);
}

/// <summary>
Expand All @@ -887,7 +884,7 @@ public static (string RepoUrl, string RepoName) GetRepoInfo(string url)
/// <returns>True if the URL is a valid GitHub URL; otherwise, false.</returns>
public static bool IsValidRepoUrl(string url)
{
return !string.IsNullOrWhiteSpace(url) && url.Contains("github.com");
return GitHubRepositoryRegex().IsMatch(url);
}

public static async Task CloneRepoAsync(string repoUrl, string repoName, string targetDirectory)
Expand Down Expand Up @@ -945,5 +942,8 @@ public static async Task CloneRepoAsync(string repoUrl, string repoName, string
banner.CancellationToken.IsCancellationRequested ? ReturnResult.Cancelled :
ReturnResult.Failed);
}

[GeneratedRegex(@"^(?:https?:\/\/)?(?:www\.)?github\.com\/(?<user>[^\/]+)\/(?<repo>[^\/]+?)(?=\.git|\/|$)(?:\.git)?(?:\/)?", RegexOptions.IgnoreCase)]
private static partial Regex GitHubRepositoryRegex();
}
}
Loading