8000 Merge pull request #581 from tucksaun/feat/symfony-composer-path · tucksaun/symfonycli@ea259ac · GitHub
[go: up one dir, main page]

Skip to content

Commit ea259ac

Browse files
authored
Merge pull request symfony-cli#581 from tucksaun/feat/symfony-composer-path
feat: allow to define where is Composer using SYMFONY_COMPOSER_PATH env var
2 parents 1309e83 + e93e62e commit ea259ac

File tree

5 files changed

+106
-12
lines changed

5 files changed

+106
-12
lines changed

local/php/composer.go

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,19 @@ func Composer(dir string, args, env []string, stdout, stderr, logger io.Writer,
7373
if composerVersion() == 2 {
7474
composerBin = "composer2"
7575
}
76-
path, err := e.findComposer(composerBin)
77-
if err != nil || !isPHPScript(path) {
78-
fmt.Fprintln(logger, " WARNING: Unable to find Composer, downloading one. It is recommended to install Composer yourself at https://getcomposer.org/download/")
76+
77+
if composerPath := os.Getenv("SYMFONY_COMPOSER_PATH"); composerPath != "" {
78+
debugLogger.Debug().Str("SYMFONY_COMPOSER_PATH", composerPath).Msg("SYMFONY_COMPOSER_PATH has been defined. User is taking control over Composer detection and execution.")
79+
e.Args = append([]string{composerPath}, args...)
80+
} else if path, err := e.findComposer(composerBin); err == nil && isPHPScript(path) {
81+
e.Args = append([]string{"php", path}, args...)
82+
} else {
83+
reason := "No Composer installation found."
84+
if path != "" {
85+
reason = fmt.Sprintf("Detected Composer file (%s) is not a valid PHAR or PHP script.", path)
86+
}
87+
fmt.Fprintln(logger, " WARNING:", reason)
88+
fmt.Fprintln(logger, " Downloading Composer for you, but it is recommended to install Composer yourself, instructions available at https://getcomposer.org/download/")
7989
// we don't store it under bin/ to avoid it being found by findComposer as we want to only use it as a fallback
8090
binDir := filepath.Join(util.GetHomeDir(), "composer")
8191
if path, err = downloadComposer(binDir, debugLogger); err != nil {
@@ -84,22 +94,25 @@ func Composer(dir string, args, env []string, stdout, stderr, logger io.Writer,
8494
error: errors.Wrap(err, "unable to find composer, get it at https://getcomposer.org/download/"),
8595
}
8696
}
87-
fmt.Fprintf(logger, " (running %s %s)\n\n", path, strings.TrimSpace(strings.Join(args, " ")))
97+
e.Args = append([]string{"php", path}, args...)
98+
fmt.Fprintf(logger, " (running %s)\n\n", e.CommandLine())
8899
}
89100

90-
e.Args = append([]string{"php", path}, args...)
91101
ret := e.Execute(false)
92102
if ret != 0 {
93103
return ComposerResult{
94104
code: ret,
95-
error: errors.Errorf("unable to run %s %s", path, strings.Join(args, " ")),
105+
error: errors.Errorf("unable to run %s", e.CommandLine()),
96106
}
97107
}
98108
return ComposerResult{}
99109
}
100110

101111
// isPHPScript checks that the composer file is indeed a phar/PHP script (not a .bat file)
102112
func isPHPScript(path string) bool {
113+
if path == "" {
114+
return false
115+
}
103116
file, err := os.Open(path)
104117
if err != nil {
105118
return false
@@ -111,6 +124,10 @@ func isPHPScript(path string) bool {
111124
return false
112125
}
113126

127+
if bytes.Equal(byteSlice, []byte("<?php")) {
128+
return true
129+
}
130+
114131
return bytes.HasPrefix(byteSlice, []byte("#!/")) && bytes.HasSuffix(byteSlice, []byte("php"))
115132
}
116133

@@ -149,7 +166,7 @@ func findComposer(extraBin string, logger zerolog.Logger) (string, error) {
149166
if strings.HasSuffix(pharPath, ".bat") {
150167
pharPath = pharPath[:len(pharPath)-4] + ".phar"
151168
}
152-
logger.Debug().Str("source", "Composer").Msgf(`Found Composer as "%s"`, pharPath)
169+
logger.Debug().Str("source", "Composer").Msgf(`Found potential Composer as "%s"`, pharPath)
153170
return pharPath, nil
154171
}
155172
}

local/php/composer_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,15 @@ func (s *ComposerSuite) TestIsComposerPHPScript(c *C) {
3333
dir, err := filepath.Abs("testdata/php_scripts")
3434
c.Assert(err, IsNil)
3535

36+
c.Assert(isPHPScript(""), Equals, false)
3637
c.Assert(isPHPScript(filepath.Join(dir, "unknown")), Equals, false)
3738
c.Assert(isPHPScript(filepath.Join(dir, "invalid")), Equals, false)
3839

3940
for _, validScripts := range []string{
4041
"usual-one",
4142
"debian-style",
4243
"custom-one",
44+
"plain-one.php",
4345
} {
4446
c.Assert(isPHPScript(filepath.Join(dir, validScripts)), Equals, true)
4547
}

local/php/executor.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ func GetBinaryNames() []string {
7474
return []string{"php", "pecl", "pear", "php-fpm", "php-cgi", "php-config", "phpdbg", "phpize"}
7575
}
7676

77+
func (e Executor) CommandLine() string {
78+
return strings.TrimSpace(strings.Join(e.Args, " "))
79+
}
80+
7781
func (e *Executor) lookupPHP(cliDir string, forceReload bool) (*phpstore.Version, string, bool, error) {
7882
phpStore := phpstore.New(cliDir, forceReload, nil)
7983
v, source, warning, err := phpStore.BestVersionForDir(e.scriptDir)
@@ -284,9 +288,11 @@ func (e *Executor) Config(loadDotEnv bool) error {
284288
}
285289
}
286290

287-
// args[0] MUST be the same as path
288-
// but as we change the path, we should update args[0] accordingly
289-
e.Args[0] = path
291+
if IsBinaryName(e.Args[0]) {
292+
// args[0] MUST be the same as path
293+
// but as we change the path, we should update args[0] accordingly
294+
e.Args[0] = path
295+
}
290296

291297
return err
292298
}
@@ -401,7 +407,7 @@ func (e *Executor) findComposer(extraBin string) (string, error) {
401407
}
402408
if m := d.Mode(); !m.IsDir() {
403409
// Yep!
404-
e.Logger.Debug().Str("source", "Composer").Msgf(`Found Composer as "%s"`, path)
410+
e.Logger.Debug().Str("source", "Composer").Msgf(`Found potential Composer as "%s"`, path)
405411
return path, nil
406412
}
407413
}

