Skip to content
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,27 @@ Options:
-?, -h, --help Show help and usage information
```

#### `stack branch move` <!-- omit from toc -->

Move a branch to another location in a stack.

```shell
Usage:
stack branch move [options]

Options:
--working-dir The path to the directory containing the git repository. Defaults to the current directory.
--debug Show debug output.
--verbose Show verbose output.
--json Write output and log messages as JSON. Log messages will be written to stderr.
-s, --stack The name of the stack.
-b, --branch The name of the branch.
-p, --parent The name of the parent branch to put the branch under.
--re-parent-children Re-parent child branches to the current parent of the branch being moved.
--move-children Move child branches with the branch being moved.
-?, -h, --help Show help and usage information
```

### Remote commands <!-- omit from toc -->

#### `stack pull` <!-- omit from toc -->
Expand Down
336 changes: 336 additions & 0 deletions src/Stack.Tests/Commands/Branch/MoveBranchCommandHandlerTests.cs

Large diffs are not rendered by default.

50 changes: 25 additions & 25 deletions src/Stack.Tests/Commands/Branch/RemoveBranchCommandHandlerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@ public async Task WhenNoInputsProvided_AsksForAllInputsAndConfirms_RemovesBranch
var gitClientFactory = Substitute.For<IGitClientFactory>();
var executionContext = new CliExecutionContext { WorkingDirectory = "/some/path" };
var handler = new RemoveBranchCommandHandler(inputProvider, logger, gitClientFactory, executionContext, stackConfig);

gitClientFactory.Create(executionContext.WorkingDirectory).Returns(gitClient);

gitClient.GetRemoteUri().Returns(remoteUri);
gitClient.GetCurrentBranch().Returns(sourceBranch);

inputProvider.Select(Questions.SelectStack, Arg.Any<string[]>(), Arg.Any<CancellationToken>()).Returns("Stack1");
inputProvider.Select(Questions.SelectBranch, Arg.Any<string[]>(), Arg.Any<CancellationToken>()).Returns(branchToRemove);
inputProvider.SelectGrouped(Questions.SelectBranch, Arg.Any<ChoiceGroup<string>[]>(), Arg.Any<CancellationToken>()).Returns(branchToRemove);
inputProvider.Select(Questions.RemoveBranchChildAction, Arg.Any<RemoveBranchChildAction[]>(), Arg.Any<CancellationToken>(), Arg.Any<Func<RemoveBranchChildAction, string>>())
.Returns(RemoveBranchChildAction.RemoveChildren);
inputProvider.Confirm(Questions.ConfirmRemoveBranch, Arg.Any<CancellationToken>()).Returns(true);
Expand Down Expand Up @@ -87,13 +87,13 @@ public async Task WhenStackNameProvided_DoesNotAskForStackName_RemovesBranchFrom
var gitClientFactory = Substitute.For<IGitClientFactory>();
var executionContext = new CliExecutionContext { WorkingDirectory = "/some/path" };
var handler = new RemoveBranchCommandHandler(inputProvider, logger, gitClientFactory, executionContext, stackConfig);

gitClientFactory.Create(executionContext.WorkingDirectory).Returns(gitClient);

gitClient.GetRemoteUri().Returns(remoteUri);
gitClient.GetCurrentBranch().Returns(sourceBranch);

inputProvider.Select(Questions.SelectBranch, Arg.Any<string[]>(), Arg.Any<CancellationToken>()).Returns(branchToRemove);
inputProvider.SelectGrouped(Questions.SelectBranch, Arg.Any<ChoiceGroup<string>[]>(), Arg.Any<CancellationToken>()).Returns(branchToRemove);
inputProvider.Confirm(Questions.ConfirmRemoveBranch, Arg.Any<CancellationToken>()).Returns(true);

// Act
Expand Down Expand Up @@ -133,7 +133,7 @@ public async Task WhenStackNameProvided_ButStackDoesNotExist_Throws()
var gitClientFactory = Substitute.For<IGitClientFactory>();
var executionContext = new CliExecutionContext { WorkingDirectory = "/some/path" };
var handler = new RemoveBranchCommandHandler(inputProvider, logger, gitClientFactory, executionContext, stackConfig);

gitClientFactory.Create(executionContext.WorkingDirectory).Returns(gitClient);

gitClient.GetRemoteUri().Returns(remoteUri);
Expand Down Expand Up @@ -172,7 +172,7 @@ public async Task WhenBranchNameProvided_DoesNotAskForBranchName_RemovesBranchFr
var gitClientFactory = Substitute.For<IGitClientFactory>();
var executionContext = new CliExecutionContext { WorkingDirectory = "/some/path" };
var handler = new RemoveBranchCommandHandler(inputProvider, logger, gitClientFactory, executionContext, stackConfig);

gitClientFactory.Create(executionContext.WorkingDirectory).Returns(gitClient);

gitClient.GetRemoteUri().Returns(remoteUri);
Expand Down Expand Up @@ -218,7 +218,7 @@ public async Task WhenBranchNameProvided_ButBranchDoesNotExistInStack_Throws()
var gitClientFactory = Substitute.For<IGitClientFactory>();
var executionContext = new CliExecutionContext { WorkingDirectory = "/some/path" };
var handler = new RemoveBranchCommandHandler(inputProvider, logger, gitClientFactory, executionContext, stackConfig);

gitClientFactory.Create(executionContext.WorkingDirectory).Returns(gitClient);

gitClient.GetRemoteUri().Returns(remoteUri);
Expand Down Expand Up @@ -255,13 +255,13 @@ public async Task WhenOnlyOneStackExists_DoesNotAskForStackName()
var gitClientFactory = Substitute.For<IGitClientFactory>();
var executionContext = new CliExecutionContext { WorkingDirectory = "/some/path" };
var handler = new RemoveBranchCommandHandler(inputProvider, logger, gitClientFactory, executionContext, stackConfig);

gitClientFactory.Create(executionContext.WorkingDirectory).Returns(gitClient);

gitClient.GetRemoteUri().Returns(remoteUri);
gitClient.GetCurrentBranch().Returns(sourceBranch);

inputProvider.Select(Questions.SelectBranch, Arg.Any<string[]>(), Arg.Any<CancellationToken>()).Returns(branchToRemove);
inputProvider.SelectGrouped(Questions.SelectBranch, Arg.Any<ChoiceGroup<string>[]>(), Arg.Any<CancellationToken>()).Returns(branchToRemove);
inputProvider.Confirm(Questions.ConfirmRemoveBranch, Arg.Any<CancellationToken>()).Returns(true);

// Act
Expand Down Expand Up @@ -301,14 +301,14 @@ public async Task WhenConfirmProvided_DoesNotAskForConfirmation_RemovesBranchFro
var gitClientFactory = Substitute.For<IGitClientFactory>();
var executionContext = new CliExecutionContext { WorkingDirectory = "/some/path" };
var handler = new RemoveBranchCommandHandler(inputProvider, logger, gitClientFactory, executionContext, stackConfig);

gitClientFactory.Create(executionContext.WorkingDirectory).Returns(gitClient);

gitClient.GetRemoteUri().Returns(remoteUri);
gitClient.GetCurrentBranch().Returns(sourceBranch);

inputProvider.Select(Questions.SelectStack, Arg.Any<string[]>(), Arg.Any<CancellationToken>()).Returns("Stack1");
inputProvider.Select(Questions.SelectBranch, Arg.Any<string[]>(), Arg.Any<CancellationToken>()).Returns(branchToRemove);
inputProvider.SelectGrouped(Questions.SelectBranch, Arg.Any<ChoiceGroup<string>[]>(), Arg.Any<CancellationToken>()).Returns(branchToRemove);

// Act
await handler.Handle(new RemoveBranchCommandInputs(null, null, true), CancellationToken.None);
Expand Down Expand Up @@ -344,14 +344,14 @@ public async Task WhenChildActionIsMoveChildrenToParent_RemovesBranchAndMovesChi
var gitClientFactory = Substitute.For<IGitClientFactory>();
var executionContext = new CliExecutionContext { WorkingDirectory = "/some/path" };
var handler = new RemoveBranchCommandHandler(inputProvider, logger, gitClientFactory, executionContext, stackConfig);

gitClientFactory.Create(executionContext.WorkingDirectory).Returns(gitClient);

gitClient.GetRemoteUri().Returns(remoteUri);
gitClient.GetCurrentBranch().Returns(sourceBranch);

inputProvider.Select(Questions.SelectStack, Arg.Any<string[]>(), Arg.Any<CancellationToken>()).Returns("Stack1");
inputProvider.Select(Questions.SelectBranch, Arg.Any<string[]>(), Arg.Any<CancellationToken>()).Returns(branchToRemove);
inputProvider.SelectGrouped(Questions.SelectBranch, Arg.Any<ChoiceGroup<string>[]>(), Arg.Any<CancellationToken>()).Returns(branchToRemove);
inputProvider.Select(Questions.RemoveBranchChildAction, Arg.Any<RemoveBranchChildAction[]>(), Arg.Any<CancellationToken>(), Arg.Any<Func<RemoveBranchChildAction, string>>())
.Returns(RemoveBranchChildAction.MoveChildrenToParent);
inputProvider.Confirm(Questions.ConfirmRemoveBranch, Arg.Any<CancellationToken>()).Returns(true);
Expand Down Expand Up @@ -388,14 +388,14 @@ public async Task WhenChildActionIsRemoveChildren_RemovesBranchAndDeletesChildre
var gitClientFactory = Substitute.For<IGitClientFactory>();
var executionContext = new CliExecutionContext { WorkingDirectory = "/some/path" };
var handler = new RemoveBranchCommandHandler(inputProvider, logger, gitClientFactory, executionContext, stackConfig);

gitClientFactory.Create(executionContext.WorkingDirectory).Returns(gitClient);

gitClient.GetRemoteUri().Returns(remoteUri);
gitClient.GetCurrentBranch().Returns(sourceBranch);

inputProvider.Select(Questions.SelectStack, Arg.Any<string[]>(), Arg.Any<CancellationToken>()).Returns("Stack1");
inputProvider.Select(Questions.SelectBranch, Arg.Any<string[]>(), Arg.Any<CancellationToken>()).Returns(branchToRemove);
inputProvider.SelectGrouped(Questions.SelectBranch, Arg.Any<ChoiceGroup<string>[]>(), Arg.Any<CancellationToken>()).Returns(branchToRemove);
inputProvider.Select(Questions.RemoveBranchChildAction, Arg.Any<RemoveBranchChildAction[]>(), Arg.Any<CancellationToken>(), Arg.Any<Func<RemoveBranchChildAction, string>>())
.Returns(RemoveBranchChildAction.RemoveChildren);
inputProvider.Confirm(Questions.ConfirmRemoveBranch, Arg.Any<CancellationToken>()).Returns(true);
Expand Down Expand Up @@ -432,14 +432,14 @@ public async Task WhenRemoveChildrenIsProvided_RemovesBranchAndDeletesChildren()
var gitClientFactory = Substitute.For<IGitClientFactory>();
var executionContext = new CliExecutionContext { WorkingDirectory = "/some/path" };
var handler = new RemoveBranchCommandHandler(inputProvider, logger, gitClientFactory, executionContext, stackConfig);

gitClientFactory.Create(executionContext.WorkingDirectory).Returns(gitClient);

gitClient.GetRemoteUri().Returns(remoteUri);
gitClient.GetCurrentBranch().Returns(sourceBranch);

inputProvider.Select(Questions.SelectStack, Arg.Any<string[]>(), Arg.Any<CancellationToken>()).Returns("Stack1");
inputProvider.Select(Questions.SelectBranch, Arg.Any<string[]>(), Arg.Any<CancellationToken>()).Returns(branchToRemove);
inputProvider.SelectGrouped(Questions.SelectBranch, Arg.Any<ChoiceGroup<string>[]>(), Arg.Any<CancellationToken>()).Returns(branchToRemove);
inputProvider.Confirm(Questions.ConfirmRemoveBranch, Arg.Any<CancellationToken>()).Returns(true);

// Act
Expand Down Expand Up @@ -476,14 +476,14 @@ public async Task WhenMoveChildrenToParentIsProvided_RemovesBranchAndMovesChildr
var gitClientFactory = Substitute.For<IGitClientFactory>();
var executionContext = new CliExecutionContext { WorkingDirectory = "/some/path" };
var handler = new RemoveBranchCommandHandler(inputProvider, logger, gitClientFactory, executionContext, stackConfig);

gitClientFactory.Create(executionContext.WorkingDirectory).Returns(gitClient);

gitClient.GetRemoteUri().Returns(remoteUri);
gitClient.GetCurrentBranch().Returns(sourceBranch);

inputProvider.Select(Questions.SelectStack, Arg.Any<string[]>(), Arg.Any<CancellationToken>()).Returns("Stack1");
inputProvider.Select(Questions.SelectBranch, Arg.Any<string[]>(), Arg.Any<CancellationToken>()).Returns(branchToRemove);
inputProvider.SelectGrouped(Questions.SelectBranch, Arg.Any<ChoiceGroup<string>[]>(), Arg.Any<CancellationToken>()).Returns(branchToRemove);
inputProvider.Confirm(Questions.ConfirmRemoveBranch, Arg.Any<CancellationToken>()).Returns(true);

// Act
Expand Down Expand Up @@ -519,14 +519,14 @@ public async Task WhenBranchHasNoChildren_DoesNotAskForChildAction()
var gitClientFactory = Substitute.For<IGitClientFactory>();
var executionContext = new CliExecutionContext { WorkingDirectory = "/some/path" };
var handler = new RemoveBranchCommandHandler(inputProvider, logger, gitClientFactory, executionContext, stackConfig);

gitClientFactory.Create(executionContext.WorkingDirectory).Returns(gitClient);

gitClient.GetRemoteUri().Returns(remoteUri);
gitClient.GetCurrentBranch().Returns(sourceBranch);

inputProvider.Select(Questions.SelectStack, Arg.Any<string[]>(), Arg.Any<CancellationToken>()).Returns("Stack1");
inputProvider.Select(Questions.SelectBranch, Arg.Any<string[]>(), Arg.Any<CancellationToken>()).Returns(branchToRemove);
inputProvider.SelectGrouped(Questions.SelectBranch, Arg.Any<ChoiceGroup<string>[]>(), Arg.Any<CancellationToken>()).Returns(branchToRemove);
inputProvider.Confirm(Questions.ConfirmRemoveBranch, Arg.Any<CancellationToken>()).Returns(true);

// Act
Expand Down Expand Up @@ -563,14 +563,14 @@ public async Task WhenBranchHasNoChildrenButRemoveChildrenIsProvided_DoesNotAskF
var gitClientFactory = Substitute.For<IGitClientFactory>();
var executionContext = new CliExecutionContext { WorkingDirectory = "/some/path" };
var handler = new RemoveBranchCommandHandler(inputProvider, logger, gitClientFactory, executionContext, stackConfig);

gitClientFactory.Create(executionContext.WorkingDirectory).Returns(gitClient);

gitClient.GetRemoteUri().Returns(remoteUri);
gitClient.GetCurrentBranch().Returns(sourceBranch);

inputProvider.Select(Questions.SelectStack, Arg.Any<string[]>(), Arg.Any<CancellationToken>()).Returns("Stack1");
inputProvider.Select(Questions.SelectBranch, Arg.Any<string[]>(), Arg.Any<CancellationToken>()).Returns(branchToRemove);
inputProvider.SelectGrouped(Questions.SelectBranch, Arg.Any<ChoiceGroup<string>[]>(), Arg.Any<CancellationToken>()).Returns(branchToRemove);
inputProvider.Confirm(Questions.ConfirmRemoveBranch, Arg.Any<CancellationToken>()).Returns(true);

// Act
Expand Down Expand Up @@ -607,14 +607,14 @@ public async Task WhenBranchHasNoChildrenButMoveChildrenToParentIsProvided_DoesN
var gitClientFactory = Substitute.For<IGitClientFactory>();
var executionContext = new CliExecutionContext { WorkingDirectory = "/some/path" };
var handler = new RemoveBranchCommandHandler(inputProvider, logger, gitClientFactory, executionContext, stackConfig);

gitClientFactory.Create(executionContext.WorkingDirectory).Returns(gitClient);

gitClient.GetRemoteUri().Returns(remoteUri);
gitClient.GetCurrentBranch().Returns(sourceBranch);

inputProvider.Select(Questions.SelectStack, Arg.Any<string[]>(), Arg.Any<CancellationToken>()).Returns("Stack1");
inputProvider.Select(Questions.SelectBranch, Arg.Any<string[]>(), Arg.Any<CancellationToken>()).Returns(branchToRemove);
inputProvider.SelectGrouped(Questions.SelectBranch, Arg.Any<ChoiceGroup<string>[]>(), Arg.Any<CancellationToken>()).Returns(branchToRemove);
inputProvider.Confirm(Questions.ConfirmRemoveBranch, Arg.Any<CancellationToken>()).Returns(true);

// Act
Expand Down
Loading
Loading