fix(CommitViewer): show submodule revision when item seleted in FILES tab

This commit is contained in:
leo 2020-07-22 21:28:57 +08:00
parent 0132fc496b
commit 39e55a3f2d
3 changed files with 82 additions and 24 deletions

View file

@ -12,6 +12,22 @@ namespace SourceGit.Git {
private static readonly string GPGSIG_START = "gpgsig -----BEGIN PGP SIGNATURE-----";
private static readonly string GPGSIG_END = " -----END PGP SIGNATURE-----";
/// <summary>
/// Object in commit.
/// </summary>
public class Object {
public enum Type {
Tag,
Blob,
Tree,
Commit,
}
public string Path { get; set; }
public Type Kind { get; set; }
public string SHA { get; set; }
}
/// <summary>
/// SHA
/// </summary>
@ -173,11 +189,27 @@ namespace SourceGit.Git {
/// </summary>
/// <param name="repo"></param>
/// <returns></returns>
public List<string> GetFiles(Repository repo) {
var files = new List<string>();
public List<Object> GetFiles(Repository repo) {
var files = new List<Object>();
var test = new Regex(@"^\d+\s+(\w+)\s+([0-9a-f]+)\s+(.*)$");
var errs = repo.RunCommand($"ls-tree --name-only -r {SHA}", line => {
files.Add(line);
var errs = repo.RunCommand($"ls-tree -r {SHA}", line => {
var match = test.Match(line);
if (!match.Success) return;
var obj = new Object();
obj.Path = match.Groups[3].Value;
obj.Kind = Object.Type.Blob;
obj.SHA = match.Groups[2].Value;
switch (match.Groups[1].Value) {
case "tag": obj.Kind = Object.Type.Tag; break;
case "blob": obj.Kind = Object.Type.Blob; break;
case "tree": obj.Kind = Object.Type.Tree; break;
case "commit": obj.Kind = Object.Type.Commit; break;
}
files.Add(obj);
});
if (errs != null) App.RaiseError(errs);

View file

@ -405,6 +405,11 @@
x:Name="filePreview"/>
</ScrollViewer>
<StackPanel x:Name="maskRevision" Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center" Visibility="Collapsed">
<Path x:Name="iconPreviewRevision" Width="64" Height="64" Style="{StaticResource Style.Icon}" Data="{StaticResource Icon.Submodule}" Fill="{StaticResource Brush.FG2}"/>
<Label x:Name="txtPreviewRevision" Margin="0,16,0,0" FontFamily="Consolas" FontSize="18" FontWeight="UltraBold" HorizontalAlignment="Center" Foreground="{StaticResource Brush.FG2}"/>
</StackPanel>
<StackPanel x:Name="maskPreviewNotSupported" Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center" Visibility="Collapsed">
<Path Width="64" Height="64" Style="{StaticResource Style.Icon}" Data="{StaticResource Icon.Info}" Fill="{StaticResource Brush.FG2}"/>
<Label Margin="0,16,0,0" Content="BINARY FILE DETECTED" FontFamily="Consolas" FontSize="18" FontWeight="UltraBold" HorizontalAlignment="Center" Foreground="{StaticResource Brush.FG2}"/>

View file

@ -30,6 +30,7 @@ namespace SourceGit.UI {
public bool IsFile { get; set; } = false;
public bool IsNodeExpanded { get; set; } = true;
public Git.Change Change { get; set; } = null;
public Git.Commit.Object CommitObject { get; set; } = null;
public List<Node> Children { get; set; } = new List<Node>();
}
@ -295,25 +296,26 @@ namespace SourceGit.UI {
#endregion
#region FILES
private void SetRevisionFiles(List<string> files) {
private void SetRevisionFiles(List<Git.Commit.Object> files) {
List<Node> fileTreeSource = new List<Node>();
Dictionary<string, Node> folders = new Dictionary<string, Node>();
foreach (var path in files) {
var sepIdx = path.IndexOf("/");
foreach (var obj in files) {
var sepIdx = obj.Path.IndexOf("/");
if (sepIdx == -1) {
Node node = new Node();
node.FilePath = path;
node.Name = path;
node.FilePath = obj.Path;
node.Name = obj.Path;
node.IsFile = true;
node.IsNodeExpanded = false;
node.CommitObject = obj;
fileTreeSource.Add(node);
} else {
Node lastFolder = null;
var start = 0;
while (sepIdx != -1) {
var folder = path.Substring(0, sepIdx);
var folder = obj.Path.Substring(0, sepIdx);
if (folders.ContainsKey(folder)) {
lastFolder = folders[folder];
} else if (lastFolder == null) {
@ -334,14 +336,15 @@ namespace SourceGit.UI {
}
start = sepIdx + 1;
sepIdx = path.IndexOf('/', start);
sepIdx = obj.Path.IndexOf('/', start);
}
Node node = new Node();
node.FilePath = path;
node.Name = path.Substring(start);
node.FilePath = obj.Path;
node.Name = obj.Path.Substring(start);
node.IsFile = true;
node.IsNodeExpanded = false;
node.CommitObject = obj;
lastFolder.Children.Add(node);
}
}
@ -358,20 +361,37 @@ namespace SourceGit.UI {
private async void FileTreeItemSelected(object sender, RoutedPropertyChangedEventArgs<object> e) {
filePreview.Text = "";
maskPreviewNotSupported.Visibility = Visibility.Collapsed;
maskRevision.Visibility = Visibility.Collapsed;
var node = e.NewValue as Node;
if (node == null || !node.IsFile) return;
if (node == null || !node.IsFile || node.CommitObject == null) return;
await Task.Run(() => {
var isBinary = false;
var data = commit.GetTextFileContent(repo, node.FilePath, out isBinary);
switch (node.CommitObject.Kind) {
case Git.Commit.Object.Type.Blob:
await Task.Run(() => {
var isBinary = false;
var data = commit.GetTextFileContent(repo, node.FilePath, out isBinary);
if (isBinary) {
Dispatcher.Invoke(() => maskPreviewNotSupported.Visibility = Visibility.Visible);
} else {
Dispatcher.Invoke(() => filePreview.Text = data);
}
});
if (isBinary) {
Dispatcher.Invoke(() => maskPreviewNotSupported.Visibility = Visibility.Visible);
} else {
Dispatcher.Invoke(() => filePreview.Text = data);
}
});
break;
case Git.Commit.Object.Type.Tag:
maskRevision.Visibility = Visibility.Visible;
iconPreviewRevision.Data = FindResource("Icon.Tag") as Geometry;
txtPreviewRevision.Content = "TAG: " + node.CommitObject.SHA;
break;
case Git.Commit.Object.Type.Commit:
maskRevision.Visibility = Visibility.Visible;
iconPreviewRevision.Data = FindResource("Icon.Submodule") as Geometry;
txtPreviewRevision.Content = "SUBMODULE: " + node.CommitObject.SHA;
break;
default:
return;
}
}
#endregion
@ -455,6 +475,7 @@ namespace SourceGit.UI {
MenuItem saveAs = new MenuItem();
saveAs.Header = "Save As ...";
saveAs.IsEnabled = node.CommitObject == null || node.CommitObject.Kind == Git.Commit.Object.Type.Blob;
saveAs.Click += (obj, ev) => {
var dialog = new System.Windows.Forms.FolderBrowserDialog();
dialog.Description = node.FilePath;