local/php/executor_test.go

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,12 @@ func TestHelperProcess(t *testing.T) {
9999
for _, v := range os.Environ() {
100100
fmt.Println(v)
101101
}
102+
os.Exit(0)
102103
case "exit-code":
103104
code, _ := strconv.Atoi(os.Args[4])
104105
os.Exit(code)
105106
}
106-
os.Exit(0)
107+
os.Exit(1)
107108
}
108109

109110
func (s *ExecutorSuite) TestNotEnoughArgs(c *C) {
@@ -112,6 +113,14 @@ func (s *ExecutorSuite) TestNotEnoughArgs(c *C) {
112113
c.Assert((&Executor{BinName: "php"}).Execute(true), Equals, 1)
113114
}
114115

116+
func (s *ExecutorSuite) TestCommandLineFormatting(c *C) {
117+
c.Assert((&Executor{}).CommandLine(), Equals, "")
118+
119+
c.Assert((&Executor{Args: []string{"php"}}).CommandLine(), Equals, "php")
120+
121+
c.Assert((&Executor{Args: []string{"php", "-dmemory_limit=-1", "/path/to/composer.phar"}}).CommandLine(), Equals, "php -dmemory_limit=-1 /path/to/composer.phar")
122+
}
123+
115124
func (s *ExecutorSuite) TestForwardExitCode(c *C) {
116125
defer restoreExecCommand()
117126
fakeExecCommand("exit-code", "5")
@@ -131,6 +140,63 @@ func (s *ExecutorSuite) TestForwardExitCode(c *C) {
131140
c.Assert((&Executor{BinName: "php", Args: []string{"php"}}).Execute(true), Equals, 5)
132141
}
133142

143+
func (s *ExecutorSuite) TestExecutorRunsPHP(c *C) {
144+
defer restoreExecCommand()
145+
execCommand = func(name string, arg ...string) *exec.Cmd {
146+
c.Assert(name, Equals, "../bin/php")
147+
148+
cmd := exec.Command(os.Args[0], "-test.run=TestHelperProcess", "--", "exit-code", "0")
149+
cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
150+
// Set the working directory right now so that it can be changed by
151+
// calling test case
152+
cmd.Dir, _ = os.Getwd()
153+
return cmd
154+
}
155+
156+
home, err := filepath.Abs("testdata/executor")
157+
c.Assert(err, IsNil)
158+
159+
homedir.Reset()
160+
os.Setenv("HOME", home)
161+
defer homedir.Reset()
162+
163+
oldwd, _ := os.Getwd()
164+
defer os.Chdir(oldwd)
165+
os.Chdir(filepath.Join(home, "project"))
166+
defer cleanupExecutorTempFiles()
167+
168+
c.Assert((&Executor{BinName: "php", Args: []string{"php"}}).Execute(true), Equals, 0)
169+
170+
}
171+
172+
func (s *ExecutorSuite) TestBinaryOtherThanPhp(c *C) {
173+
defer restoreExecCommand()
174+
execCommand = func(name string, arg ...string) *exec.Cmd {
175+
c.Assert(name, Equals, "not-php")
176+
177+
cmd := exec.Command(os.Args[0], "-test.run=TestHelperProcess", "--", "exit-code", "0")
178+
cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
179+
// Set the working directory right now so that it can be changed by
180+
// calling test case
181+
cmd.Dir, _ = os.Getwd()
182+
return cmd
183+
}
184+
185+
home, err := filepath.Abs("testdata/executor")
186+
c.Assert(err, IsNil)
187+
188+
homedir.Reset()
189+
os.Setenv("HOME", home)
190+
defer homedir.Reset()
191+
192+
oldwd, _ := os.Getwd()
193+
defer os.Chdir(oldwd)
194+
os.Chdir(filepath.Join(home, "project"))
195+
defer cleanupExecutorTempFiles()
196+
197+
c.Assert((&Executor{BinName: "php", Args: []string{"not-php"}}).Execute(true), Equals, 0)
198+
}
199+
134200
func (s *ExecutorSuite) TestEnvInjection(c *C) {
135201
defer restoreExecCommand()
136202
fakeExecCommand("dump-env")
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<?php
2+
3+
echo 'Hello World!';

0 commit comments

Comments
 (0)
0