Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,20 @@ import (

var composerDirectoryArg = ""

// ComposerCreateCmd handles ddev composer create
var ComposerCreateCmd = &cobra.Command{
// ComposerCreateProjectCmd handles ddev composer create-project
var ComposerCreateProjectCmd = &cobra.Command{
DisableFlagParsing: true,
Use: "create [args] [flags]",
Aliases: []string{"create-project"},
Use: "create-project [args] [flags]",
Short: "Executes 'composer create-project' within the web container with the arguments and flags provided",
Long: `Directs basic invocations of 'composer create-project' within the context of the
web container. Projects will be installed to a temporary directory and moved to
the Composer root directory after install.`,
Example: `ddev composer create drupal/recommended-project
ddev composer create drupal/recommended-project
ddev composer create "typo3/cms-base-distribution:^10"
ddev composer create drupal/recommended-project --no-install
ddev composer create --repository=https://repo.magento.com/ magento/project-community-edition
ddev composer create --prefer-dist --no-interaction --no-dev psr/log
Example: `ddev composer create-project drupal/recommended-project
ddev composer create-project drupal/recommended-project .
ddev composer create-project typo3/cms-base-distribution . "^10"
ddev composer create-project drupal/recommended-project --no-install .
ddev composer create-project --repository=https://repo.magento.com/ magento/project-community-edition .
ddev composer create-project --prefer-dist --no-interaction --no-dev psr/log .
`,
ValidArgsFunction: getComposerCompletionFunc(true),
Run: func(cmd *cobra.Command, args []string) {
Expand Down Expand Up @@ -75,7 +74,7 @@ ddev composer create --prefer-dist --no-interaction --no-dev psr/log

// Add some args to avoid troubles while cloning the project.
// We add the three options to "composer create-project": --no-plugins, --no-scripts, --no-install
// These options make the difference between "composer create-project" and "ddev composer create".
// These options make the difference between "composer create-project" and "ddev composer create-project".
var createArgs []string

for _, arg := range args {
Expand Down Expand Up @@ -301,19 +300,19 @@ ddev composer create --prefer-dist --no-interaction --no-dev psr/log
prepareAppForComposer(app)
}

util.Success("\nddev composer create was successful.")
util.Success("\nddev composer create-project was successful.")

if runtime.GOOS == "windows" {
fileutil.ReplaceSimulatedLinks(app.AppRoot)
}
},
}

// checkForComposerCreateAllowedPaths ensures that the project does not contain any paths that are not allowed to be present in the composer create command
// checkForComposerCreateAllowedPaths ensures that the project does not contain any paths that are not allowed to be present in the composer create-project command
func checkForComposerCreateAllowedPaths(app *ddevapp.DdevApp) {
appRoot := app.GetAbsAppRoot(false)
composerRoot := filepath.Join(app.GetComposerRoot(false, false), composerDirectoryArg)
skipDirs := []string{".ddev", ".git", ".tarballs"}
skipDirs := []string{".ddev", ".git", ".idea", ".tarballs", ".vscode"}
composerCreateAllowedPaths, _ := app.GetComposerCreateAllowedPaths()
err := filepath.Walk(composerRoot,
func(walkPath string, walkInfo os.FileInfo, err error) error {
Expand All @@ -327,7 +326,7 @@ func checkForComposerCreateAllowedPaths(app *ddevapp.DdevApp) {
return filepath.SkipDir
}
if !slices.Contains(composerCreateAllowedPaths, checkPath) {
return fmt.Errorf("'%s' is not allowed to be present. composer create needs to be run on a clean/empty project with only the following paths: %v - please clean up the project before using 'ddev composer create'", filepath.Join(appRoot, checkPath), composerCreateAllowedPaths)
return fmt.Errorf("'%s' is not allowed to be present. composer create-project needs to be run on a clean/empty project with only the following paths: %v - please clean up the project before using 'ddev composer create-project'", filepath.Join(appRoot, checkPath), composerCreateAllowedPaths)
}
return err
})
Expand Down Expand Up @@ -497,6 +496,24 @@ func prepareAppForComposer(app *ddevapp.DdevApp) {
}
}

// ComposerCreateCmd does the same thing as "ddev composer create-project".
// This command was introduced a while ago and has always caused some confusion:
// why "composer create-project" but "ddev composer create"?
// As of DDEV v1.24.2, "ddev composer create-project" works almost the same as "composer create-project",
// so we can now hide this command.
var ComposerCreateCmd = &cobra.Command{
Use: "create [args] [flags]",
Short: `Use "ddev composer create-project" instead`,
DisableFlagParsing: true,
Hidden: true,
// TODO: make it deprecated when we switch to "create-project" in our quickstarts
//Deprecated: `use "create-project" instead`,
Run: func(cmd *cobra.Command, args []string) {
ComposerCreateProjectCmd.Run(cmd, args)
},
}

func init() {
ComposerCmd.AddCommand(ComposerCreateProjectCmd)
ComposerCmd.AddCommand(ComposerCreateCmd)
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
"github.com/stretchr/testify/require"
)

func TestComposerCreateCmd(t *testing.T) {
func TestComposerCreateProjectCmd(t *testing.T) {
composerVersionForThisTest := nodeps.ComposerDefault
//composerVersionForThisTest := "2.8.0"

Expand All @@ -31,11 +31,11 @@ func TestComposerCreateCmd(t *testing.T) {
for _, docRoot := range []string{"", "doc-root"} {
for _, projectType := range validAppTypes {
if projectType == nodeps.AppTypeDrupal6 {
t.Logf("== SKIP TestComposerCreateCmd for project of type '%s' with docroot '%s'\n", projectType, docRoot)
t.Logf("== SKIP drupal6 projects uses a very old php version and composer create is very unlikely to be used")
t.Logf("== SKIP TestComposerCreateProjectCmd for project of type '%s' with docroot '%s'\n", projectType, docRoot)
t.Logf("== SKIP drupal6 projects uses a very old php version and composer create-project is very unlikely to be used")
continue
}
t.Logf("== BEGIN TestComposerCreateCmd for project of type '%s' with docroot '%s'\n", projectType, docRoot)
t.Logf("== BEGIN TestComposerCreateProjectCmd for project of type '%s' with docroot '%s'\n", projectType, docRoot)
tmpDir := testcommon.CreateTmpDir(t.Name() + projectType)
err = os.Chdir(tmpDir)
require.NoError(t, err)
Expand Down Expand Up @@ -88,22 +88,22 @@ func TestComposerCreateCmd(t *testing.T) {
// These are different conditions to test different composer flag combinations
// Conditions for docRoot and projectType are not important here, they are only needed to make the test act different each time
if docRoot == "" {
cmd = "ddev composer create --no-plugins --no-scripts ddev/ddev-test-composer-create"
cmd = "ddev composer create-project --no-plugins --no-scripts ddev/ddev-test-composer-create"
if projectType == nodeps.AppTypePHP {
cmd = "ddev composer create --no-install ddev/ddev-test-composer-create ."
cmd = "ddev composer create-project --no-install ddev/ddev-test-composer-create ."
}
} else {
if projectType != nodeps.AppTypePHP {
cmd = "ddev composer create ddev/ddev-test-composer-create --prefer-install auto . --no-dev v1.0.0"
cmd = "ddev composer create-project ddev/ddev-test-composer-create --prefer-install auto . --no-dev v1.0.0"
} else {
cmd = "ddev composer create -vvv ddev/ddev-test-composer-create --prefer-install=auto --fake-flag ."
cmd = "ddev composer create-project -vvv ddev/ddev-test-composer-create --prefer-install=auto --fake-flag ."
}
}

t.Logf("Attempting cmd='%s' with docroot='%s' composer_root='%s' type='%s'", cmd, docRoot, docRoot, projectType)
args := strings.Split(strings.TrimPrefix(cmd, "ddev "), " ")

// If a file exists in the composer root then composer create should fail
// If a file exists in the composer root then composer create-project should fail
file, err := os.Create(filepath.Join(composerDirOnHost, "touch1.txt"))
require.NoError(t, err)
out, err = exec.RunHostCommand(DdevBin, args...)
Expand All @@ -118,7 +118,7 @@ func TestComposerCreateCmd(t *testing.T) {
require.Contains(t, out, "Created project in ")
require.FileExists(t, filepath.Join(composerDirOnHost, "composer.json"))

if cmd == "ddev composer create --no-plugins --no-scripts ddev/ddev-test-composer-create" {
if cmd == "ddev composer create-project --no-plugins --no-scripts ddev/ddev-test-composer-create" {
// Check what was executed or not
require.Contains(t, out, "Executing Composer command: [composer create-project --no-plugins --no-scripts --no-install ddev/ddev-test-composer-create /tmp/")
require.NotContains(t, out, "Executing Composer command: [composer run-script post-root-package-install")
Expand All @@ -133,7 +133,7 @@ func TestComposerCreateCmd(t *testing.T) {
require.FileExists(t, filepath.Join(composerDirOnHost, "vendor", "ddev", "ddev-test-composer-require-dev", "composer.json"))
}

if cmd == "ddev composer create -vvv ddev/ddev-test-composer-create --prefer-install=auto --fake-flag ." {
if cmd == "ddev composer create-project -vvv ddev/ddev-test-composer-create --prefer-install=auto --fake-flag ." {
// Check what was executed or not
require.Contains(t, out, "Executing Composer command: [composer create-project -vvv --prefer-install=auto --no-plugins --no-scripts --no-install ddev/ddev-test-composer-create /tmp/")
require.Contains(t, out, "Executing Composer command: [composer run-script post-root-package-install -vvv]")
Expand All @@ -149,7 +149,7 @@ func TestComposerCreateCmd(t *testing.T) {
require.FileExists(t, filepath.Join(composerDirOnHost, "vendor", "ddev", "ddev-test-composer-require-dev", "composer.json"))
}

if cmd == "ddev composer create --no-install ddev/ddev-test-composer-create ." {
if cmd == "ddev composer create-project --no-install ddev/ddev-test-composer-create ." {
// Check what was executed or not
require.Contains(t, out, "Executing Composer command: [composer create-project --no-install --no-plugins --no-scripts ddev/ddev-test-composer-create /tmp/")
require.Contains(t, out, "Executing Composer command: [composer run-script post-root-package-install]")
Expand All @@ -162,7 +162,7 @@ func TestComposerCreateCmd(t *testing.T) {
require.NoDirExists(t, filepath.Join(composerDirOnHost, "vendor"))
}

if cmd == "ddev composer create ddev/ddev-test-composer-create --prefer-install auto . --no-dev v1.0.0" {
if cmd == "ddev composer create-project ddev/ddev-test-composer-create --prefer-install auto . --no-dev v1.0.0" {
// Check what was executed or not
require.Contains(t, out, "Executing Composer command: [composer create-project --prefer-install auto --no-dev --no-plugins --no-scripts --no-install ddev/ddev-test-composer-create /tmp/")
require.Contains(t, out, "v1.0.0")
Expand All @@ -179,7 +179,7 @@ func TestComposerCreateCmd(t *testing.T) {
}

require.Contains(t, out, "Moving install to Composer root")
require.Contains(t, out, "ddev composer create was successful")
require.Contains(t, out, "ddev composer create-project was successful")

// Check that resulting composer.json (copied from testdata) has post-root-package-install and post-create-project-cmd scripts
composerManifest, err := composer.NewManifest(filepath.Join(composerDirOnHost, "composer.json"))
Expand Down Expand Up @@ -217,7 +217,7 @@ func TestComposerCreateAutocomplete(t *testing.T) {
require.NoError(t, err)

// Pressing tab after `composer completion` should result in the completion "bash"
out, err := exec.RunHostCommand(DdevBin, "__complete", "composer", "create", "--")
out, err := exec.RunHostCommand(DdevBin, "__complete", "composer", "create-project", "--")
require.NoError(t, err)
// Completions are terminated with ":4", so just grab the stuff before that
completions, _, found := strings.Cut(out, ":")
Expand Down
2 changes: 1 addition & 1 deletion cmd/ddev/cmd/composer.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ the command with 'ddev'.`,
Example: `ddev composer install
ddev composer require <package>
ddev composer outdated --minor-only
ddev composer create drupal/recommended-project`,
ddev composer create-project drupal/recommended-project .`,
ValidArgsFunction: getComposerCompletionFunc(false),
Run: func(_ *cobra.Command, args []string) {
app, err := ddevapp.GetActiveApp("")
Expand Down
12 changes: 6 additions & 6 deletions cmd/ddev/cmd/composer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
)

func TestComposerCmdCreateConfigInstall(t *testing.T) {
// 2022-05-24: I've spent lots of time debugging intermittent `composer create` failures when NFS
// 2022-05-24: I've spent lots of time debugging intermittent `composer create-project` failures when NFS
// is enabled, both on macOS and Windows. As far as I can tell, it only happens in this test, I've
// never recreated manually. I do see https://github.com/composer/composer/issues/9627 which seemed
// to deal with similar issues in vagrant context, and has a hack now embedded into Composer.
Expand Down Expand Up @@ -70,8 +70,8 @@ func TestComposerCmdCreateConfigInstall(t *testing.T) {
// These two often fail on Windows with NFS, also Colima
// It appears to be something about Composer itself?

// ddev composer create --prefer-dist --no-interaction --no-dev psr/log:1.1.0
args := []string{"composer", "create", "--prefer-dist", "--no-interaction", "--no-dev", "--no-install", "psr/log:1.1.0"}
// ddev composer create-project --prefer-dist --no-interaction --no-dev psr/log:1.1.0
args := []string{"composer", "create-project", "--prefer-dist", "--no-interaction", "--no-dev", "--no-install", "psr/log:1.1.0"}
out, err = exec.RunHostCommand(DdevBin, args...)
assert.NoError(err, "failed to run %v: err=%v, output=\n=====\n%s\n=====\n", args, err, out)
assert.Contains(out, "Created project in ")
Expand All @@ -90,7 +90,7 @@ func TestComposerCmdCreateConfigInstall(t *testing.T) {
}

func TestComposerCmdCreateRequireRemoveConfigVersion(t *testing.T) {
// 2022-05-24: I've spent lots of time debugging intermittent `composer create` failures when NFS
// 2022-05-24: I've spent lots of time debugging intermittent `composer create-project` failures when NFS
// is enabled, both on macOS and Windows. As far as I can tell, it only happens in this test, I've
// never recreated manually. I do see https://github.com/composer/composer/issues/9627 which seemed
// to deal with similar issues in vagrant context, and has a hack now embedded into Composer.
Expand Down Expand Up @@ -143,8 +143,8 @@ func TestComposerCmdCreateRequireRemoveConfigVersion(t *testing.T) {
// These two often fail on Windows with NFS, also Colima
// It appears to be something about Composer itself?

// ddev composer create --prefer-dist --no-dev --no-install psr/log:1.1.0
args := []string{"composer", "create", "--prefer-dist", "--no-dev", "--no-install", "psr/log:1.1.0"}
// ddev composer create-project --prefer-dist --no-dev --no-install psr/log:1.1.0 .
args := []string{"composer", "create-project", "--prefer-dist", "--no-dev", "--no-install", "psr/log:1.1.0", "."}
out, err = exec.RunHostCommand(DdevBin, args...)
assert.NoError(err, "failed to run %v: err=%v, output=\n=====\n%s\n=====\n", args, err, out)
assert.Contains(out, "Created project in ")
Expand Down
2 changes: 1 addition & 1 deletion docs/content/developers/building-contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ The pull request title must follow this convention which is based on the [Conven
* `ci: enforce commit message convention, fixes #5037`
* `docs: change code refs of Mac M1 to Apple Silicon`
* `feat: allow multiple upload dirs, fixes #4190, fixes #4796`
* `fix: create upload_dir if it doesn't exist in ddev composer create, fixes #5031`
* `fix: create upload_dir if it doesn't exist in ddev composer create-project, fixes #5031`
* `refactor: add new Amplitude Property DDEV-Environment`
* `test: optimize caching of downloaded assets`

Expand Down
2 changes: 1 addition & 1 deletion docs/content/developers/project-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ To add a new project type:
* `postStartAction` adds actions at the end of [`ddev start`](../users/usage/commands.md#start). You'll see several implementations of this, for things like creating needed default directories, or setting permissions on files, etc.
* `importFilesAction` defines how [`ddev import-files`](../users/usage/commands.md#import-files) works for this project type.
* `defaultWorkingDirMap` allows the project type to override the project’s [`working_dir`](../users/configuration/config.md#working_dir) (where [`ddev ssh`](../users/usage/commands.md#ssh) and [`ddev exec`](../users/usage/commands.md#exec) start by default). This is mostly not done anymore, as the `working_dir` is typically the project root.
* `composerCreateAllowedPaths` specifies the paths that can exist in a directory when `ddev composer create` is being used.
* `composerCreateAllowedPaths` specifies the paths that can exist in a directory when `ddev composer create-project` is being used.
* You’ll likely need templates for settings files, use the Drupal or TYPO3 templates as examples, for example `pkg/ddevapp/drupal` and `pkg/ddevapp/typo3`. Those templates have to be loaded at runtime as well.
* Implement `nginx-site-<project-type>.conf` in `webserver_config_assets`. You can use `webserver_config_assets/nginx-site-php.conf` as a pattern, or something from the upstream project.
* Upload the project detection file stubs to the `testdata/TestDetectAppType` folder.
Expand Down
2 changes: 1 addition & 1 deletion docs/content/users/install/performance.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ Mutagen is enabled by default on Mac and traditional Windows, and it can be disa
* **Beware simultaneous changes to the same file in both filesystems.**<br>
As we pointed out above, any project likely to change the same file on the host *and* inside the container may encounter conflicts.
* **Massive changes can cause problems.**<br>
Massive file changes on the host or in the container are the most likely to introduce issues. This integration has been tested extensively with major changes introduced by `ddev composer` and `ddev composer create`, but be aware of this issue. Changing Git branches, `npm install`, `yarn install`, or a script that deletes huge sections of the synced data are related behaviors that should raise caution. Again, use `ddev mutagen reset` before restarting the project if you want to be sure Mutagen starts out looking at the host machine’s files.
Massive file changes on the host or in the container are the most likely to introduce issues. This integration has been tested extensively with major changes introduced by `ddev composer` and `ddev composer create-project`, but be aware of this issue. Changing Git branches, `npm install`, `yarn install`, or a script that deletes huge sections of the synced data are related behaviors that should raise caution. Again, use `ddev mutagen reset` before restarting the project if you want to be sure Mutagen starts out looking at the host machine’s files.
* **Mutagen is asynchronous.**<br>
A massive change in either filesystem can result in lag as all changed files are handled. You can use `ddev mutagen monitor` to get a better look at what’s happening.
* **You can manually trigger a sync.**<br>
Expand Down
6 changes: 3 additions & 3 deletions docs/content/users/usage/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ ddev clean my-project my-other-project

Executes a [Composer command](../usage/developer-tools.md#ddev-and-composer) within the web container.

`ddev composer create` is a special command that is an adaptation of `composer create-project`. See [DDEV and Composer](../usage/developer-tools.md#ddev-and-composer) for more information.
`ddev composer create-project` is a special command that is an adaptation of `composer create-project`. See [DDEV and Composer](../usage/developer-tools.md#ddev-and-composer) for more information.

Example:

Expand All @@ -271,11 +271,11 @@ Example:
ddev composer install
```

Example of `ddev composer create`:
Example of `ddev composer create-project`:

```shell
# Create a new Drupal project in the current directory
ddev composer create drupal/recommended-project
ddev composer create-project drupal/recommended-project .
```

## `config`
Expand Down
Loading