func handleNoComposerJSON()

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
}