diff --git a/src/Stack/Commands/Branch/AddBranchCommand.cs b/src/Stack/Commands/Branch/AddBranchCommand.cs index 8437f9f6..68542679 100644 --- a/src/Stack/Commands/Branch/AddBranchCommand.cs +++ b/src/Stack/Commands/Branch/AddBranchCommand.cs @@ -63,7 +63,7 @@ public override async Task Handle(AddBranchCommandInputs inputs, CancellationTok if (stacksForRemote.Count == 0) { - logger.LogInformation("No stacks found for current repository."); + logger.NoStacksForRepository(); return; } @@ -99,7 +99,7 @@ public override async Task Handle(AddBranchCommandInputs inputs, CancellationTok } } - logger.LogInformation($"Adding branch {branchName.Branch()} to stack {stack.Name.Stack()}"); + logger.AddingBranchToStack(branchName.Branch(), stack.Name.Stack()); if (sourceBranch is not null) { @@ -113,6 +113,15 @@ public override async Task Handle(AddBranchCommandInputs inputs, CancellationTok stackConfig.Save(stackData); - logger.LogInformation($"Branch added"); + logger.BranchAdded(branchName.Branch(), stack.Name.Stack()); } +} + +internal static partial class LoggerExtensionMethods +{ + [LoggerMessage(Level = LogLevel.Trace, Message = "Adding branch {Branch} to stack \"{Stack}\".")] + public static partial void AddingBranchToStack(this ILogger logger, string branch, string stack); + + [LoggerMessage(Level = LogLevel.Information, Message = "Branch {Branch} added to stack \"{Stack}\".")] + public static partial void BranchAdded(this ILogger logger, string branch, string stack); } \ No newline at end of file diff --git a/src/Stack/Commands/Branch/NewBranchCommand.cs b/src/Stack/Commands/Branch/NewBranchCommand.cs index 5d2d6530..90f2bb84 100644 --- a/src/Stack/Commands/Branch/NewBranchCommand.cs +++ b/src/Stack/Commands/Branch/NewBranchCommand.cs @@ -65,7 +65,7 @@ public override async Task Handle(NewBranchCommandInputs inputs, CancellationTok if (stacksForRemote.Count == 0) { - logger.LogInformation("No stacks found for current repository."); + logger.NoStacksForRepository(); return; } @@ -103,7 +103,7 @@ public override async Task Handle(NewBranchCommandInputs inputs, CancellationTok var sourceBranchName = sourceBranch?.Name ?? stack.SourceBranch; - logger.LogInformation($"Creating branch {branchName.Branch()} from {sourceBranchName.Branch()} in stack {stack.Name.Stack()}"); + logger.CreatingBranch(branchName.Branch(), sourceBranchName.Branch(), stack.Name.Stack()); gitClient.CreateNewBranch(branchName, sourceBranchName); @@ -119,18 +119,30 @@ public override async Task Handle(NewBranchCommandInputs inputs, CancellationTok stackConfig.Save(stackData); - logger.LogInformation($"Branch {branchName.Branch()} created."); + logger.BranchCreated(branchName.Branch()); try { - logger.LogInformation($"Pushing branch {branchName.Branch()} to remote repository"); + logger.PushingBranchToRemote(branchName.Branch()); gitClient.PushNewBranch(branchName); } catch (Exception) { - logger.LogWarning($"An error has occurred pushing branch {branchName.Branch()} to remote repository. Use {$"stack push --name \"{stack.Name}\"".Example()} to push the branch to the remote repository."); + logger.NewBranchPushWarning(branchName.Branch(), stack.Name); } gitClient.ChangeBranch(branchName); } +} + +internal static partial class LoggerExtensionMethods +{ + [LoggerMessage(Level = LogLevel.Information, Message = "Creating branch {Branch} from {SourceBranch} in stack \"{Stack}\"")] + public static partial void CreatingBranch(this ILogger logger, string branch, string sourceBranch, string stack); + + [LoggerMessage(Level = LogLevel.Information, Message = "Branch {Branch} created.")] + public static partial void BranchCreated(this ILogger logger, string branch); + + [LoggerMessage(Level = LogLevel.Information, Message = "Pushing branch {Branch} to remote repository")] + public static partial void PushingBranchToRemote(this ILogger logger, string branch); } \ No newline at end of file diff --git a/src/Stack/Commands/Branch/RemoveBranchCommand.cs b/src/Stack/Commands/Branch/RemoveBranchCommand.cs index 3a3f7925..d20b1806 100644 --- a/src/Stack/Commands/Branch/RemoveBranchCommand.cs +++ b/src/Stack/Commands/Branch/RemoveBranchCommand.cs @@ -108,7 +108,7 @@ await inputProvider.Select( stack.RemoveBranch(branchName, action); stackConfig.Save(stackData); - logger.LogInformation($"Branch {branchName.Branch()} removed from stack {stack.Name.Stack()}"); + logger.BranchRemovedFromStack(branchName.Branch(), stack.Name.Stack()); } } } @@ -122,3 +122,9 @@ public enum RemoveBranchChildAction RemoveChildren } +internal static partial class LoggerExtensionMethods +{ + [LoggerMessage(Level = LogLevel.Information, Message = "Branch {Branch} removed from stack \"{Stack}\"")] + public static partial void BranchRemovedFromStack(this ILogger logger, string branch, string stack); +} + diff --git a/src/Stack/Commands/Config/OpenConfigCommand.cs b/src/Stack/Commands/Config/OpenConfigCommand.cs index 6e813d91..76ecfcd2 100644 --- a/src/Stack/Commands/Config/OpenConfigCommand.cs +++ b/src/Stack/Commands/Config/OpenConfigCommand.cs @@ -30,7 +30,7 @@ protected override async Task Execute(ParseResult parseResult, CancellationToken if (!File.Exists(configPath)) { - Logger.LogInformation("No config file found."); + Logger.NoConfigFileFound(); return; } @@ -43,3 +43,9 @@ protected override async Task Execute(ParseResult parseResult, CancellationToken return; } } + +internal static partial class LoggerExtensionMethods +{ + [LoggerMessage(Level = LogLevel.Information, Message = "No config file found.")] + public static partial void NoConfigFileFound(this ILogger logger); +} diff --git a/src/Stack/Commands/Helpers/InputProviderExtensionMethods.cs b/src/Stack/Commands/Helpers/InputProviderExtensionMethods.cs index de0eaf17..8ca3008d 100644 --- a/src/Stack/Commands/Helpers/InputProviderExtensionMethods.cs +++ b/src/Stack/Commands/Helpers/InputProviderExtensionMethods.cs @@ -17,7 +17,7 @@ public static async Task Text( { if (presetValue is not null) { - logger.LogInformation($"{prompt} {presetValue}"); + logger.Answer(prompt, presetValue); return presetValue; } @@ -35,7 +35,7 @@ public static async Task Select( { var selection = presetValue ?? await inputProvider.Select(prompt, choices, cancellationToken); - logger.LogInformation($"{prompt} {selection}"); + logger.Answer(prompt, selection); return selection; } @@ -51,7 +51,7 @@ public static async Task MultiSelect( { var selection = presetValues ?? (await inputProvider.MultiSelect(prompt, choices, required, cancellationToken)).ToArray(); - logger.LogInformation($"{prompt} {string.Join(", ", selection)}"); + logger.Answer(prompt, string.Join(", ", selection)); return [.. selection]; } @@ -73,7 +73,7 @@ public static async Task MultiSelect( if (stack is not null) { - logger.LogInformation($"{Questions.SelectStack} {stack.Name}"); + logger.Answer(Questions.SelectStack, stack.Name); } return stack; @@ -113,7 +113,7 @@ void GetBranchNamesWithIndentation(Branch branch, List names, int level var branchSelection = (name ?? await inputProvider.Select(Questions.SelectParentBranch, [stack.SourceBranch, .. allBranchNamesWithLevel], cancellationToken)).Trim(); - logger.LogInformation($"{Questions.SelectParentBranch} {branchSelection}"); + logger.Answer(Questions.SelectParentBranch, branchSelection); return branchSelection; } diff --git a/src/Stack/Commands/Helpers/StackActions.cs b/src/Stack/Commands/Helpers/StackActions.cs index 48ed144c..4321da62 100644 --- a/src/Stack/Commands/Helpers/StackActions.cs +++ b/src/Stack/Commands/Helpers/StackActions.cs @@ -53,7 +53,7 @@ public void PullChanges(Config.Stack stack) if (shouldPullCurrent) { - logger.LogInformation($"Pulling changes for {currentBranch.Branch()} from remote"); + logger.PullingCurrentBranch(currentBranch.Branch()); gitClient.PullBranch(currentBranch); } @@ -61,13 +61,13 @@ public void PullChanges(Config.Stack stack) foreach (var branch in branchesInOtherWorktrees) { var worktreePath = branchStatus[branch].WorktreePath!; // not null due to filter - logger.LogInformation($"Pulling changes for {branch.Branch()} (worktree: {worktreePath}) from remote"); + logger.PullingWorktreeBranch(branch.Branch(), worktreePath); gitClient.PullBranchForWorktree(branch, worktreePath); } if (nonCurrentBranches.Length > 0) { - logger.LogInformation($"Fetching changes for {string.Join(", ", nonCurrentBranches.Select(b => b.Branch()))} from remote"); + logger.FetchingNonCurrentBranches(string.Join(", ", nonCurrentBranches.Select(b => b.Branch()))); gitClient.FetchBranchRefSpecs(nonCurrentBranches); } } @@ -86,7 +86,7 @@ public void PushChanges( foreach (var branch in branchesThatHaveNotBeenPushedToRemote) { - logger.LogInformation($"Pushing new branch {branch.Branch()} to remote"); + logger.PushingNewBranch(branch.Branch()); gitClient.PushNewBranch(branch); } @@ -103,8 +103,7 @@ public void PushChanges( foreach (var branches in branchGroupsToPush) { - logger.LogInformation($"Pushing changes for {string.Join(", ", branches.Select(b => b.Branch()))} to remote"); - + logger.PushingBranches(string.Join(", ", branches.Select(b => b.Branch()))); gitClient.PushBranches([.. branches], forceWithLease); } } @@ -137,7 +136,7 @@ private async Task UpdateStackUsingMerge( StackStatus status, CancellationToken cancellationToken) { - logger.LogInformation($"Updating stack {status.Name.Stack()} using merge..."); + logger.UpdatingStackUsingMerge(status.Name.Stack()); var allBranchLines = status.GetAllBranchLines(); @@ -162,14 +161,14 @@ private async Task UpdateBranchLineUsingMerge( } else { - logger.LogTrace($"Branch '{branch}' no longer exists on the remote repository or the associated pull request is no longer open. Skipping..."); + logger.TraceSkippingInactiveBranch(branch.Name); } } } private async Task MergeFromSourceBranch(string branch, string sourceBranchName, CancellationToken cancellationToken) { - logger.LogInformation($"Merging {sourceBranchName.Branch()} into {branch.Branch()}"); + logger.MergingBranch(sourceBranchName.Branch(), branch.Branch()); gitClient.ChangeBranch(branch); try @@ -202,7 +201,7 @@ private async Task UpdateStackUsingRebase( StackStatus status, CancellationToken cancellationToken) { - logger.LogInformation($"Updating stack {status.Name.Stack()} using rebase..."); + logger.UpdatingStackUsingRebase(status.Name.Stack()); var allBranchLines = status.GetAllBranchLines(); @@ -242,7 +241,7 @@ private async Task UpdateBranchLineUsingRebase(StackStatus status, List {string.Join(" -> ", branchLine.Select(b => b.Name.Branch()))}"); + logger.RebasingStackForBranchLine(status.Name.Stack(), status.SourceBranch.Name.Branch(), string.Join(" -> ", branchLine.Select(b => b.Name.Branch()))); BranchDetail? lowestActionBranch = null; foreach (var branch in branchLine) @@ -255,7 +254,7 @@ private async Task UpdateBranchLineUsingRebase(StackStatus status, List {BranchLine}")] + public static partial void RebasingStackForBranchLine(this ILogger logger, string stack, string sourceBranch, string branchLine); + + [LoggerMessage(Level = LogLevel.Debug, Message = "No active branches found for branch line.")] + public static partial void NoActiveBranchesFound(this ILogger logger); + + [LoggerMessage(Level = LogLevel.Information, Message = "Rebasing {Branch} onto {SourceBranch}")] + public static partial void RebasingBranchOnto(this ILogger logger, string branch, string sourceBranch); + + [LoggerMessage(Level = LogLevel.Information, Message = "Rebasing {Branch} onto new parent {NewParentBranch}")] + public static partial void RebasingBranchOntoNewParent(this ILogger logger, string branch, string newParentBranch); +} diff --git a/src/Stack/Commands/Helpers/StackHelpers.cs b/src/Stack/Commands/Helpers/StackHelpers.cs index ee67ac61..e42da1b5 100644 --- a/src/Stack/Commands/Helpers/StackHelpers.cs +++ b/src/Stack/Commands/Helpers/StackHelpers.cs @@ -142,7 +142,7 @@ static void EvaluateBranchStatusDetails(ILogger logger, IGitClient gitClient, IG { if (!branchStatuses.TryGetValue(stack.SourceBranch, out var sourceBranchStatus)) { - logger.LogWarning($"Source branch '{stack.SourceBranch}' does not exist locally or in the remote repository."); + logger.SourceBranchDoesNotExist(stack.SourceBranch.Branch()); continue; } @@ -441,41 +441,41 @@ public static void OutputBranchAndStackActions( var allBranches = status.GetAllBranches(); if (allBranches.All(branch => branch.CouldBeCleanedUp)) { - logger.LogInformation("All branches exist locally but are either not in the remote repository or the pull request associated with the branch is no longer open. This stack might be able to be deleted."); + logger.AllBranchesMightBeDeleted(); logger.NewLine(); - logger.LogInformation($"Run {$"stack delete --stack \"{status.Name}\"".Example()} to delete the stack if it's no longer needed."); + logger.RunDeleteStackCommand(status.Name); logger.NewLine(); } else if (allBranches.Any(branch => branch.CouldBeCleanedUp)) { - logger.LogInformation("Some branches exist locally but are either not in the remote repository or the pull request associated with the branch is no longer open."); + logger.SomeBranchesCouldBeCleanedUp(); logger.NewLine(); - logger.LogInformation($"Run {$"stack cleanup --stack \"{status.Name}\"".Example()} to clean up local branches."); + logger.RunCleanupStackCommand(status.Name); logger.NewLine(); } else if (allBranches.All(branch => !branch.Exists)) { - logger.LogInformation("No branches exist locally. This stack might be able to be deleted."); + logger.NoLocalBranchesStackMightBeDeleted(); logger.NewLine(); - logger.LogInformation($"Run {$"stack delete --stack \"{status.Name}\"".Example()} to delete the stack."); + logger.RunDeleteStackCommand(status.Name); logger.NewLine(); } if (allBranches.Any(branch => branch.Exists && (branch.RemoteTrackingBranch is null || branch.RemoteTrackingBranch.Ahead > 0))) { - logger.LogInformation("There are changes in local branches that have not been pushed to the remote repository."); + logger.ChangesNotPushedToRemote(); logger.NewLine(); - logger.LogInformation($"Run {$"stack push --stack \"{status.Name}\"".Example()} to push the changes to the remote repository."); + logger.RunPushStackCommand(status.Name); logger.NewLine(); } if (allBranches.Any(branch => branch.Exists && branch.RemoteTrackingBranch is not null && branch.RemoteTrackingBranch.Behind > 0)) { - logger.LogInformation("There are changes in source branches that have not been applied to the stack."); + logger.SourceChangesNotApplied(); logger.NewLine(); - logger.LogInformation($"Run {$"stack update --stack \"{status.Name}\"".Example()} to update the stack locally."); + logger.RunUpdateStackCommand(status.Name); logger.NewLine(); - logger.LogInformation($"Run {$"stack sync --stack \"{status.Name}\"".Example()} to sync the stack with the remote repository."); + logger.RunSyncStackCommand(status.Name); logger.NewLine(); } } @@ -523,7 +523,7 @@ public static async Task GetUpdateStrategy( [UpdateStrategy.Merge, UpdateStrategy.Rebase], cancellationToken); - logger.LogInformation($"{Questions.SelectUpdateStrategy} {strategy}"); + logger.Answer(Questions.SelectUpdateStrategy, strategy); return strategy; } @@ -538,11 +538,11 @@ public static string[] GetBranchesNeedingCleanup(Config.Stack stack, ILogger log public static void OutputBranchesNeedingCleanup(ILogger logger, string[] branches) { - logger.LogInformation("The following branches exist locally but are either not in the remote repository or the pull request associated with the branch is no longer open:"); + logger.BranchesToCleanupHeader(); foreach (var branch in branches) { - logger.LogInformation($" {branch.Branch()}"); + logger.BranchToCleanup(branch.Branch()); } } @@ -550,7 +550,7 @@ public static void CleanupBranches(IGitClient gitClient, ILogger logger, string[ { foreach (var branch in branches) { - logger.LogInformation($"Deleting local branch {branch.Branch()}"); + logger.DeletingLocalBranch(branch.Branch()); gitClient.DeleteLocalBranch(branch); } } @@ -605,7 +605,7 @@ void AppendBranchPullRequestsToList(Branch branch, int indentLevel) prBody = prBody.Remove(prListStart, prListEnd - prListStart + StackConstants.StackMarkerEnd.Length); prBody = prBody.Insert(prListStart, prBodyMarkdown); - logger.LogInformation($"Updating pull request {pullRequest.GetPullRequestDisplay()} with stack details"); + logger.UpdatingPullRequestWithStackDetails(pullRequest.GetPullRequestDisplay()); gitHubClient.EditPullRequest(pullRequest, prBody); } @@ -623,4 +623,52 @@ public enum UpdateStrategy { Merge, Rebase +} + +internal static partial class LoggerExtensionMethods +{ + [LoggerMessage(Level = LogLevel.Warning, Message = "Source branch {SourceBranch} does not exist locally or in the remote repository.")] + public static partial void SourceBranchDoesNotExist(this ILogger logger, string sourceBranch); + + [LoggerMessage(Level = LogLevel.Information, Message = "All branches exist locally but are either not in the remote repository or the pull request associated with the branch is no longer open. This stack might be able to be deleted.")] + public static partial void AllBranchesMightBeDeleted(this ILogger logger); + + [LoggerMessage(Level = LogLevel.Information, Message = "Run 'stack delete --stack \"{Stack}\"' to delete the stack if it's no longer needed.")] + public static partial void RunDeleteStackCommand(this ILogger logger, string stack); + + [LoggerMessage(Level = LogLevel.Information, Message = "Some branches exist locally but are either not in the remote repository or the pull request associated with the branch is no longer open.")] + public static partial void SomeBranchesCouldBeCleanedUp(this ILogger logger); + + [LoggerMessage(Level = LogLevel.Information, Message = "Run 'stack cleanup --stack \"{Stack}\"' to clean up local branches.")] + public static partial void RunCleanupStackCommand(this ILogger logger, string stack); + + [LoggerMessage(Level = LogLevel.Information, Message = "No branches exist locally. This stack might be able to be deleted.")] + public static partial void NoLocalBranchesStackMightBeDeleted(this ILogger logger); + + [LoggerMessage(Level = LogLevel.Information, Message = "There are changes in local branches that have not been pushed to the remote repository.")] + public static partial void ChangesNotPushedToRemote(this ILogger logger); + + [LoggerMessage(Level = LogLevel.Information, Message = "Run 'stack push --stack \"{Stack}\"' to push the changes to the remote repository.")] + public static partial void RunPushStackCommand(this ILogger logger, string stack); + + [LoggerMessage(Level = LogLevel.Information, Message = "There are changes in source branches that have not been applied to the stack.")] + public static partial void SourceChangesNotApplied(this ILogger logger); + + [LoggerMessage(Level = LogLevel.Information, Message = "Run 'stack update --stack \"{Stack}\"' to update the stack locally.")] + public static partial void RunUpdateStackCommand(this ILogger logger, string stack); + + [LoggerMessage(Level = LogLevel.Information, Message = "Run 'stack sync --stack \"{Stack}\"' to sync the stack with the remote repository.")] + public static partial void RunSyncStackCommand(this ILogger logger, string stack); + + [LoggerMessage(Level = LogLevel.Information, Message = "The following branches exist locally but are either not in the remote repository or the pull request associated with the branch is no longer open:")] + public static partial void BranchesToCleanupHeader(this ILogger logger); + + [LoggerMessage(Level = LogLevel.Information, Message = " {Branch}")] + public static partial void BranchToCleanup(this ILogger logger, string branch); + + [LoggerMessage(Level = LogLevel.Information, Message = "Deleting local branch {Branch}")] + public static partial void DeletingLocalBranch(this ILogger logger, string branch); + + [LoggerMessage(Level = LogLevel.Information, Message = "Updating pull request {PullRequest} with stack details")] + public static partial void UpdatingPullRequestWithStackDetails(this ILogger logger, string pullRequest); } \ No newline at end of file diff --git a/src/Stack/Commands/PullRequests/CreatePullRequestsCommand.cs b/src/Stack/Commands/PullRequests/CreatePullRequestsCommand.cs index 1e4dd95a..54784ad8 100644 --- a/src/Stack/Commands/PullRequests/CreatePullRequestsCommand.cs +++ b/src/Stack/Commands/PullRequests/CreatePullRequestsCommand.cs @@ -62,7 +62,7 @@ public override async Task Handle(CreatePullRequestsCommandInputs inputs, Cancel if (stacksForRemote.Count == 0) { - logger.LogInformation("No stacks found for current repository."); + logger.NoStacksForRepository(); return; } @@ -117,11 +117,11 @@ public override async Task Handle(CreatePullRequestsCommandInputs inputs, Cancel cancellationToken, action => $"{action.Branch} -> {action.BaseBranch}")).ToList(); - logger.LogInformation("Select branches to create pull requests for:"); + logger.Question(Questions.SelectPullRequestsToCreate); foreach (var action in selectedPullRequestActions) { - logger.LogInformation($" {action.Branch} -> {action.BaseBranch}"); + logger.PullRequestSelected(action.Branch, action.BaseBranch); } logger.NewLine(); @@ -167,7 +167,7 @@ public override async Task Handle(CreatePullRequestsCommandInputs inputs, Cancel } else { - logger.LogInformation("No new pull requests to create."); + logger.NoPullRequestsToCreate(); } } @@ -180,7 +180,7 @@ private static List CreatePullRequests( var pullRequests = new List(); foreach (var action in pullRequestCreateActions) { - logger.LogInformation($"Creating pull request for branch {action.HeadBranch.Branch()} to {action.BaseBranch.Branch()}"); + logger.CreatingPullRequest(action.HeadBranch.Branch(), action.BaseBranch.Branch()); var pullRequest = gitHubClient.CreatePullRequest( action.HeadBranch, action.BaseBranch, @@ -190,7 +190,7 @@ private static List CreatePullRequests( if (pullRequest is not null) { - logger.LogInformation($"Pull request {pullRequest.GetPullRequestDisplay()} created for branch {action.HeadBranch.Branch()} to {action.BaseBranch.Branch()}"); + logger.PullRequestCreated(pullRequest.GetPullRequestDisplay(), action.HeadBranch.Branch(), action.BaseBranch.Branch()); pullRequests.Add(pullRequest); } } @@ -239,14 +239,13 @@ private static async Task> GetPullRequestInformatio if (pullRequestTemplatePath is not null) { - logger.LogInformation($"Found pull request template in repository, this will be used as the default body for each pull request."); + logger.FoundPullRequestTemplate(pullRequestTemplatePath); } foreach (var action in pullRequestCreateActions) { logger.NewLine(); - var pullRequestHeader = $"New pull request from {action.Branch.Branch()} -> {action.BaseBranch.Branch()}"; - await displayProvider.DisplayHeader(pullRequestHeader, cancellationToken); + await displayProvider.DisplayHeader($"New pull request from {action.Branch.Branch()} -> {action.BaseBranch.Branch()}", cancellationToken); var title = inputProvider.Text(Questions.PullRequestTitle, cancellationToken).Result; var bodyFilePath = Path.Join(fileOperations.GetTempPath(), $"stack-pr-{Guid.NewGuid():N}.md"); @@ -285,3 +284,21 @@ public record PullRequestInformation( public record PullRequestCreateAction(string Branch, string BaseBranch); } + +internal static partial class LoggerExtensionMethods +{ + [LoggerMessage(Level = LogLevel.Information, Message = "Pull request selected: {HeadBranch} -> {BaseBranch}")] + public static partial void PullRequestSelected(this ILogger logger, string headBranch, string baseBranch); + + [LoggerMessage(Level = LogLevel.Information, Message = "Creating pull request for branch {HeadBranch} to {BaseBranch}")] + public static partial void CreatingPullRequest(this ILogger logger, string headBranch, string baseBranch); + + [LoggerMessage(Level = LogLevel.Information, Message = "Pull request \"{PullRequest}\" created for branch {HeadBranch} to {BaseBranch}")] + public static partial void PullRequestCreated(this ILogger logger, string pullRequest, string headBranch, string baseBranch); + + [LoggerMessage(Level = LogLevel.Information, Message = "No new pull requests to create.")] + public static partial void NoPullRequestsToCreate(this ILogger logger); + + [LoggerMessage(Level = LogLevel.Information, Message = "Found pull request template at \"{TemplatePath}\", this will be used as the default body for each pull request.")] + public static partial void FoundPullRequestTemplate(this ILogger logger, string templatePath); +} \ No newline at end of file diff --git a/src/Stack/Commands/PullRequests/OpenPullRequestsCommand.cs b/src/Stack/Commands/PullRequests/OpenPullRequestsCommand.cs index eda6c05f..cc65002e 100644 --- a/src/Stack/Commands/PullRequests/OpenPullRequestsCommand.cs +++ b/src/Stack/Commands/PullRequests/OpenPullRequestsCommand.cs @@ -57,7 +57,7 @@ public override async Task Handle(OpenPullRequestsCommandInputs inputs, Cancella if (stacksForRemote.Count == 0) { - logger.LogInformation("No stacks found for current repository."); + logger.NoStacksForRepository(); return; } @@ -83,7 +83,7 @@ public override async Task Handle(OpenPullRequestsCommandInputs inputs, Cancella if (pullRequestsInStack.Count == 0) { - logger.LogInformation($"No pull requests found for stack {stack.Name.Branch()}"); + logger.NoPullRequestsForStack(stack.Name.Stack()); return; } @@ -93,3 +93,9 @@ public override async Task Handle(OpenPullRequestsCommandInputs inputs, Cancella } } } + +internal static partial class LoggerExtensionMethods +{ + [LoggerMessage(Level = LogLevel.Information, Message = "No pull requests found for stack \"{Stack}\"")] + public static partial void NoPullRequestsForStack(this ILogger logger, string stack); +} diff --git a/src/Stack/Commands/Remote/PullStackCommand.cs b/src/Stack/Commands/Remote/PullStackCommand.cs index 691a982c..9a2bd71a 100644 --- a/src/Stack/Commands/Remote/PullStackCommand.cs +++ b/src/Stack/Commands/Remote/PullStackCommand.cs @@ -52,7 +52,7 @@ public override async Task Handle(PullStackCommandInputs inputs, CancellationTok if (stacksForRemote.Count == 0) { - logger.LogInformation("No stacks found for current repository."); + logger.NoStacksForRepository(); return; } diff --git a/src/Stack/Commands/Remote/PushStackCommand.cs b/src/Stack/Commands/Remote/PushStackCommand.cs index 320ce841..584d3c2f 100644 --- a/src/Stack/Commands/Remote/PushStackCommand.cs +++ b/src/Stack/Commands/Remote/PushStackCommand.cs @@ -65,7 +65,7 @@ public override async Task Handle(PushStackCommandInputs inputs, CancellationTok if (stacksForRemote.Count == 0) { - logger.LogInformation("No stacks found for current repository."); + logger.NoStacksForRepository(); return; } diff --git a/src/Stack/Commands/Remote/SyncStackCommand.cs b/src/Stack/Commands/Remote/SyncStackCommand.cs index b16bde60..80f8a3ef 100644 --- a/src/Stack/Commands/Remote/SyncStackCommand.cs +++ b/src/Stack/Commands/Remote/SyncStackCommand.cs @@ -111,7 +111,7 @@ public override async Task Handle(SyncStackCommandInputs inputs, CancellationTok if (inputs.Confirm || await inputProvider.Confirm(Questions.ConfirmSyncStack, cancellationToken)) { - logger.LogInformation($"Syncing stack {stack.Name.Stack()} with the remote repository"); + logger.SyncingStackWithRemote(stack.Name.Stack()); stackActions.PullChanges(stack); @@ -142,4 +142,10 @@ private void FetchChanges() gitClient.Fetch(true); }); } +} + +internal static partial class LoggerExtensionMethods +{ + [LoggerMessage(Level = LogLevel.Information, Message = "Syncing stack \"{Stack}\" with the remote repository")] + public static partial void SyncingStackWithRemote(this ILogger logger, string stack); } \ No newline at end of file diff --git a/src/Stack/Commands/Stack/CleanupStackCommand.cs b/src/Stack/Commands/Stack/CleanupStackCommand.cs index 406e429c..69eacdd0 100644 --- a/src/Stack/Commands/Stack/CleanupStackCommand.cs +++ b/src/Stack/Commands/Stack/CleanupStackCommand.cs @@ -70,7 +70,7 @@ public override async Task Handle(CleanupStackCommandInputs inputs, Cancellation if (branchesToCleanUp.Length == 0) { - logger.LogInformation("No branches to clean up"); + logger.NoBranchesToCleanUp(); return; } @@ -79,7 +79,16 @@ public override async Task Handle(CleanupStackCommandInputs inputs, Cancellation if (inputs.Confirm || await inputProvider.Confirm(Questions.ConfirmDeleteBranches, cancellationToken)) { StackHelpers.CleanupBranches(gitClient, logger, branchesToCleanUp); - logger.LogInformation($"Stack {stack.Name.Stack()} cleaned up"); + logger.StackCleanedUp(stack.Name.Stack()); } } } + +internal static partial class LoggerExtensionMethods +{ + [LoggerMessage(Level = LogLevel.Information, Message = "No branches to clean up")] + public static partial void NoBranchesToCleanUp(this ILogger logger); + + [LoggerMessage(Level = LogLevel.Information, Message = "Stack \"{Stack}\" cleaned up")] + public static partial void StackCleanedUp(this ILogger logger, string stack); +} diff --git a/src/Stack/Commands/Stack/DeleteStackCommand.cs b/src/Stack/Commands/Stack/DeleteStackCommand.cs index da201d66..9ed0ff42 100644 --- a/src/Stack/Commands/Stack/DeleteStackCommand.cs +++ b/src/Stack/Commands/Stack/DeleteStackCommand.cs @@ -86,7 +86,13 @@ public override async Task Handle(DeleteStackCommandInputs inputs, CancellationT stackData.Stacks.Remove(stack); stackConfig.Save(stackData); - logger.LogInformation($"Stack {stack.Name.Stack()} deleted"); + logger.StackDeleted(stack.Name.Stack()); } } } + +internal static partial class LoggerExtensionMethods +{ + [LoggerMessage(Level = LogLevel.Information, Message = "Stack \"{Stack}\" deleted")] + public static partial void StackDeleted(this ILogger logger, string stack); +} diff --git a/src/Stack/Commands/Stack/ListStacksCommand.cs b/src/Stack/Commands/Stack/ListStacksCommand.cs index 405beca0..a6a47cc8 100644 --- a/src/Stack/Commands/Stack/ListStacksCommand.cs +++ b/src/Stack/Commands/Stack/ListStacksCommand.cs @@ -41,7 +41,7 @@ protected override async Task WriteDefaultOutput(ListStacksCommandResponse respo { if (response.Stacks.Count == 0) { - Logger.LogInformation("No stacks found for current repository."); + Logger.NoStacksForRepository(); return; } diff --git a/src/Stack/Commands/Stack/NewStackCommand.cs b/src/Stack/Commands/Stack/NewStackCommand.cs index 3d8134d5..6d0fc634 100644 --- a/src/Stack/Commands/Stack/NewStackCommand.cs +++ b/src/Stack/Commands/Stack/NewStackCommand.cs @@ -107,7 +107,7 @@ public override async Task Handle(NewStackCommandInputs inputs, CancellationToke cancellationToken, action => action.Humanize()); - logger.LogInformation($"{Questions.AddOrCreateBranch} {selectedBranchAction.Humanize()}"); + logger.Answer(Questions.AddOrCreateBranch, selectedBranchAction.Humanize()); branchAction = selectedBranchAction; } @@ -119,12 +119,12 @@ public override async Task Handle(NewStackCommandInputs inputs, CancellationToke try { - logger.LogInformation($"Pushing branch {branchName.Branch()} to remote repository"); + logger.PushingBranch(branchName.Branch()); gitClient.PushNewBranch(branchName); } catch (Exception) { - logger.LogWarning($"An error has occurred pushing branch {branchName.Branch()} to remote repository. Use {$"stack push --name \"{name}\"".Example()} to push the branch to the remote repository."); + logger.NewBranchPushWarning(branchName.Branch(), name); } } else if (branchAction == BranchAction.Add) @@ -149,23 +149,35 @@ public override async Task Handle(NewStackCommandInputs inputs, CancellationToke } catch (Exception ex) { - logger.LogWarning($"An error has occurred changing to branch {branchName.Branch()}. Use {$"stack switch --branch \"{branchName}\"".Example()} to switch to the branch. Error: {ex.Message}"); + logger.ChangeBranchWarning(branchName.Branch(), ex.Message); } } if (branchAction is BranchAction.Create) { - logger.LogInformation($"Stack {name.Stack()} created from source branch {sourceBranch.Branch()} with new branch {branchName!.Branch()}"); + logger.NewStackWithNewBranch(name.Stack(), sourceBranch.Branch(), branchName!.Branch()); } else if (branchAction is BranchAction.Add) { - logger.LogInformation($"Stack {name.Stack()} created from source branch {sourceBranch.Branch()} with existing branch {branchName!.Branch()}"); + logger.NewStackWithExistingBranch(name.Stack(), sourceBranch.Branch(), branchName!.Branch()); } else { - logger.LogInformation($"Stack {name.Stack()} created from source branch {sourceBranch.Branch()}"); + logger.NewStackWithNoBranch(name.Stack(), sourceBranch.Branch()); } } } +internal static partial class LoggerExtensionMethods +{ + [LoggerMessage(Level = LogLevel.Information, Message = "Stack \"{Stack}\" created from source branch {SourceBranch} with new branch {Branch}.")] + public static partial void NewStackWithNewBranch(this ILogger logger, string stack, string sourceBranch, string branch); + + [LoggerMessage(Level = LogLevel.Information, Message = "Stack \"{Stack}\" created from source branch {SourceBranch} with existing branch {Branch}.")] + public static partial void NewStackWithExistingBranch(this ILogger logger, string stack, string sourceBranch, string branch); + + [LoggerMessage(Level = LogLevel.Information, Message = "Stack \"{Stack}\" created from source branch {SourceBranch}.")] + public static partial void NewStackWithNoBranch(this ILogger logger, string stack, string sourceBranch); +} + diff --git a/src/Stack/Git/GitClient.cs b/src/Stack/Git/GitClient.cs index 531f4f61..ddab1fa4 100644 --- a/src/Stack/Git/GitClient.cs +++ b/src/Stack/Git/GitClient.cs @@ -288,7 +288,13 @@ private void ExecuteGitCommand( // changes to the Git repository as the output might be important. // In verbose mode we would have already written the output // of the command so don't write it again. - logger.LogDebug(Markup.Escape(output)); + logger.DebugCommandOutput(Markup.Escape(output)); } } } + +internal static partial class LoggerExtensionMethods +{ + [LoggerMessage(Level = LogLevel.Debug, Message = "{Output}")] + public static partial void DebugCommandOutput(this ILogger logger, string output); +} diff --git a/src/Stack/Git/ProcessHelpers.cs b/src/Stack/Git/ProcessHelpers.cs index 0789a945..76cf96cc 100644 --- a/src/Stack/Git/ProcessHelpers.cs +++ b/src/Stack/Git/ProcessHelpers.cs @@ -16,7 +16,7 @@ public static string ExecuteProcessAndReturnOutput( bool captureStandardError = false, Func? exceptionHandler = null) { - logger.LogTrace($"{fileName} {command}"); + logger.TraceCommand(fileName, command); var infoBuilder = new StringBuilder(); var errorBuilder = new StringBuilder(); @@ -53,7 +53,7 @@ public static string ExecuteProcessAndReturnOutput( if (result != 0) { - logger.LogTrace($"Failed to execute command: {fileName} {command}. Exit code: {result}. Error: {errorBuilder}."); + logger.TraceFailedCommand(fileName, command, result, errorBuilder.ToString()); if (exceptionHandler != null) { @@ -71,7 +71,7 @@ public static string ExecuteProcessAndReturnOutput( if (infoBuilder.Length > 0) { - logger.LogTrace(Markup.Escape(infoBuilder.ToString())); + logger.TraceInfoOutput(Markup.Escape(infoBuilder.ToString())); } var output = infoBuilder.ToString(); @@ -93,4 +93,16 @@ public ProcessException(string message, int exitCode) : base(message) { ExitCode = exitCode; } +} + +internal static partial class LoggerExtensionMethods +{ + [LoggerMessage(Level = LogLevel.Trace, Message = "{FileName} {Command}")] + public static partial void TraceCommand(this ILogger logger, string fileName, string command); + + [LoggerMessage(Level = LogLevel.Trace, Message = "Failed to execute command: {FileName} {Command}. Exit code: {ExitCode}. Error: {Error}.")] + public static partial void TraceFailedCommand(this ILogger logger, string fileName, string command, int exitCode, string error); + + [LoggerMessage(Level = LogLevel.Trace, Message = "{Info}")] + public static partial void TraceInfoOutput(this ILogger logger, string info); } \ No newline at end of file diff --git a/src/Stack/Infrastructure/Commands/Command.cs b/src/Stack/Infrastructure/Commands/Command.cs index 6320cfb6..5815f8d9 100644 --- a/src/Stack/Infrastructure/Commands/Command.cs +++ b/src/Stack/Infrastructure/Commands/Command.cs @@ -42,7 +42,7 @@ public Command( } catch (ProcessException processException) { - Logger.LogError(processException.Message); + Logger.ErrorMessage(processException.Message); return processException.ExitCode; } catch (OperationCanceledException) @@ -51,7 +51,7 @@ public Command( } catch (Exception ex) { - Logger.LogError(ex.Message); + Logger.ErrorMessage(ex.Message); return 1; } }); @@ -61,3 +61,9 @@ public Command( protected abstract Task Execute(ParseResult parseResult, CancellationToken cancellationToken); } + +internal static partial class LoggerExtensionMethods +{ + [LoggerMessage(Level = LogLevel.Error, Message = "{Message}")] + public static partial void ErrorMessage(this ILogger logger, string message); +} diff --git a/src/Stack/Infrastructure/LoggerExtensionMethods.cs b/src/Stack/Infrastructure/LoggerExtensionMethods.cs index 973252d5..264f60a3 100644 --- a/src/Stack/Infrastructure/LoggerExtensionMethods.cs +++ b/src/Stack/Infrastructure/LoggerExtensionMethods.cs @@ -1,8 +1,28 @@ +using System.Diagnostics.CodeAnalysis; using Microsoft.Extensions.Logging; namespace Stack.Infrastructure; -public static class LoggerExtensionMethods +public static partial class LoggerExtensionMethods { public static void NewLine(this ILogger logger) => logger.LogInformation(string.Empty); + + [LoggerMessage(Level = LogLevel.Information, Message = "{Question}")] + public static partial void Question(this ILogger logger, string question); + + [LoggerMessage(Level = LogLevel.Information, Message = "{Question} {Answer}")] + [SuppressMessage("LoggerMessage", "LOGGEN036:A value being logged doesn't have an effective way to be converted into a string", Justification = "Usage is only with objects that have ToString() methods")] + public static partial void Answer(this ILogger logger, string question, object answer); + + [LoggerMessage(Level = LogLevel.Information, Message = "No stacks found for current repository.")] + public static partial void NoStacksForRepository(this ILogger logger); + + [LoggerMessage(Level = LogLevel.Information, Message = "Pushing branch {Branch} to remote repository.")] + public static partial void PushingBranch(this ILogger logger, string branch); + + [LoggerMessage(Level = LogLevel.Warning, Message = "An error has occurred pushing branch {Branch} to remote repository. Run 'stack push --name \"{Stack}\"' to push the branch to the remote repository.")] + public static partial void NewBranchPushWarning(this ILogger logger, string branch, string stack); + + [LoggerMessage(Level = LogLevel.Warning, Message = "An error has occurred changing to branch {Branch}. Run 'stack switch --branch \"{Branch}\"' to switch to the branch. Error: {ErrorMessage}.")] + public static partial void ChangeBranchWarning(this ILogger logger, string branch, string errorMessage); } diff --git a/src/Stack/Infrastructure/OutputStyleExtensionMethods.cs b/src/Stack/Infrastructure/OutputStyleExtensionMethods.cs index b59bd84d..bae90f57 100644 --- a/src/Stack/Infrastructure/OutputStyleExtensionMethods.cs +++ b/src/Stack/Infrastructure/OutputStyleExtensionMethods.cs @@ -7,6 +7,5 @@ public static class OutputStyleExtensionMethods public static string Stack(this string name) => $"[{Color.Yellow}]{name}[/]"; public static string Branch(this string name) => $"[{Color.Blue}]{name}[/]"; public static string Muted(this string name) => $"[{Color.Grey}]{name}[/]"; - public static string Example(this string name) => $"[{Color.Aqua}]{name}[/]"; public static string Highlighted(this string name) => $"[{Color.Green}]{name}[/]"; } \ No newline at end of file