Show Git, Cloud, and created date in Details, and hide Free space except on drives.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
148
src/Explorer.Application/GitListingOverlay.cs
Normal file
148
src/Explorer.Application/GitListingOverlay.cs
Normal file
@@ -0,0 +1,148 @@
|
||||
using Explorer.Domain;
|
||||
|
||||
namespace Explorer.Application;
|
||||
|
||||
public static class GitListingOverlay
|
||||
{
|
||||
public static string ForNestedRepo(GitStatus status)
|
||||
{
|
||||
var parts = new List<string> { status.Branch };
|
||||
if (!string.IsNullOrEmpty(status.OperationLabel))
|
||||
{
|
||||
parts.Add(status.OperationLabel);
|
||||
}
|
||||
|
||||
if (status.ModifiedCount > 0)
|
||||
{
|
||||
parts.Add($"{status.ModifiedCount} modified");
|
||||
}
|
||||
|
||||
if (status.UntrackedCount > 0)
|
||||
{
|
||||
parts.Add($"{status.UntrackedCount} untracked");
|
||||
}
|
||||
|
||||
return string.Join(" · ", parts);
|
||||
}
|
||||
|
||||
public static string ForItem(string itemFullPath, bool isDirectory, string repoRoot, GitStatus status)
|
||||
{
|
||||
var rel = ToGitRelative(repoRoot, itemFullPath);
|
||||
if (rel is null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
return isDirectory ? FolderLabel(status.Changes, rel) : FileLabel(status.Changes, rel);
|
||||
}
|
||||
|
||||
internal static string? ToGitRelative(string repoRoot, string fullPath)
|
||||
{
|
||||
var root = PathRules.FromExtended(repoRoot).TrimEnd('\\');
|
||||
var full = PathRules.FromExtended(fullPath).TrimEnd('\\');
|
||||
if (full.Equals(root, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
if (!full.StartsWith(root + "\\", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return full[(root.Length + 1)..].Replace('\\', '/');
|
||||
}
|
||||
|
||||
private static string FileLabel(IReadOnlyList<GitChange> changes, string rel)
|
||||
{
|
||||
if (rel.Length == 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
var hits = changes.Where(c => Matches(c, rel)).ToList();
|
||||
if (hits.Count == 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
if (hits.Exists(c => c.State == GitChangeState.Unmerged))
|
||||
{
|
||||
return "Unmerged";
|
||||
}
|
||||
|
||||
if (hits.Exists(c => c.State == GitChangeState.Untracked))
|
||||
{
|
||||
return "Untracked";
|
||||
}
|
||||
|
||||
var staged = hits.Find(c => c.State == GitChangeState.Staged);
|
||||
var unstaged = hits.Find(c => c.State == GitChangeState.Unstaged);
|
||||
if (staged is not null && unstaged is not null)
|
||||
{
|
||||
return "Staged · Modified";
|
||||
}
|
||||
|
||||
if (staged is not null)
|
||||
{
|
||||
return staged.Index switch
|
||||
{
|
||||
'R' => "Renamed",
|
||||
'A' => "Added",
|
||||
'D' => "Deleted",
|
||||
_ => "Staged"
|
||||
};
|
||||
}
|
||||
|
||||
return unstaged is null ? "" : Title(unstaged.ChangeLabel);
|
||||
}
|
||||
|
||||
private static string FolderLabel(IReadOnlyList<GitChange> changes, string rel)
|
||||
{
|
||||
var hits = changes.Where(c => Under(c, rel)).ToList();
|
||||
if (hits.Count == 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
if (hits.Exists(c => c.State == GitChangeState.Unmerged))
|
||||
{
|
||||
return "Unmerged";
|
||||
}
|
||||
|
||||
if (hits.TrueForAll(c => c.State == GitChangeState.Untracked))
|
||||
{
|
||||
return "Untracked";
|
||||
}
|
||||
|
||||
return "Modified";
|
||||
}
|
||||
|
||||
private static bool Matches(GitChange change, string rel)
|
||||
=> Same(change.Path, rel)
|
||||
|| (change.OriginalPath is { Length: > 0 } original && Same(original, rel));
|
||||
|
||||
private static bool Under(GitChange change, string rel)
|
||||
{
|
||||
if (Matches(change, rel))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (rel.Length == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var prefix = rel + "/";
|
||||
return change.Path.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)
|
||||
|| (change.OriginalPath is { Length: > 0 } original
|
||||
&& original.StartsWith(prefix, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
private static bool Same(string left, string right)
|
||||
=> left.Equals(right, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
private static string Title(string value)
|
||||
=> string.IsNullOrEmpty(value) ? "" : char.ToUpperInvariant(value[0]) + value[1..];
|
||||
}
|
||||
Reference in New Issue
Block a user