feature: bare repository support

This commit is contained in:
leo 2025-01-13 19:49:50 +08:00
parent cc5f3ebfa5
commit b9b5220590
No known key found for this signature in database
6 changed files with 89 additions and 48 deletions

View file

@ -31,6 +31,11 @@ namespace SourceGit.ViewModels
set => _repo.Settings.CheckoutBranchOnCreateBranch = value; set => _repo.Settings.CheckoutBranchOnCreateBranch = value;
} }
public bool IsBareRepository
{
get => _repo.IsBare;
}
public CreateBranch(Repository repo, Models.Branch branch) public CreateBranch(Repository repo, Models.Branch branch)
{ {
_repo = repo; _repo = repo;
@ -84,7 +89,7 @@ namespace SourceGit.ViewModels
return Task.Run(() => return Task.Run(() =>
{ {
var succ = false; var succ = false;
if (CheckoutAfterCreated) if (CheckoutAfterCreated && !_repo.IsBare)
{ {
var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result(); var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
var needPopStash = false; var needPopStash = false;

View file

@ -280,19 +280,20 @@ namespace SourceGit.ViewModels
return; return;
} }
var gitDir = new Commands.QueryGitDir(node.Id).Result(); var isBare = new Commands.IsBareRepository(node.Id).Result();
var gitDir = node.Id;
if (!isBare)
{
gitDir = new Commands.QueryGitDir(node.Id).Result();
if (string.IsNullOrEmpty(gitDir)) if (string.IsNullOrEmpty(gitDir))
{ {
var ctx = page == null ? ActivePage.Node.Id : page.Node.Id; var ctx = page == null ? ActivePage.Node.Id : page.Node.Id;
App.RaiseException(ctx, "Given path is not a valid git repository!"); App.RaiseException(ctx, "Given path is not a valid git repository!");
return; return;
} }
}
var repo = new Repository() var repo = new Repository(isBare, node.Id, gitDir);
{
FullPath = node.Id,
GitDir = gitDir,
};
repo.Open(); repo.Open();
if (page == null) if (page == null)

View file

@ -18,6 +18,11 @@ namespace SourceGit.ViewModels
{ {
public class Repository : ObservableObject, Models.IRepository public class Repository : ObservableObject, Models.IRepository
{ {
public bool IsBare
{
get;
}
public string FullPath public string FullPath
{ {
get => _fullpath; get => _fullpath;
@ -448,6 +453,13 @@ namespace SourceGit.ViewModels
private set => SetProperty(ref _isAutoFetching, value); private set => SetProperty(ref _isAutoFetching, value);
} }
public Repository(bool isBare, string path, string gitDir)
{
IsBare = isBare;
FullPath = path;
GitDir = gitDir;
}
public void Open() public void Open()
{ {
var settingsFile = Path.Combine(_gitDir, "sourcegit.settings"); var settingsFile = Path.Combine(_gitDir, "sourcegit.settings");
@ -995,6 +1007,9 @@ namespace SourceGit.ViewModels
public void RefreshWorkingCopyChanges() public void RefreshWorkingCopyChanges()
{ {
if (IsBare)
return;
var changes = new Commands.QueryLocalChanges(_fullpath, _settings.IncludeUntrackedInLocalChanges).Result(); var changes = new Commands.QueryLocalChanges(_fullpath, _settings.IncludeUntrackedInLocalChanges).Result();
if (_workingCopy == null) if (_workingCopy == null)
return; return;
@ -1010,6 +1025,9 @@ namespace SourceGit.ViewModels
public void RefreshStashes() public void RefreshStashes()
{ {
if (IsBare)
return;
var stashes = new Commands.QueryStashes(_fullpath).Result(); var stashes = new Commands.QueryStashes(_fullpath).Result();
Dispatcher.UIThread.Invoke(() => Dispatcher.UIThread.Invoke(() =>
{ {

View file

@ -34,7 +34,7 @@ namespace SourceGit.ViewModels
watch.Start(); watch.Start();
var rootDir = new DirectoryInfo(RootDir); var rootDir = new DirectoryInfo(RootDir);
var founded = new List<string>(); var founded = new List<FoundRepository>();
GetUnmanagedRepositories(rootDir, founded, new EnumerationOptions() GetUnmanagedRepositories(rootDir, founded, new EnumerationOptions()
{ {
AttributesToSkip = FileAttributes.Hidden | FileAttributes.System, AttributesToSkip = FileAttributes.Hidden | FileAttributes.System,
@ -47,16 +47,16 @@ namespace SourceGit.ViewModels
foreach (var f in founded) foreach (var f in founded)
{ {
var parent = new DirectoryInfo(f).Parent!.FullName.Replace("\\", "/"); var parent = new DirectoryInfo(f.Path).Parent!.FullName.Replace("\\", "/");
if (parent.Equals(normalizedRoot, StringComparison.Ordinal)) if (parent.Equals(normalizedRoot, StringComparison.Ordinal))
{ {
Preferences.Instance.FindOrAddNodeByRepositoryPath(f, null, false); Preferences.Instance.FindOrAddNodeByRepositoryPath(f.Path, null, false);
} }
else if (parent.StartsWith(normalizedRoot, StringComparison.Ordinal)) else if (parent.StartsWith(normalizedRoot, StringComparison.Ordinal))
{ {
var relative = parent.Substring(normalizedRoot.Length).TrimStart('/'); var relative = parent.Substring(normalizedRoot.Length).TrimStart('/');
var group = FindOrCreateGroupRecursive(Preferences.Instance.RepositoryNodes, relative); var group = FindOrCreateGroupRecursive(Preferences.Instance.RepositoryNodes, relative);
Preferences.Instance.FindOrAddNodeByRepositoryPath(f, group, false); Preferences.Instance.FindOrAddNodeByRepositoryPath(f.Path, group, false);
} }
} }
@ -85,7 +85,7 @@ namespace SourceGit.ViewModels
} }
} }
private void GetUnmanagedRepositories(DirectoryInfo dir, List<string> outs, EnumerationOptions opts, int depth = 0) private void GetUnmanagedRepositories(DirectoryInfo dir, List<FoundRepository> outs, EnumerationOptions opts, int depth = 0)
{ {
var subdirs = dir.GetDirectories("*", opts); var subdirs = dir.GetDirectories("*", opts);
foreach (var subdir in subdirs) foreach (var subdir in subdirs)
@ -111,12 +111,19 @@ namespace SourceGit.ViewModels
{ {
var normalized = test.StdOut.Trim().Replace("\\", "/"); var normalized = test.StdOut.Trim().Replace("\\", "/");
if (!_managed.Contains(normalized)) if (!_managed.Contains(normalized))
outs.Add(normalized); outs.Add(new FoundRepository(normalized, false));
} }
continue; continue;
} }
var isBare = new Commands.IsBareRepository(subdir.FullName).Result();
if (isBare)
{
outs.Add(new FoundRepository(normalizedSelf, true));
continue;
}
if (depth < 5) if (depth < 5)
GetUnmanagedRepositories(subdir, outs, opts, depth + 1); GetUnmanagedRepositories(subdir, outs, opts, depth + 1);
} }
@ -161,6 +168,12 @@ namespace SourceGit.ViewModels
return added; return added;
} }
private record FoundRepository(string path, bool isBare)
{
public string Path { get; set; } = path;
public bool IsBare { get; set; } = isBare;
}
private HashSet<string> _managed = new HashSet<string>(); private HashSet<string> _managed = new HashSet<string>();
} }
} }

View file

@ -94,12 +94,9 @@ namespace SourceGit.ViewModels
} }
var isBare = new Commands.IsBareRepository(path).Result(); var isBare = new Commands.IsBareRepository(path).Result();
if (isBare) var repoRoot = path;
if (!isBare)
{ {
App.RaiseException(string.Empty, $"'{path}' is a bare repository, which is not supported by SourceGit!");
return;
}
var test = new Commands.QueryRepositoryRootPath(path).ReadToEnd(); var test = new Commands.QueryRepositoryRootPath(path).ReadToEnd();
if (!test.IsSuccess || string.IsNullOrEmpty(test.StdOut)) if (!test.IsSuccess || string.IsNullOrEmpty(test.StdOut))
{ {
@ -107,7 +104,10 @@ namespace SourceGit.ViewModels
return; return;
} }
var node = Preferences.Instance.FindOrAddNodeByRepositoryPath(test.StdOut.Trim(), parent, bMoveExistedNode); repoRoot = test.StdOut.Trim();
}
var node = Preferences.Instance.FindOrAddNodeByRepositoryPath(repoRoot, parent, bMoveExistedNode);
Refresh(); Refresh();
var launcher = App.GetLauncer(); var launcher = App.GetLauncer();

View file

@ -18,8 +18,8 @@
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="32"/> <RowDefinition Height="32"/>
<RowDefinition Height="32"/> <RowDefinition Height="32"/>
<RowDefinition Height="Auto" MinHeight="32"/> <RowDefinition Height="Auto"/>
<RowDefinition Height="32"/> <RowDefinition Height="Auto"/>
</Grid.RowDefinitions> </Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" <TextBlock Grid.Row="0" Grid.Column="0"
@ -67,7 +67,9 @@
<TextBlock Grid.Row="2" Grid.Column="0" <TextBlock Grid.Row="2" Grid.Column="0"
HorizontalAlignment="Right" VerticalAlignment="Center" HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,8,0" Margin="0,0,8,0"
Text="{DynamicResource Text.CreateBranch.LocalChanges}"/> Text="{DynamicResource Text.CreateBranch.LocalChanges}"
IsVisible="{Binding !IsBareRepository}"/>
<Border Grid.Row="2" Grid.Column="1" MinHeight="32" IsVisible="{Binding !IsBareRepository}">
<WrapPanel Grid.Row="2" Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center"> <WrapPanel Grid.Row="2" Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center">
<RadioButton Content="{DynamicResource Text.CreateBranch.LocalChanges.DoNothing}" <RadioButton Content="{DynamicResource Text.CreateBranch.LocalChanges.DoNothing}"
x:Name="RadioDoNothing" x:Name="RadioDoNothing"
@ -84,10 +86,12 @@
GroupName="LocalChanges" GroupName="LocalChanges"
IsCheckedChanged="OnLocalChangeActionIsCheckedChanged"/> IsCheckedChanged="OnLocalChangeActionIsCheckedChanged"/>
</WrapPanel> </WrapPanel>
</Border>
<CheckBox Grid.Row="3" Grid.Column="1" <CheckBox Grid.Row="3" Grid.Column="1"
Content="{DynamicResource Text.CreateBranch.Checkout}" Content="{DynamicResource Text.CreateBranch.Checkout}"
IsChecked="{Binding CheckoutAfterCreated, Mode=TwoWay}"/> IsChecked="{Binding CheckoutAfterCreated, Mode=TwoWay}"
IsVisible="{Binding !IsBareRepository}"/>
</Grid> </Grid>
</StackPanel> </StackPanel>
</UserControl> </UserControl>