diff --git a/src/WingetCreateCLI/Commands/BaseCommand.cs b/src/WingetCreateCLI/Commands/BaseCommand.cs index c6c2edb7..61d3875e 100644 --- a/src/WingetCreateCLI/Commands/BaseCommand.cs +++ b/src/WingetCreateCLI/Commands/BaseCommand.cs @@ -778,6 +778,24 @@ protected async Task GitHubSubmitManifests(Manifests manifests, string prT Logger.ErrorLocalized(nameof(Resources.SyncForkWithUpstream_Message)); return false; } + else if (e is BranchMergeConflictException) + { + // While attempting to sync fork through the GitHub API, a branch merge conflict was detected. + // The user will need to manually resolve the conflict. + Logger.ErrorLocalized(nameof(Resources.BranchMergeConflict_Message)); + return false; + } + else if (e is GenericSyncFailureException) + { + // While attempting to sync fork through the GitHub API, a generic sync failure occurred. + Logger.ErrorLocalized(nameof(Resources.SyncForkFailed_Message)); + return false; + } + else if (e is HttpRequestException) + { + Logger.ErrorLocalized(nameof(Resources.NetworkConnectionFailure_Message)); + return false; + } else { throw; diff --git a/src/WingetCreateCLI/Properties/Resources.Designer.cs b/src/WingetCreateCLI/Properties/Resources.Designer.cs index f4f99c6d..1eb6b026 100644 --- a/src/WingetCreateCLI/Properties/Resources.Designer.cs +++ b/src/WingetCreateCLI/Properties/Resources.Designer.cs @@ -267,6 +267,15 @@ public static string Back_MenuItem { } } + /// + /// Looks up a localized string similar to The forked repository could not be synced with the upstream commits due to a merge conflict. Resolve conflicts manually and try again.. + /// + public static string BranchMergeConflict_Message { + get { + return ResourceManager.GetString("BranchMergeConflict_Message", resourceCulture); + } + } + /// /// Looks up a localized string similar to Web browser failed to launch: {0}. /// @@ -3194,6 +3203,15 @@ public static string SwitchToUpdateLocaleFlow_Message { } } + /// + /// Looks up a localized string similar to The forked repository could not be synced with the upstream commits. Sync your fork manually and try again.. + /// + public static string SyncForkFailed_Message { + get { + return ResourceManager.GetString("SyncForkFailed_Message", resourceCulture); + } + } + /// /// Looks up a localized string similar to Unable to create a reference to the forked repository. This can be caused when the forked repository is behind by too many commits. Sync your fork and try again.. /// diff --git a/src/WingetCreateCLI/Properties/Resources.resx b/src/WingetCreateCLI/Properties/Resources.resx index 42b13aaa..14180ffb 100644 --- a/src/WingetCreateCLI/Properties/Resources.resx +++ b/src/WingetCreateCLI/Properties/Resources.resx @@ -1400,4 +1400,10 @@ Warning: Using this argument may result in the token being logged. Consider an a Does this executable depend on DLLs or any other files present in the zip archive? + + The forked repository could not be synced with the upstream commits. Sync your fork manually and try again. + + + The forked repository could not be synced with the upstream commits due to a merge conflict. Resolve conflicts manually and try again. + \ No newline at end of file diff --git a/src/WingetCreateCore/Common/Exceptions/BranchMergeConflictException.cs b/src/WingetCreateCore/Common/Exceptions/BranchMergeConflictException.cs new file mode 100644 index 00000000..fab9ce24 --- /dev/null +++ b/src/WingetCreateCore/Common/Exceptions/BranchMergeConflictException.cs @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.WingetCreateCore.Common.Exceptions +{ + using System; + + /// + /// The exception that is thrown when the forked repo's branch has a merge conflict with the upstream branch. + /// + public class BranchMergeConflictException : Exception + { + /// + /// Initializes a new instance of the class. + /// + public BranchMergeConflictException() + { + } + } +} diff --git a/src/WingetCreateCore/Common/Exceptions/GenericSyncFailureException.cs b/src/WingetCreateCore/Common/Exceptions/GenericSyncFailureException.cs new file mode 100644 index 00000000..c9563ebf --- /dev/null +++ b/src/WingetCreateCore/Common/Exceptions/GenericSyncFailureException.cs @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.WingetCreateCore.Common.Exceptions +{ + using System; + + /// + /// The exception that is thrown when a generic failure occurs while syncing the forked repo with upstream commits. + /// + public class GenericSyncFailureException : Exception + { + /// + /// Initializes a new instance of the class. + /// + public GenericSyncFailureException() + { + } + } +} diff --git a/src/WingetCreateCore/Common/GitHub.cs b/src/WingetCreateCore/Common/GitHub.cs index 03d99d45..7ace29de 100644 --- a/src/WingetCreateCore/Common/GitHub.cs +++ b/src/WingetCreateCore/Common/GitHub.cs @@ -488,9 +488,11 @@ private async Task UpdateForkedRepoWithUpstreamCommits(Repository forkedRepo) // Octokit .NET doesn't support sync fork endpoint, so we make a direct call to the GitHub API. // Tracking issue for the request: https://github.com/octokit/octokit.net/issues/2989 - // API reference: https://docs.github.com/en/rest/branches/branches?apiVersion=2022-11-28#sync-a-fork-branch-with-the-upstream-repository HttpClient httpClient = new HttpClient(); + // API reference: https://docs.github.com/en/rest/branches/branches?apiVersion=2022-11-28#sync-a-fork-branch-with-the-upstream-repository + var url = $"https://api.github.com/repos/{forkedRepo.Owner.Login}/{forkedRepo.Name}/merge-upstream"; + // Headers httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", this.github.Credentials.Password); httpClient.DefaultRequestHeaders.Add("Accept", "application/vnd.github+json"); @@ -501,8 +503,21 @@ private async Task UpdateForkedRepoWithUpstreamCommits(Repository forkedRepo) JsonObject jsonObject = new JsonObject { { "branch", forkedRepo.DefaultBranch } }; var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json"); - var url = $"https://api.github.com/repos/{forkedRepo.Owner.Login}/{forkedRepo.Name}/merge-upstream"; var response = await httpClient.PostAsync(url, content); + + // 409 status code + if (response.StatusCode == System.Net.HttpStatusCode.Conflict) + { + throw new BranchMergeConflictException(); + } + + // 422 status code + if (response.StatusCode == System.Net.HttpStatusCode.UnprocessableEntity) + { + throw new GenericSyncFailureException(); + } + + // The API doesn't document another error code. If this fails, a generic HttpRequestException is thrown. response.EnsureSuccessStatusCode(); } }