in cmd/php/functions_framework/main.go [143:232]
func handleNoComposerJSON(ctx *gcp.Context) error {
ctx.Logf("Handling function without composer.json")
vendorExists, err := ctx.FileExists(php.Vendor)
if err != nil {
return err
}
// Check if there's a vendor directory. If not, this is truly a dependency-less function
// so we can `composer install` the framework and cache the vendor dir.
if !vendorExists {
ctx.Logf("No vendor directory present, installing functions framework")
cvt := filepath.Join(ctx.BuildpackRoot(), "converter")
if _, err := ctx.Exec([]string{"cp", filepath.Join(cvt, "composer.json"), filepath.Join(cvt, "composer.lock"), "."}); err != nil {
return err
}
if _, err := php.ComposerInstall(ctx, cacheTag); err != nil {
return fmt.Errorf("composer install: %w", err)
}
cloudfunctions.AddFrameworkVersionLabel(ctx, &cloudfunctions.FrameworkVersionInfo{
Runtime: "php",
Version: ffVersion,
Injected: true,
})
return nil
}
ffPath := filepath.Join(php.Vendor, ffPackage)
ffExists, err := ctx.FileExists(ffPath)
if err != nil {
return err
}
// Check if the vendor directory contains the functions framework. If so we're done.
if ffExists {
ctx.Logf("Functions framework is already present in the vendor directory")
routerScriptExists, err := ctx.FileExists(routerScript)
if err != nil {
return err
}
// Make sure the router script also exists. If the user is vendoring their own deps
// you never know how they've structured their vendor directory.
if !routerScriptExists {
return gcp.UserErrorf("functions framework router script %s is not present", routerScript)
}
cloudfunctions.AddFrameworkVersionLabel(ctx, &cloudfunctions.FrameworkVersionInfo{
Runtime: "php",
Version: "unknown-vendored",
Injected: false,
})
return nil
}
if err := cloudfunctions.AssertFrameworkInjectionAllowed(); err != nil {
return err
}
// The user did not vendor the functions framework. Before installing it, let's see if they used
// Composer to install their deps. If so we can safely `composer require` the framework even
// without composer.json; vendor/composer/installed.json contains the info required to resolve
// a working set of dependencies.
ctx.Warnf("Functions framework is not present at %s, so automatic injection will be attempted. Please add a dependency on it to avoid unexpected conflicts or breakages that result from this. See %s and %s", ffPath, ffGitHubURL, ffPackagistURL)
installed := filepath.Join(php.Vendor, "composer", "installed.json")
installedExists, err := ctx.FileExists(installed)
if err != nil {
return err
}
if !installedExists {
return gcp.UserErrorf("%s is not present, so it appears that Composer was not used to install dependencies.", installed)
}
// All clear to install the functions framework! We'll do this via `composer require`
// because we're adding a package to an already existing vendor directory.
ctx.Logf("Installing functions framework %s", ffPackageWithVersion)
if err := php.ComposerRequire(ctx, []string{ffPackageWithVersion}); err != nil {
return nil
}
cloudfunctions.AddFrameworkVersionLabel(ctx, &cloudfunctions.FrameworkVersionInfo{
Runtime: "php",
Version: ffVersion,
Injected: true,
})
return nil
}