Skip to content

Commit

Permalink
Add a way to navigate to GitHub/GitLab from the selected commit (#8)
Browse files Browse the repository at this point in the history
* Add a way to navigate to GitHub/GitLab from the selected commit

- Closes #4
  • Loading branch information
LaurentM-Ubi authored Apr 25, 2022
1 parent 48324e3 commit a2d38cf
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 17 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ jobs:
release_name="GitTimelapseView-$tag-${{ matrix.target }}"
# Build everything
dotnet publish GitTimelapseView/GitTimelapseView.csproj --framework net6.0-windows --runtime "${{ matrix.target }}" -c Release -o "$release_name"
dotnet publish GitTimelapseView/GitTimelapseView.csproj --framework net6.0-windows --runtime "${{ matrix.target }}" -c Release -o "$release_name" --self-contained
# Pack files
if [ "${{ matrix.target }}" == "win-x64" ]; then
Expand Down
48 changes: 48 additions & 0 deletions GitTimelapseView.Core/Common/GitHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,20 @@ public static string RunGitCommand(string gitRootPath, string args, ILogger logg
return gitProcess.StandardOutput.ReadToEnd().Trim();
}

public static string? GetRemotePlatform(string remoteUrl)
{
if (remoteUrl.Contains("github.com", StringComparison.OrdinalIgnoreCase))
{
return "GitHub";
}
else if (remoteUrl.Contains("gitlab", StringComparison.OrdinalIgnoreCase))
{
return "GitLab";
}

return null;
}

internal static IReadOnlyList<string> GetCommitFileLines(this Repository repository, string relativeFilePath, string sha)
{
var commit = repository.Lookup<Commit>(sha);
Expand Down Expand Up @@ -79,6 +93,40 @@ internal static IReadOnlyList<string> GetCommitFileLines(this Repository reposit
return relRoot.MakeRelativeUri(fullPath).ToString();
}

internal static string? FindRemoteUrl(this Repository repository)
{
if (repository.Network.Remotes.Any())
{
var remote = repository.Network.Remotes.First();
var url = remote.Url;
if (url.EndsWith(".git", StringComparison.Ordinal))
{
if (url.StartsWith("git", StringComparison.Ordinal))
{
url = url.Replace(":", "/", StringComparison.Ordinal).Replace("git@", "https://", StringComparison.Ordinal);
}

return url.Replace(".git", string.Empty, StringComparison.Ordinal).TrimEnd('/');
}
}

return null;
}

internal static string? GetCommitUrl(string remoteUrl, string sha)
{
if (remoteUrl.Contains("github.com", StringComparison.OrdinalIgnoreCase))
{
return $"{remoteUrl}/commit/{sha}";
}
else if (remoteUrl.Contains("gitlab", StringComparison.OrdinalIgnoreCase))
{
return $"{remoteUrl}/-/commit/{sha}";
}

return null;
}

private static void HandleGitCommandErrors(object? sender, ILogger logger, string? onGitErrorMessage = null)
{
if (sender is Process gitProcess)
Expand Down
6 changes: 3 additions & 3 deletions GitTimelapseView.Core/Models/BlameBlock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ namespace GitTimelapseView.Core.Models
{
public class BlameBlock
{
public BlameBlock(BlameHunk block, FileRevision fileRevision, IReadOnlyList<string> lines)
public BlameBlock(BlameHunk block, FileRevision fileRevision, IReadOnlyList<string> lines, string? remoteUrl)
{
InitialSignature = block.InitialSignature;
FinalSignature = block.FinalSignature;
InitialCommit = new Commit(block.InitialCommit, fileRevision.FileHistory);
FinalCommit = new Commit(block.FinalCommit, fileRevision.FileHistory);
InitialCommit = new Commit(block.InitialCommit, fileRevision.FileHistory, remoteUrl);
FinalCommit = new Commit(block.FinalCommit, fileRevision.FileHistory, remoteUrl);
StartLine = block.FinalStartLineNumber + 1;
LineCount = block.LineCount;
FileRevision = fileRevision.FileHistory.GetRevisionPerCommit(FinalCommit);
Expand Down
8 changes: 7 additions & 1 deletion GitTimelapseView.Core/Models/Commit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class Commit
{
private readonly List<FileChange> _fileChanges = new();

public Commit(LibGit2Sharp.Commit commit, FileHistory fileHistory)
public Commit(LibGit2Sharp.Commit commit, FileHistory fileHistory, string? remoteUrl)
{
Message = commit.Message;
MessageShort = commit.MessageShort;
Expand All @@ -22,6 +22,10 @@ public Commit(LibGit2Sharp.Commit commit, FileHistory fileHistory)
Committer = commit.Committer;
FileHistory = fileHistory;
Parents = commit.Parents.Select(x => x.Sha).ToArray();
if (remoteUrl != null)
{
WebUrl = GitHelpers.GetCommitUrl(remoteUrl, commit.Sha);
}
}

public string Message { get; init; }
Expand All @@ -44,6 +48,8 @@ public Commit(LibGit2Sharp.Commit commit, FileHistory fileHistory)

public string? ContainedInTag { get; private set; }

public string? WebUrl { get; }

public void UpdateInfo(ILogger logger)
{
if (FileChanges.Any())
Expand Down
4 changes: 3 additions & 1 deletion GitTimelapseView.Core/Models/FileHistory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ public void Initialize(ILogger logger)
var commitIds = GetFileCommitIDs(logger).Reverse().ToArray();
using (var repository = new Repository(GitRootPath))
{
var remoteUrl = repository.FindRemoteUrl();

var relativeFilePath = repository.MakeRelativeFilePath(FilePath);
if (relativeFilePath == null)
throw new Exception($"Unable to blame '{FilePath}'. Path is not located in the repository working directory.");
Expand All @@ -57,7 +59,7 @@ public void Initialize(ILogger logger)
{
var commitId = commitIds[index];
var commit = repository.Lookup<LibGit2Sharp.Commit>(commitId);
_revisions.Add(new FileRevision(index, new Commit(commit, this), this));
_revisions.Add(new FileRevision(index, new Commit(commit, this, remoteUrl), this));
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion GitTimelapseView.Core/Models/FileRevision.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public void LoadBlocks(ILogger logger)

using (var repository = new Repository(FileHistory.GitRootPath))
{
var remoteUrl = repository.FindRemoteUrl();

var relativeFilePath = repository.MakeRelativeFilePath(FileHistory.FilePath);
if (relativeFilePath == null)
throw new Exception($"Unable to blame '{FileHistory.FilePath}'. Path is not located in the repository working directory.");
Expand All @@ -43,7 +45,7 @@ public void LoadBlocks(ILogger logger)

foreach (var block in blocks)
{
Blocks.Add(new BlameBlock(block, this, lines));
Blocks.Add(new BlameBlock(block, this, lines, remoteUrl));
}
}
}
Expand Down
36 changes: 27 additions & 9 deletions GitTimelapseView/Components/CommitInfo/CommitInfo.razor
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
@namespace GitTimelapseView
@using System.Diagnostics
@using GitTimelapseView.Core.Common

@if (_commit == null)
{
Expand All @@ -9,28 +11,32 @@ else
{
<Card Size="small" class="commit-details" Style="height: 100%">
<TitleTemplate>
<div class="card-title" style="font-weight: bolder;">
<div class="card-title">
<span title=@_commit.Id>
Commit #@_commit.ShortId
</span>
<Tooltip Title=@CopyToClipboardTooltip>
<Button Type="@ButtonType.Text" @onclick="OnButtonClicked" Size="@ButtonSize.Small">
<i class="mdi mdi-clipboard-multiple-outline"></i>
<i class="mdi mdi-clipboard-multiple-outline" />
</Button>
</Tooltip>
<span style="font-size: 12px;">by</span>
<span>by</span>
<span>
<AvatarExt Email=@_commit.Author.Email ShowDisplayName />
</span>
<span style="font-size: 12px;">on @_authoredString</span>
</div>
<span>on @_authoredString</span>
@if(_commit.WebUrl != null && GitHelpers.GetRemotePlatform(_commit.WebUrl) is string platform)
{
<a class="open-remote-url" title=@($"Open commit in {platform}") href="" @onclick="OnWebUrlClicked" @onclick:preventDefault><i class="mdi mdi-open-in-new " />&nbsp;@platform</a>
}
</div>
</TitleTemplate>
<Extra>
@if(!string.IsNullOrEmpty(_commit.ContainedInTag))
{
<Tooltip Title=@($"contained in tag {_commit.ContainedInTag}")>
<span style="opacity:0.4; margin-left: 20px; font-size: 12px;">
<i class="mdi mdi-tag" ></i>
<span class="tag-label" >
<i class="mdi mdi-tag" />
@_commit.ContainedInTag
</span>
</Tooltip>
Expand All @@ -39,7 +45,7 @@ else
<CardTabs>
<Tabs @bind-ActiveKey="@_selectedTab" Animated Size="@TabSize.Small" >
<TabPane Tab="Message" Key="message">
<div style="margin:10px; overflow: scroll; max-height: 220px; max-width: 750px; overflow-y: scroll; overflow-x: scroll;white-space: pre-wrap;">
<div class="commit-message">
@_commit.Message
</div>
</TabPane >
Expand Down Expand Up @@ -86,5 +92,17 @@ else
{
await new CopyToClipboardAction(TimelapseService.CurrentCommit.Id, "commit id").ExecuteAsync().ConfigureAwait(false);
}
}
}

private void OnWebUrlClicked()
{
if (_commit?.WebUrl != null)
{
Process.Start(new ProcessStartInfo
{
FileName = _commit?.WebUrl,
UseShellExecute = true,
});
}
}
}
27 changes: 26 additions & 1 deletion GitTimelapseView/Components/CommitInfo/CommitInfo.razor.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,28 @@
.card-title{
.card-title {
font-weight: bolder;
font-size: 12px;
}

.open-remote-url {
opacity: 0.4;
margin-left: 10px;
font-size: 12px;
color: var(--gtlv-foreground);
text-decoration: none;
}

.tag-label {
opacity: 0.4;
margin-left: 20px;
font-size: 12px;
}

.commit-message {
margin: 10px;
overflow: scroll;
max-height: 220px;
max-width: 750px;
overflow-y: scroll;
overflow-x: scroll;
white-space: pre-wrap;
}

0 comments on commit a2d38cf

Please sign in to comment.