diff --git a/src/Stack.Tests/Commands/Helpers/StackActionsTests.cs b/src/Stack.Tests/Commands/Helpers/StackActionsTests.cs new file mode 100644 index 00000000..11e99565 --- /dev/null +++ b/src/Stack.Tests/Commands/Helpers/StackActionsTests.cs @@ -0,0 +1,84 @@ +using FluentAssertions; +using NSubstitute; +using Stack.Commands; +using Stack.Commands.Helpers; +using Stack.Git; +using Stack.Infrastructure; +using Xunit.Abstractions; + +namespace Stack.Tests.Helpers; + +public class StackActionsTests(ITestOutputHelper testOutputHelper) +{ + [Fact] + public void PullChanges_WhenSomeBranchesHaveChanges_AndOthersDoNot_OnlyPullsChangesForBranchesThatNeedIt() + { + // Arrange + var sourceBranch = Some.BranchName(); + var branchWithRemoteChanges = Some.BranchName(); + var branchWithoutRemoteChanges = Some.BranchName(); + + var gitClient = Substitute.For(); + + var branchStatus = new Dictionary + { + { sourceBranch, new GitBranchStatus(sourceBranch, $"origin/{sourceBranch}", true, false, 0, 0, new Commit(Some.Sha(), Some.Name())) }, + { branchWithRemoteChanges, new GitBranchStatus(branchWithRemoteChanges, $"origin/{branchWithRemoteChanges}", true, false, 0, 3, new Commit(Some.Sha(), Some.Name())) }, + { branchWithoutRemoteChanges, new GitBranchStatus(branchWithoutRemoteChanges, $"origin/{branchWithoutRemoteChanges}", true, false, 0, 0, new Commit(Some.Sha(), Some.Name())) } + }; + + gitClient.GetBranchStatuses(Arg.Any()).Returns(branchStatus); + + var stack = new TestStackBuilder() + .WithSourceBranch(sourceBranch) + .WithBranch(b => b.WithName(branchWithRemoteChanges)) + .WithBranch(b => b.WithName(branchWithoutRemoteChanges)) + .Build(); + + var stackActions = new StackActions(gitClient, new TestLogger(testOutputHelper)); + + // Act + stackActions.PullChanges(stack); + + // Assert + gitClient.DidNotReceive().PullBranch(sourceBranch); + gitClient.Received().PullBranch(branchWithRemoteChanges); + gitClient.DidNotReceive().PullBranch(branchWithoutRemoteChanges); + } + + [Fact] + public void PullChanges_WhenSomeBranchesDoNotExistInRemote_OnlyPullsBranchesThatExistInRemote() + { + // Arrange + var sourceBranch = Some.BranchName(); + var branchThatExistsInRemote = Some.BranchName(); + var branchThatDoesNotExistInRemote = Some.BranchName(); + + var gitClient = Substitute.For(); + + var branchStatus = new Dictionary + { + { sourceBranch, new GitBranchStatus(sourceBranch, $"origin/{sourceBranch}", true, false, 0, 0, new Commit(Some.Sha(), Some.Name())) }, + { branchThatExistsInRemote, new GitBranchStatus(branchThatExistsInRemote, $"origin/{branchThatExistsInRemote}", true, false, 0, 2, new Commit(Some.Sha(), Some.Name())) }, + { branchThatDoesNotExistInRemote, new GitBranchStatus(branchThatDoesNotExistInRemote, $"origin/{branchThatDoesNotExistInRemote}", false, false, 0, 0, new Commit(Some.Sha(), Some.Name())) } + }; + + gitClient.GetBranchStatuses(Arg.Any()).Returns(branchStatus); + + var stack = new TestStackBuilder() + .WithSourceBranch(sourceBranch) + .WithBranch(b => b.WithName(branchThatExistsInRemote)) + .WithBranch(b => b.WithName(branchThatDoesNotExistInRemote)) + .Build(); + + var stackActions = new StackActions(gitClient, new TestLogger(testOutputHelper)); + + // Act + stackActions.PullChanges(stack); + + // Assert + gitClient.DidNotReceive().PullBranch(sourceBranch); + gitClient.Received().PullBranch(branchThatExistsInRemote); + gitClient.DidNotReceive().PullBranch(branchThatDoesNotExistInRemote); + } +} \ No newline at end of file diff --git a/src/Stack.Tests/Commands/Helpers/StackHelpersTests.cs b/src/Stack.Tests/Commands/Helpers/StackHelpersTests.cs index 3aee6f6c..fcf6994d 100644 --- a/src/Stack.Tests/Commands/Helpers/StackHelpersTests.cs +++ b/src/Stack.Tests/Commands/Helpers/StackHelpersTests.cs @@ -472,38 +472,4 @@ public void PushChanges_WhenSomeLocalBranchesAreAhead_OnlyPushesChangesForBranch // Assert branchesPushedToRemote.ToArray().Should().BeEquivalentTo([branchAheadOfRemote]); } - - [Fact] - public void PullChanges_WhenSomeBranchesHaveChanges_AndOthersDoNot_OnlyPullsChangesForBranchesThatNeedIt() - { - // Arrange - var sourceBranch = Some.BranchName(); - var branchWithRemoteChanges = Some.BranchName(); - var branchWithoutRemoteChanges = Some.BranchName(); - - var gitClient = Substitute.For(); - - var branchStatus = new Dictionary - { - { sourceBranch, new GitBranchStatus(sourceBranch, $"origin/{sourceBranch}", true, false, 0, 0, new Commit(Some.Sha(), Some.Name())) }, - { branchWithRemoteChanges, new GitBranchStatus(branchWithRemoteChanges, $"origin/{branchWithRemoteChanges}", true, false, 0, 3, new Commit(Some.Sha(), Some.Name())) }, - { branchWithoutRemoteChanges, new GitBranchStatus(branchWithoutRemoteChanges, $"origin/{branchWithoutRemoteChanges}", true, false, 0, 0, new Commit(Some.Sha(), Some.Name())) } - }; - - gitClient.GetBranchStatuses(Arg.Any()).Returns(branchStatus); - - var stack = new TestStackBuilder() - .WithSourceBranch(sourceBranch) - .WithBranch(b => b.WithName(branchWithRemoteChanges)) - .WithBranch(b => b.WithName(branchWithoutRemoteChanges)) - .Build(); - - // Act - StackHelpers.PullChanges(stack, gitClient, new TestLogger(testOutputHelper)); - - // Assert - gitClient.DidNotReceive().PullBranch(sourceBranch); - gitClient.Received().PullBranch(branchWithRemoteChanges); - gitClient.DidNotReceive().PullBranch(branchWithoutRemoteChanges); - } } \ No newline at end of file diff --git a/src/Stack.Tests/Commands/Remote/PullStackCommandHandlerTests.cs b/src/Stack.Tests/Commands/Remote/PullStackCommandHandlerTests.cs index 2bb9b37f..295e8f0b 100644 --- a/src/Stack.Tests/Commands/Remote/PullStackCommandHandlerTests.cs +++ b/src/Stack.Tests/Commands/Remote/PullStackCommandHandlerTests.cs @@ -13,44 +13,33 @@ namespace Stack.Tests.Commands.Remote; public class PullStackCommandHandlerTests(ITestOutputHelper testOutputHelper) { [Fact] - public async Task WhenChangesExistOnTheRemote_TheyArePulledDownToTheLocalBranch() + public async Task WhenNoStackNameIsProvided_AsksForStack_PullsChangesForTheCorrectStack() { // Arrange var sourceBranch = Some.BranchName(); var branch1 = Some.BranchName(); var branch2 = Some.BranchName(); - using var repo = new TestGitRepositoryBuilder() - .WithBranch(builder => builder.WithName(sourceBranch).PushToRemote()) - .WithBranch(builder => builder.WithName(branch1).FromSourceBranch(sourceBranch).WithNumberOfEmptyCommits(10).PushToRemote()) - .WithBranch(builder => builder.WithName(branch2).FromSourceBranch(branch1).WithNumberOfEmptyCommits(1).PushToRemote()) - .WithNumberOfEmptyCommitsOnRemoteTrackingBranchOf(sourceBranch, 5, b => b.PushToRemote()) - .WithNumberOfEmptyCommitsOnRemoteTrackingBranchOf(branch1, 3, b => b.PushToRemote()) - .Build(); - - var tipOfRemoteSourceBranch = repo.GetTipOfRemoteBranch(sourceBranch); - var tipOfRemoteBranch1 = repo.GetTipOfRemoteBranch(branch1); - - repo.GetCommitsReachableFromBranch(sourceBranch).Should().NotContain(tipOfRemoteSourceBranch); - repo.GetCommitsReachableFromBranch(branch1).Should().NotContain(tipOfRemoteBranch1); + var remoteUri = Some.HttpsUri().ToString(); var stackConfig = new TestStackConfigBuilder() .WithStack(stack => stack .WithName("Stack1") - .WithRemoteUri(repo.RemoteUri) + .WithRemoteUri(remoteUri) .WithSourceBranch(sourceBranch) .WithBranch(stackBranch => stackBranch.WithName(branch1).WithChildBranch(child => child.WithName(branch2)))) .WithStack(stack => stack .WithName("Stack2") - .WithRemoteUri(repo.RemoteUri) + .WithRemoteUri(remoteUri) .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); var logger = new TestLogger(testOutputHelper); - var gitClient = new GitClient(logger, repo.GitClientSettings); - var handler = new PullStackCommandHandler(inputProvider, logger, gitClient, stackConfig); - - gitClient.ChangeBranch(branch1); + var gitClient = Substitute.For(); + var stackActions = Substitute.For(); + var handler = new PullStackCommandHandler(inputProvider, logger, gitClient, stackConfig, stackActions); + gitClient.GetRemoteUri().Returns(remoteUri); + gitClient.GetCurrentBranch().Returns(branch1); inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); @@ -58,57 +47,48 @@ public async Task WhenChangesExistOnTheRemote_TheyArePulledDownToTheLocalBranch( await handler.Handle(new PullStackCommandInputs(null)); // Assert - repo.GetCommitsReachableFromBranch(sourceBranch).Should().Contain(tipOfRemoteSourceBranch); - repo.GetCommitsReachableFromBranch(branch1).Should().Contain(tipOfRemoteBranch1); + var expectedStack = stackConfig.Load().Stacks.First(s => s.Name == "Stack1"); + stackActions.Received(1).PullChanges(expectedStack); + gitClient.Received(1).ChangeBranch(branch1); } [Fact] - public async Task WhenNameIsProvided_DoesNotAskForName_PullsChangesFromRemoteForBranchesInStack() + public async Task WhenNameIsProvided_DoesNotAskForName_PullsChangesForTheCorrectStack() { // Arrange var sourceBranch = Some.BranchName(); var branch1 = Some.BranchName(); var branch2 = Some.BranchName(); - using var repo = new TestGitRepositoryBuilder() - .WithBranch(builder => builder.WithName(sourceBranch).PushToRemote()) - .WithBranch(builder => builder.WithName(branch1).FromSourceBranch(sourceBranch).WithNumberOfEmptyCommits(10).PushToRemote()) - .WithBranch(builder => builder.WithName(branch2).FromSourceBranch(branch1).WithNumberOfEmptyCommits(1).PushToRemote()) - .WithNumberOfEmptyCommitsOnRemoteTrackingBranchOf(sourceBranch, 5, b => b.PushToRemote()) - .WithNumberOfEmptyCommitsOnRemoteTrackingBranchOf(branch1, 3, b => b.PushToRemote()) - .Build(); - - var tipOfRemoteSourceBranch = repo.GetTipOfRemoteBranch(sourceBranch); - var tipOfRemoteBranch1 = repo.GetTipOfRemoteBranch(branch1); - - repo.GetCommitsReachableFromBranch(sourceBranch).Should().NotContain(tipOfRemoteSourceBranch); - repo.GetCommitsReachableFromBranch(branch1).Should().NotContain(tipOfRemoteBranch1); + var remoteUri = Some.HttpsUri().ToString(); var stackConfig = new TestStackConfigBuilder() .WithStack(stack => stack .WithName("Stack1") - .WithRemoteUri(repo.RemoteUri) + .WithRemoteUri(remoteUri) .WithSourceBranch(sourceBranch) .WithBranch(stackBranch => stackBranch.WithName(branch1)) .WithBranch(stackBranch => stackBranch.WithName(branch2))) .WithStack(stack => stack .WithName("Stack2") - .WithRemoteUri(repo.RemoteUri) + .WithRemoteUri(remoteUri) .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); var logger = new TestLogger(testOutputHelper); - var gitClient = new GitClient(logger, repo.GitClientSettings); - var handler = new PullStackCommandHandler(inputProvider, logger, gitClient, stackConfig); - - gitClient.ChangeBranch(branch1); + var gitClient = Substitute.For(); + var stackActions = Substitute.For(); + var handler = new PullStackCommandHandler(inputProvider, logger, gitClient, stackConfig, stackActions); + gitClient.GetRemoteUri().Returns(remoteUri); + gitClient.GetCurrentBranch().Returns(branch1); // Act await handler.Handle(new PullStackCommandInputs("Stack1")); // Assert - repo.GetCommitsReachableFromBranch(sourceBranch).Should().Contain(tipOfRemoteSourceBranch); - repo.GetCommitsReachableFromBranch(branch1).Should().Contain(tipOfRemoteBranch1); + var expectedStack = stackConfig.Load().Stacks.First(s => s.Name == "Stack1"); + stackActions.Received(1).PullChanges(expectedStack); + gitClient.Received(1).ChangeBranch(branch1); inputProvider.DidNotReceive().Select(Questions.SelectStack, Arg.Any()); } @@ -119,41 +99,28 @@ public async Task WhenNameIsProvided_ButStackDoesNotExist_Throws() var sourceBranch = Some.BranchName(); var branch1 = Some.BranchName(); var branch2 = Some.BranchName(); - using var repo = new TestGitRepositoryBuilder() - .WithBranch(builder => builder.WithName(sourceBranch).PushToRemote()) - .WithBranch(builder => builder.WithName(branch1).FromSourceBranch(sourceBranch).WithNumberOfEmptyCommits(10).PushToRemote()) - .WithBranch(builder => builder.WithName(branch2).FromSourceBranch(branch1).WithNumberOfEmptyCommits(1).PushToRemote()) - .WithNumberOfEmptyCommitsOnRemoteTrackingBranchOf(sourceBranch, 5, b => b.PushToRemote()) - .WithNumberOfEmptyCommitsOnRemoteTrackingBranchOf(branch1, 3, b => b.PushToRemote()) - .Build(); - - var tipOfRemoteSourceBranch = repo.GetTipOfRemoteBranch(sourceBranch); - var tipOfRemoteBranch1 = repo.GetTipOfRemoteBranch(branch1); - - repo.GetCommitsReachableFromBranch(sourceBranch).Should().NotContain(tipOfRemoteSourceBranch); - repo.GetCommitsReachableFromBranch(branch1).Should().NotContain(tipOfRemoteBranch1); + var remoteUri = Some.HttpsUri().ToString(); var stackConfig = new TestStackConfigBuilder() .WithStack(stack => stack .WithName("Stack1") - .WithRemoteUri(repo.RemoteUri) + .WithRemoteUri(remoteUri) .WithSourceBranch(sourceBranch) .WithBranch(stackBranch => stackBranch.WithName(branch1)) .WithBranch(stackBranch => stackBranch.WithName(branch2))) .WithStack(stack => stack .WithName("Stack2") - .WithRemoteUri(repo.RemoteUri) + .WithRemoteUri(remoteUri) .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); var logger = new TestLogger(testOutputHelper); - var gitClient = new GitClient(logger, repo.GitClientSettings); - var handler = new PullStackCommandHandler(inputProvider, logger, gitClient, stackConfig); - - gitClient.ChangeBranch(branch1); + var gitClient = Substitute.For(); + var stackActions = Substitute.For(); + var handler = new PullStackCommandHandler(inputProvider, logger, gitClient, stackConfig, stackActions); - - inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); + gitClient.GetRemoteUri().Returns(remoteUri); + gitClient.GetCurrentBranch().Returns(branch1); // Act and assert var invalidStackName = Some.Name(); @@ -161,101 +128,4 @@ await handler.Invoking(async h => await h.Handle(new PullStackCommandInputs(inva .Should().ThrowAsync() .WithMessage($"Stack '{invalidStackName}' not found."); } - - [Fact] - public async Task WhenChangesExistOnTheRemote_ForABranchThatIsNotInTheStack_TheyAreNotPulledDownToTheLocalBranch() - { - // Arrange - var sourceBranch = Some.BranchName(); - var branch1 = Some.BranchName(); - var branch2 = Some.BranchName(); - using var repo = new TestGitRepositoryBuilder() - .WithBranch(builder => builder.WithName(sourceBranch).PushToRemote()) - .WithBranch(builder => builder.WithName(branch1).FromSourceBranch(sourceBranch).WithNumberOfEmptyCommits(10).PushToRemote()) - .WithBranch(builder => builder.WithName(branch2).FromSourceBranch(branch1).WithNumberOfEmptyCommits(1).PushToRemote()) - .WithNumberOfEmptyCommitsOnRemoteTrackingBranchOf(sourceBranch, 5, b => b.PushToRemote()) - .WithNumberOfEmptyCommitsOnRemoteTrackingBranchOf(branch1, 3, b => b.PushToRemote()) - .WithNumberOfEmptyCommitsOnRemoteTrackingBranchOf(branch2, 3, b => b.PushToRemote()) - .Build(); - - var tipOfRemoteBranch2 = repo.GetTipOfRemoteBranch(branch2); - - var stackConfig = new TestStackConfigBuilder() - .WithStack(stack => stack - .WithName("Stack1") - .WithRemoteUri(repo.RemoteUri) - .WithSourceBranch(sourceBranch) - .WithBranch(stackBranch => stackBranch.WithName(branch1))) - .WithStack(stack => stack - .WithName("Stack2") - .WithRemoteUri(repo.RemoteUri) - .WithSourceBranch(sourceBranch) - .WithBranch(stackBranch => stackBranch.WithName(branch2))) - .Build(); - var inputProvider = Substitute.For(); - var logger = new TestLogger(testOutputHelper); - var gitClient = new GitClient(logger, repo.GitClientSettings); - var handler = new PullStackCommandHandler(inputProvider, logger, gitClient, stackConfig); - - gitClient.ChangeBranch(branch1); - - - inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); - - // Act - await handler.Handle(new PullStackCommandInputs(null)); - - // Assert - repo.GetCommitsReachableFromBranch(branch2).Should().NotContain(tipOfRemoteBranch2); - } - - [Fact] - public async Task WhenABranchDoesNotExistLocallyOrInTheRemote_ItIsNotPulled() - { - // Arrange - var sourceBranch = Some.BranchName(); - var branch1 = Some.BranchName(); - var branch2 = Some.BranchName(); - using var repo = new TestGitRepositoryBuilder() - .WithBranch(builder => builder.WithName(sourceBranch).PushToRemote()) - .WithBranch(builder => builder.WithName(branch2).FromSourceBranch(sourceBranch).WithNumberOfEmptyCommits(1).PushToRemote()) - .WithNumberOfEmptyCommitsOnRemoteTrackingBranchOf(sourceBranch, 5, b => b.PushToRemote()) - .WithNumberOfEmptyCommitsOnRemoteTrackingBranchOf(branch2, 3, b => b.PushToRemote()) - .Build(); - - var tipOfRemoteSourceBranch = repo.GetTipOfRemoteBranch(sourceBranch); - var tipOfRemoteBranch2 = repo.GetTipOfRemoteBranch(branch2); - - repo.GetCommitsReachableFromBranch(sourceBranch).Should().NotContain(tipOfRemoteSourceBranch); - repo.GetCommitsReachableFromBranch(branch2).Should().NotContain(tipOfRemoteBranch2); - - var stackConfig = new TestStackConfigBuilder() - .WithStack(stack => stack - .WithName("Stack1") - .WithRemoteUri(repo.RemoteUri) - .WithSourceBranch(sourceBranch) - .WithBranch(stackBranch => stackBranch.WithName(branch1)) - .WithBranch(stackBranch => stackBranch.WithName(branch2))) - .WithStack(stack => stack - .WithName("Stack2") - .WithRemoteUri(repo.RemoteUri) - .WithSourceBranch(sourceBranch)) - .Build(); - var inputProvider = Substitute.For(); - var logger = new TestLogger(testOutputHelper); - var gitClient = new GitClient(logger, repo.GitClientSettings); - var handler = new PullStackCommandHandler(inputProvider, logger, gitClient, stackConfig); - - gitClient.ChangeBranch(branch2); - - - inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); - - // Act - await handler.Handle(new PullStackCommandInputs(null)); - - // Assert - repo.GetCommitsReachableFromBranch(sourceBranch).Should().Contain(tipOfRemoteSourceBranch); - repo.GetCommitsReachableFromBranch(branch2).Should().Contain(tipOfRemoteBranch2); - } } diff --git a/src/Stack.Tests/Commands/Remote/SyncStackCommandHandlerTests.cs b/src/Stack.Tests/Commands/Remote/SyncStackCommandHandlerTests.cs index 04bc7661..2ff03848 100644 --- a/src/Stack.Tests/Commands/Remote/SyncStackCommandHandlerTests.cs +++ b/src/Stack.Tests/Commands/Remote/SyncStackCommandHandlerTests.cs @@ -45,7 +45,8 @@ public async Task WhenChangesExistOnTheSourceBranchOnTheRemote_PullsChanges_Upda var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); - var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); + var stackActions = new StackActions(gitClient, logger); + var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig, stackActions); gitClient.ChangeBranch(branch1); @@ -93,7 +94,8 @@ public async Task WhenNameIsProvided_DoesNotAskForName_SyncsCorrectStack() var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); - var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); + var stackActions = new StackActions(gitClient, logger); + var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig, stackActions); gitClient.ChangeBranch(branch1); @@ -141,7 +143,8 @@ public async Task WhenNameIsProvided_ButStackDoesNotExist_Throws() var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); - var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); + var stackActions = new StackActions(gitClient, logger); + var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig, stackActions); gitClient.ChangeBranch(branch1); @@ -185,7 +188,8 @@ public async Task WhenOnASpecificBranchInTheStack_TheSameBranchIsSetAsCurrentAft var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); - var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); + var stackActions = new StackActions(gitClient, logger); + var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig, stackActions); // We are on a specific branch in the stack gitClient.ChangeBranch(branch1); @@ -231,7 +235,8 @@ public async Task WhenOnlyASingleStackExists_DoesNotAskForStackName_SyncsStack() var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); - var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); + var stackActions = new StackActions(gitClient, logger); + var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig, stackActions); gitClient.ChangeBranch(branch1); @@ -282,7 +287,8 @@ public async Task WhenUsingRebase_ChangesExistOnTheSourceBranchOnTheRemote_Pulls var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); - var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); + var stackActions = new StackActions(gitClient, logger); + var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig, stackActions); gitClient.ChangeBranch(branch1); @@ -334,7 +340,8 @@ public async Task WhenUsingMerge_ChangesExistOnTheSourceBranchOnTheRemote_PullsC var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); - var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); + var stackActions = new StackActions(gitClient, logger); + var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig, stackActions); gitClient.ChangeBranch(branch1); @@ -387,7 +394,8 @@ public async Task WhenNotSpecifyingRebaseOrMerge_AndUpdateSettingIsRebase_DoesSy var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); - var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); + var stackActions = new StackActions(gitClient, logger); + var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig, stackActions); gitClient.ChangeBranch(branch1); @@ -440,7 +448,8 @@ public async Task WhenNotSpecifyingRebaseOrMerge_AndUpdateSettingIsMerge_DoesSyn var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); - var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); + var stackActions = new StackActions(gitClient, logger); + var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig, stackActions); gitClient.ChangeBranch(branch1); @@ -493,7 +502,8 @@ public async Task WhenGitConfigValueIsSetToMerge_ButRebaseIsSpecified_DoesSyncUs var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); - var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); + var stackActions = new StackActions(gitClient, logger); + var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig, stackActions); gitClient.ChangeBranch(branch1); @@ -546,7 +556,8 @@ public async Task WhenGitConfigValueIsSetToRebase_ButMergeIsSpecified_DoesSyncUs var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); - var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); + var stackActions = new StackActions(gitClient, logger); + var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig, stackActions); gitClient.ChangeBranch(branch1); @@ -599,7 +610,8 @@ public async Task WhenNotSpecifyingRebaseOrMerge_AndNoUpdateSettingExists_AndMer var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); - var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); + var stackActions = new StackActions(gitClient, logger); + var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig, stackActions); gitClient.ChangeBranch(branch1); @@ -653,7 +665,8 @@ public async Task WhenNotSpecifyingRebaseOrMerge_AndNoUpdateSettingsExists_AndRe var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); - var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); + var stackActions = new StackActions(gitClient, logger); + var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig, stackActions); gitClient.ChangeBranch(branch1); @@ -681,7 +694,8 @@ public async Task WhenBothRebaseAndMergeAreSpecified_AnErrorIsThrown() var logger = new TestLogger(testOutputHelper); var gitClient = Substitute.For(); var gitHubClient = Substitute.For(); - var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); + var stackActions = new StackActions(gitClient, logger); + var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig, stackActions); // Act and assert await handler @@ -723,7 +737,8 @@ public async Task WhenConfirmOptionIsProvided_DoesNotAskForConfirmation() var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); - var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); + var stackActions = new StackActions(gitClient, logger); + var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig, stackActions); gitClient.ChangeBranch(branch1); @@ -771,7 +786,8 @@ public async Task WhenNoPushOptionIsProvided_DoesNotPushChangesToRemote() var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); - var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); + var stackActions = new StackActions(gitClient, logger); + var handler = new SyncStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig, stackActions); gitClient.ChangeBranch(branch1); diff --git a/src/Stack/Commands/Helpers/StackActions.cs b/src/Stack/Commands/Helpers/StackActions.cs new file mode 100644 index 00000000..cbf7fbc4 --- /dev/null +++ b/src/Stack/Commands/Helpers/StackActions.cs @@ -0,0 +1,31 @@ +using Stack.Config; +using Stack.Infrastructure; +using Stack.Git; + +namespace Stack.Commands.Helpers +{ + public interface IStackActions + { + void PullChanges(Config.Stack stack); + } + + public class StackActions(IGitClient gitClient, ILogger logger) : IStackActions + { + public void PullChanges(Config.Stack stack) + { + List allBranchesInStacks = [stack.SourceBranch, .. stack.AllBranchNames]; + var branchStatus = gitClient.GetBranchStatuses([.. allBranchesInStacks]); + + foreach (var branch in allBranchesInStacks + .Where(b => + branchStatus.ContainsKey(b) && + branchStatus[b].RemoteBranchExists && + branchStatus[b].Behind > 0)) + { + logger.Information($"Pulling changes for {branch.Branch()} from remote"); + gitClient.ChangeBranch(branch); + gitClient.PullBranch(branch); + } + } + } +} diff --git a/src/Stack/Commands/Helpers/StackHelpers.cs b/src/Stack/Commands/Helpers/StackHelpers.cs index 580ded4f..666dee87 100644 --- a/src/Stack/Commands/Helpers/StackHelpers.cs +++ b/src/Stack/Commands/Helpers/StackHelpers.cs @@ -587,23 +587,6 @@ public static void UpdateBranchLineUsingMerge( } } - public static void PullChanges(Config.Stack stack, IGitClient gitClient, ILogger logger) - { - List allBranchesInStacks = [stack.SourceBranch, .. stack.AllBranchNames]; - var branchStatus = gitClient.GetBranchStatuses([.. allBranchesInStacks]); - - foreach (var branch in allBranchesInStacks - .Where(b => - branchStatus.ContainsKey(b) && - branchStatus[b].RemoteBranchExists && - branchStatus[b].Behind > 0)) - { - logger.Information($"Pulling changes for {branch.Branch()} from remote"); - gitClient.ChangeBranch(branch); - gitClient.PullBranch(branch); - } - } - public static void PushChanges( Config.Stack stack, int maxBatchSize, diff --git a/src/Stack/Commands/Remote/PullStackCommand.cs b/src/Stack/Commands/Remote/PullStackCommand.cs index d261665e..935cfd0d 100644 --- a/src/Stack/Commands/Remote/PullStackCommand.cs +++ b/src/Stack/Commands/Remote/PullStackCommand.cs @@ -15,11 +15,14 @@ public class PullStackCommand : Command protected override async Task Execute(ParseResult parseResult, CancellationToken cancellationToken) { + var gitClient = new GitClient(StdErrLogger, new GitClientSettings(Verbose, WorkingDirectory)); + var handler = new PullStackCommandHandler( InputProvider, StdErrLogger, - new GitClient(StdErrLogger, new GitClientSettings(Verbose, WorkingDirectory)), - new FileStackConfig()); + gitClient, + new FileStackConfig(), + new StackActions(gitClient, StdErrLogger)); await handler.Handle(new PullStackCommandInputs( parseResult.GetValue(CommonOptions.Stack))); @@ -31,7 +34,8 @@ public class PullStackCommandHandler( IInputProvider inputProvider, ILogger logger, IGitClient gitClient, - IStackConfig stackConfig) + IStackConfig stackConfig, + IStackActions stackActions) : CommandHandlerBase { public override async Task Handle(PullStackCommandInputs inputs) @@ -55,7 +59,7 @@ public override async Task Handle(PullStackCommandInputs inputs) if (stack is null) throw new InvalidOperationException($"Stack '{inputs.Stack}' not found."); - StackHelpers.PullChanges(stack, gitClient, logger); + stackActions.PullChanges(stack); gitClient.ChangeBranch(currentBranch); } diff --git a/src/Stack/Commands/Remote/SyncStackCommand.cs b/src/Stack/Commands/Remote/SyncStackCommand.cs index f0064060..476d4a59 100644 --- a/src/Stack/Commands/Remote/SyncStackCommand.cs +++ b/src/Stack/Commands/Remote/SyncStackCommand.cs @@ -25,12 +25,14 @@ public class SyncStackCommand : Command protected override async Task Execute(ParseResult parseResult, CancellationToken cancellationToken) { + var gitClient = new GitClient(StdErrLogger, new GitClientSettings(Verbose, WorkingDirectory)); var handler = new SyncStackCommandHandler( InputProvider, StdErrLogger, - new GitClient(StdErrLogger, new GitClientSettings(Verbose, WorkingDirectory)), + gitClient, new GitHubClient(StdErrLogger, new GitHubClientSettings(Verbose, WorkingDirectory)), - new FileStackConfig()); + new FileStackConfig(), + new StackActions(gitClient, StdErrLogger)); await handler.Handle(new SyncStackCommandInputs( parseResult.GetValue(CommonOptions.Stack), @@ -58,7 +60,8 @@ public class SyncStackCommandHandler( ILogger logger, IGitClient gitClient, IGitHubClient gitHubClient, - IStackConfig stackConfig) + IStackConfig stackConfig, + IStackActions stackActions) : CommandHandlerBase { public override async Task Handle(SyncStackCommandInputs inputs) @@ -104,7 +107,7 @@ public override async Task Handle(SyncStackCommandInputs inputs) { logger.Information($"Syncing stack {stack.Name.Stack()} with the remote repository"); - StackHelpers.PullChanges(stack, gitClient, logger); + stackActions.PullChanges(stack); var updateStrategy = StackHelpers.UpdateStack( stack,