Skip to content
Open
Show file tree
Hide file tree
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
Binary file added screenshots/drag_branch_graph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added screenshots/drag_branch_menu.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
72 changes: 72 additions & 0 deletions src/Models/Remote.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,5 +146,77 @@ public bool TryGetCreatePullRequestURL(out string url, string mergeBranch)

return false;
}

/// <summary>
/// Builds the URL to create a pull request on this remote that merges `sourceBranch` into `targetBranch`.
/// When `sourceRemote` is another remote (e.g. a fork), only GitHub is supported.
/// </summary>
public bool TryGetCreatePullRequestURL(out string url, string sourceBranch, string targetBranch, Remote sourceRemote)
{
url = null;

if (!TryGetVisitURL(out var baseURL))
return false;

var host = new Uri(baseURL).Host;
var source = HttpUtility.UrlEncode(sourceBranch);
var target = HttpUtility.UrlEncode(targetBranch);

if (sourceRemote != null && sourceRemote != this)
{
if (!host.Contains("github.com", StringComparison.Ordinal) || !sourceRemote.TryGetVisitURL(out var sourceURL))
return false;

var sourceURI = new Uri(sourceURL);
if (!sourceURI.Host.Equals(host, StringComparison.Ordinal))
return false;

var segments = sourceURI.AbsolutePath.Split('/', StringSplitOptions.RemoveEmptyEntries);
if (segments.Length < 2)
return false;

url = $"{baseURL}/compare/{target}...{HttpUtility.UrlEncode(segments[0])}:{HttpUtility.UrlEncode(segments[1])}:{source}?expand=1";
return true;
}

if (host.Contains("github.com", StringComparison.Ordinal))
{
url = $"{baseURL}/compare/{target}...{source}?expand=1";
return true;
}

if (host.Contains("gitlab", StringComparison.Ordinal))
{
url = $"{baseURL}/-/merge_requests/new?merge_request%5Bsource_branch%5D={source}&merge_request%5Btarget_branch%5D={target}";
return true;
}

if (host.Equals("gitee.com", StringComparison.Ordinal))
{
url = $"{baseURL}/pulls/new?source={source}&target={target}";
return true;
}

if (host.Equals("bitbucket.org", StringComparison.Ordinal))
{
url = $"{baseURL}/pull-requests/new?source={source}&dest={target}";
return true;
}

if (host.Equals("gitea.org", StringComparison.Ordinal))
{
url = $"{baseURL}/compare/{target}...{source}";
return true;
}

if (host.Contains("azure.com", StringComparison.Ordinal) ||
host.Contains("visualstudio.com", StringComparison.Ordinal))
{
url = $"{baseURL}/pullrequestcreate?sourceRef={source}&targetRef={target}";
return true;
}

return false;
}
}
}
2 changes: 2 additions & 0 deletions src/Resources/Locales/en_US.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,15 @@
<x:String x:Key="Text.Blame.TypeNotSupported" xml:space="preserve">BLAME ON THIS FILE IS NOT SUPPORTED!!!</x:String>
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Checkout ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.CheckoutAsWorktree" xml:space="preserve">Checkout ${0}$ as worktree...</x:String>
<x:String x:Key="Text.BranchCM.CompareBranches" xml:space="preserve">Compare ${0}$ with ${1}$</x:String>
<x:String x:Key="Text.BranchCM.CompareTwo" xml:space="preserve">Compare selected 2 branches</x:String>
<x:String x:Key="Text.BranchCM.CompareWith" xml:space="preserve">Compare with...</x:String>
<x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">Compare with HEAD</x:String>
<x:String x:Key="Text.BranchCM.CompareWithSpecial" xml:space="preserve">Compare with ${0}$</x:String>
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Copy Branch Name</x:String>
<x:String x:Key="Text.BranchCM.CreatePR" xml:space="preserve">Create PR...</x:String>
<x:String x:Key="Text.BranchCM.CreatePRForUpstream" xml:space="preserve">Create PR for upstream ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.CreatePRFromTo" xml:space="preserve">Create PR from ${0}$ into ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.CustomAction" xml:space="preserve">Custom Action</x:String>
<x:String x:Key="Text.BranchCM.Delete" xml:space="preserve">Delete ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.DeleteMultiBranches" xml:space="preserve">Delete selected {0} branches...</x:String>
Expand Down
14 changes: 14 additions & 0 deletions src/ViewModels/BranchTreeNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,18 @@ public CornerRadius CornerRadius
set => SetProperty(ref _cornerRadius, value);
}

public bool IsDragSource
{
get => _isDragSource;
set => SetProperty(ref _isDragSource, value);
}

public bool IsDropTarget
{
get => _isDropTarget;
set => SetProperty(ref _isDropTarget, value);
}

public bool IsBranch
{
get => Backend is Models.Branch;
Expand All @@ -57,6 +69,8 @@ public string BranchesCount
private Models.FilterMode _filterMode = Models.FilterMode.None;
private bool _isExpanded = false;
private CornerRadius _cornerRadius = new CornerRadius(4);
private bool _isDragSource = false;
private bool _isDropTarget = false;

public class Builder
{
Expand Down
Loading