Skip to content

Commit

Permalink
feat: add ddev cd command, fixes ddev#6639 (ddev#6644)
Browse files Browse the repository at this point in the history
Co-authored-by: Travis Carden <[email protected]>
Co-authored-by: Randy Fay <[email protected]>
  • Loading branch information
3 people authored Nov 3, 2024
1 parent 749449e commit 92cd790
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 0 deletions.
70 changes: 70 additions & 0 deletions cmd/ddev/cmd/cd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package cmd

import (
"fmt"
"github.com/ddev/ddev/pkg/ddevapp"
"github.com/ddev/ddev/pkg/fileutil"
"github.com/ddev/ddev/pkg/globalconfig"
"github.com/ddev/ddev/pkg/heredoc"
"github.com/ddev/ddev/pkg/output"
"github.com/ddev/ddev/pkg/util"
"github.com/spf13/cobra"
"path/filepath"
)

var (
bashFile = filepath.Join(globalconfig.GetGlobalDdevDir(), "commands/host/shells/ddev.sh")
fishFile = filepath.Join(globalconfig.GetGlobalDdevDir(), "commands/host/shells/ddev.fish")
)

// CdCmd is the top-level "ddev cd" command
var CdCmd = &cobra.Command{
Use: "cd [project-name]",
Short: "Uses shell built-in 'cd' to change to a project directory",
Long: heredoc.Doc(fmt.Sprintf(`
To enable the 'ddev cd' command, source the ddev.sh script from your rc-script.
For bash:
printf '\n[ -f "%s" ] && source "%s"\n' >> ~/.bashrc
For zsh:
printf '\n[ -f "%s" ] && source "%s"\n' >> ~/.zshrc
For fish:
printf '\n[ -f "%s" ] && source "%s"\n' >> ~/.config/fish/config.fish
Restart your shell, and use 'ddev cd project-name'.
`, bashFile, bashFile, bashFile, bashFile, fishFile, fishFile)),
ValidArgsFunction: ddevapp.GetProjectNamesFunc("all", 1),
Example: `ddev cd project-name`,
Run: func(cmd *cobra.Command, args []string) {
for _, file := range []string{bashFile, fishFile} {
if !fileutil.FileExists(file) {
util.Failed("Unable to find file: %s", file)
}

}
if len(args) != 1 {
util.Failed("This command only takes one argument: project-name")
}
projectName := args[0]
app, err := ddevapp.GetActiveApp(projectName)
if err != nil {
util.Failed("Failed to find path for project: %v", err)
}
if cmd.Flags().Changed("get-approot") {
output.UserOut.Println(app.AppRoot)
} else {
output.UserOut.Println(cmd.Long)
}
},
}

func init() {
CdCmd.Flags().BoolP("get-approot", "", false, "Get the full path to the project root directory")
_ = CdCmd.Flags().MarkHidden("get-approot")
RootCmd.AddCommand(CdCmd)
}
33 changes: 33 additions & 0 deletions cmd/ddev/cmd/cd_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package cmd

import (
"github.com/ddev/ddev/pkg/exec"
"github.com/ddev/ddev/pkg/globalconfig"
"github.com/ddev/ddev/pkg/util"
asrt "github.com/stretchr/testify/assert"
"path/filepath"
"strings"
"testing"
)

// TestCdCmd runs `ddev cd` to see if it works.
func TestCdCmd(t *testing.T) {
assert := asrt.New(t)
// Shows help
out, err := exec.RunHostCommand(DdevBin, "cd", TestSites[0].Name)
assert.NoError(err)
assert.Contains(out, filepath.Join(globalconfig.GetGlobalDdevDir(), "commands/host/shells/ddev.sh"))
assert.Contains(out, filepath.Join(globalconfig.GetGlobalDdevDir(), "commands/host/shells/ddev.fish"))
// Returns the path to the project
out, err = exec.RunHostCommand(DdevBin, "cd", TestSites[0].Name, "--get-approot")
assert.NoError(err)
assert.Equal(strings.TrimRight(out, "\n"), TestSites[0].Dir)
// Shows error
out, err = exec.RunHostCommand(DdevBin, "cd", "does-not-exist-"+util.RandString(4))
assert.Error(err)
assert.Contains(out, "Failed to find path for project")
// Shows error
out, err = exec.RunHostCommand(DdevBin, "cd")
assert.Error(err)
assert.Contains(out, "This command only takes one argument: project-name")
}
11 changes: 11 additions & 0 deletions docs/content/users/usage/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,17 @@ Run the `cake` command; available only in projects of type `cakephp`, and only a
ddev cake
```

## `cd`

Uses shell built-in `cd` to change to a project directory. For example, `ddev cd some-project` will change directories to the project root of the project named `some-project`.

Note that this command can't work until you make a small addition to your `.bashrc`, `.zshrc`, or `config.fish`. To see the explanation of what you need to do:

```shell
# Where some-project is a project from the `ddev list`
ddev cd some-project
```

## `clean`

Removes items DDEV has created. (See [Uninstalling DDEV](../usage/uninstall.md).)
Expand Down
20 changes: 20 additions & 0 deletions pkg/ddevapp/global_dotddev_assets/commands/host/shells/ddev.fish
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#ddev-generated
# This script should be sourced in the context of your shell like so:
# source $HOME/.ddev/commands/host/shells/ddev.fish
# Alternatively, it can be installed into one of the directories
# that fish uses to autoload functions (e.g ~/.config/fish/functions)
# Once the ddev() function is defined, you can type
# "ddev cd project-name" to cd into the project directory.

function ddev
if test (count $argv) -eq 2 -a "$argv[1]" = "cd"
switch "$argv[2]"
case '-*'
command ddev $argv
case '*'
cd (DDEV_VERBOSE=false command ddev cd "$argv[2]" --get-approot)
end
else
command ddev $argv
end
end
17 changes: 17 additions & 0 deletions pkg/ddevapp/global_dotddev_assets/commands/host/shells/ddev.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env sh
#ddev-generated
# This script should be sourced in the context of your shell like so:
# source $HOME/.ddev/commands/host/shells/ddev.sh
# Once the ddev() function is defined, you can type
# "ddev cd project-name" to cd into the project directory.

ddev() {
if [ "$#" -eq 2 ] && [ "$1" = "cd" ]; then
case "$2" in
-*) command ddev "$@" ;;
*) cd "$(DDEV_VERBOSE=false command ddev cd "$2" --get-approot)" ;;
esac
else
command ddev "$@"
fi
}

0 comments on commit 92cd790

Please sign in to comment.