text:
package com.android.build.gradle.integration.common.fixture;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import com.android.SdkConstants;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.build.gradle.integration.common.fixture.app.AbstractAndroidTestApp;
import com.android.build.gradle.integration.common.fixture.app.AndroidTestApp;
import com.android.build.gradle.integration.common.fixture.app.TestSourceFile;
import com.android.build.gradle.integration.common.utils.FileHelper;
import com.android.build.gradle.integration.common.utils.JacocoAgent;
import com.android.build.gradle.integration.common.utils.SdkHelper;
import com.android.builder.core.BuilderConstants;
import com.android.builder.model.AndroidProject;
import com.android.builder.model.SyncIssue;
import com.android.builder.model.Version;
import com.android.io.StreamException;
import com.android.sdklib.internal.project.ProjectProperties;
import com.android.sdklib.internal.project.ProjectPropertiesWorkingCopy;
import com.android.sdklib.repository.FullRevision;
import com.google.common.base.Charsets;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.io.Files;

import org.gradle.tooling.BuildAction;
import org.gradle.tooling.BuildActionExecuter;
import org.gradle.tooling.BuildLauncher;
import org.gradle.tooling.GradleConnector;
import org.gradle.tooling.LongRunningOperation;
import org.gradle.tooling.ProjectConnection;
import org.gradle.tooling.internal.consumer.DefaultGradleConnector;
import org.gradle.tooling.model.GradleProject;
import org.gradle.tooling.model.GradleTask;
import org.junit.Assume;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.Charset;
import java.security.CodeSource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * JUnit4 test rule for integration test.
 *
 * This rule create a gradle project in a temporary directory.
 * It can be use with the @Rule or @ClassRule annotations.  Using this class with @Rule will create
 * a gradle project in separate directories for each unit test, whereas using it with @ClassRule
 * creates a single gradle project.
 *
 * The test directory is always deleted if it already exists at the start of the test to ensure a
 * clean environment.
 */
public class GradleTestProject implements TestRule {

    public static final File TEST_RES_DIR = new File("src/test/resources");

    public static final int DEFAULT_COMPILE_SDK_VERSION = 21;
    public static final String DEFAULT_BUILD_TOOL_VERSION;
    public static final String REMOTE_TEST_PROVIDER = System.getenv().get("REMOTE_TEST_PROVIDER");

    public static final String DEVICE_PROVIDER_NAME = REMOTE_TEST_PROVIDER != null ?
            REMOTE_TEST_PROVIDER : BuilderConstants.CONNECTED;

    public static final String GRADLE_TEST_VERSION = "2.2.1";
    public static final String GRADLE_EXP_TEST_VERSION = "2.5-rc-1";

    public static final String ANDROID_GRADLE_PLUGIN_VERSION;

    public static final String CUSTOM_JACK;

    public static final boolean USE_JACK;

    static {
        String envBuildToolVersion = System.getenv("CUSTOM_BUILDTOOLS");
        DEFAULT_BUILD_TOOL_VERSION = !Strings.isNullOrEmpty(envBuildToolVersion) ?
                envBuildToolVersion : "22.0.1";
        String envVersion = System.getenv().get("CUSTOM_GRADLE");
        ANDROID_GRADLE_PLUGIN_VERSION = !Strings.isNullOrEmpty(envVersion) ? envVersion
                : Version.ANDROID_GRADLE_PLUGIN_VERSION;
        String envJack = System.getenv().get("CUSTOM_JACK");
        CUSTOM_JACK = !Strings.isNullOrEmpty(envJack) ? envJack : "false";
        USE_JACK = Boolean.parseBoolean(CUSTOM_JACK);
    }

    private static final String COMMON_HEADER = "commonHeader.gradle";
    private static final String COMMON_LOCAL_REPO = "commonLocalRepo.gradle";
    private static final String COMMON_BUILD_SCRIPT = "commonBuildScript.gradle";
    private static final String COMMON_BUILD_SCRIPT_EXP = "commonBuildScriptExperimental.gradle";
    private static final String COMMON_GRADLE_PLUGIN_VERSION = "commonGradlePluginVersion.gradle";
    private static final String DEFAULT_TEST_PROJECT_NAME = "project";

    public static class Builder {
        private static final File SAMPLE_PROJECT_DIR = new File("samples");
        private static final File TEST_PROJECT_DIR = new File("test-projects");

        @Nullable
        private String name;

        @Nullable
        private TestProject testProject = null;

        @Nullable
        File sdkDir = SdkHelper.findSdkDir();
        @Nullable
        File ndkDir = findNdkDir();
        boolean captureStdOut = false;
        boolean captureStdErr = false;
        boolean experimentalMode = false;
        boolean useExperimentalGradleVersion = false;
        @NonNull
        private List<String> gradleProperties = Lists.newArrayList();
        @Nullable
        private String heapSize;

        /**
         * Create a GradleTestProject.
         */
        public GradleTestProject create()  {
            return new GradleTestProject(
                    name,
                    testProject,
                    experimentalMode,
                    useExperimentalGradleVersion ? GRADLE_EXP_TEST_VERSION : GRADLE_TEST_VERSION,
                    captureStdOut,
                    captureStdErr,
                    sdkDir,
                    ndkDir,
                    gradleProperties,
                    heapSize);
        }

        /**
         * Set the name of the project.
         *
         * Necessary if you have multiple projects in a test class.
         */
        public Builder withName(@NonNull String name) {
            this.name = name;
            return this;
        }

        public Builder captureStdOut(boolean captureStdOut) {
            this.captureStdOut = captureStdOut;
            return this;
        }

        public Builder captureStdErr(boolean captureStdErr) {
            this.captureStdErr = captureStdErr;
            return this;
        }

        /**
         * Use experimental plugin for the test project.
         */
        public Builder forExpermimentalPlugin(boolean mode) {
            this.useExperimentalGradleVersion = mode;
            this.experimentalMode = mode;
            return this;
        }

        /**
         * Use the gradle version for experimental plugin, but the test project do not necessarily
         * have to use experimental plugin.
         */
        public Builder useExperimentalGradleVersion(boolean mode) {
            this.useExperimentalGradleVersion = mode;
            return this;
        }

        /**
         * Create a project without setting ndk.dir in local.properties.
         */
        public Builder withoutNdk() {
            this.ndkDir = null;
            return this;
        }

        /**
         * Create GradleTestProject from a TestProject.
         */
        public Builder fromTestApp(@NonNull TestProject testProject) {
            this.testProject = testProject;
            return this;
        }

        /**
         * Create GradleTestProject from an existing test project.
         */
        public Builder fromTestProject(@NonNull String project) {
            AndroidTestApp app = new EmptyTestApp();
            name = project;
            File projectDir = new File(TEST_PROJECT_DIR, project);
            addAllFiles(app, projectDir);
            return fromTestApp(app);
        }

        /**
         * Add gradle properties.
         */
        public Builder addGradleProperties(@NonNull String property) {
            gradleProperties.add(property);
            return this;
        }

        /**
         * Sets the test heap size requirement. Example values : 1024m, 2048m...
         *
         * @param heapSize the heap size in a format understood by the -Xmx JVM parameter
         * @return itself.
         */
        public Builder withHeap(String heapSize) {
            this.heapSize = heapSize;
            return this;
        }

        private static class EmptyTestApp extends AbstractAndroidTestApp {
            @Override
            public boolean containsFullBuildScript() {
                return true;
            }
        }
    }

    private String name;

    private File outDir;

    private File testDir;

    private File sourceDir;

    private File buildFile;

    private File ndkDir;

    private File sdkDir;

    private final ByteArrayOutputStream stdout;
    private final ByteArrayOutputStream stderr;

    private final Collection<String> gradleProperties;

    @Nullable
    private TestProject testProject;

    private boolean experimentalMode;
    private String targetGradleVersion;

    @Nullable
    private String heapSize;

    private GradleTestProject(
            @Nullable String name,
            @Nullable TestProject testProject,
            boolean experimentalMode,
            String targetGradleVersion,
            boolean captureStdOut,
            boolean captureStdErr,
            @Nullable File sdkDir,
            @Nullable File ndkDir,
            @NonNull Collection<String> gradleProperties,
            @Nullable String heapSize) {
        String buildDir = System.getenv("PROJECT_BUILD_DIR");
        outDir = (buildDir == null) ? new File("build/tests") : new File(buildDir, "tests");
        this.name = (name == null) ? DEFAULT_TEST_PROJECT_NAME : name;
        this.experimentalMode = experimentalMode;
        this.targetGradleVersion = targetGradleVersion;
        this.testProject = testProject;
        stdout = captureStdOut ? new ByteArrayOutputStream() : null;
        stderr = captureStdErr ? new ByteArrayOutputStream() : null;
        this.sdkDir = sdkDir;
        this.ndkDir = ndkDir;
        this.heapSize = heapSize;
        this.gradleProperties = gradleProperties;
    }

    /**
     * Create a GradleTestProject representing a subProject of another GradleTestProject.
     * @param subProject name of the subProject.
     * @param rootProject root GradleTestProject.
     */
    private GradleTestProject(
            @NonNull String subProject,
            @NonNull GradleTestProject rootProject) {
        name = subProject;
        outDir = rootProject.outDir;

        testDir = new File(rootProject.testDir, subProject);
        assertTrue("No subproject dir at " + testDir.toString(), testDir.isDirectory());

        buildFile = new File(testDir, "build.gradle");
        sourceDir = new File(testDir, "src");
        ndkDir = rootProject.ndkDir;
        sdkDir = rootProject.sdkDir;
        stdout = rootProject.stdout;
        stderr = rootProject.stdout;
        gradleProperties = ImmutableList.of();
        testProject = null;
    }

    public static Builder builder() {
        return new Builder();
    }

    /**
     * Recursively delete directory or file.
     *
     * @param root directory to delete
     */
    private static void deleteRecursive(File root) {
        if (root.exists()) {
            if (root.isDirectory()) {
                File files[] = root.listFiles();
                if (files != null) {
                    for (File file : files) {
                        deleteRecursive(file);
                    }
                }
            }
            assertTrue(root.delete());
        }
    }

    /**
     * Add all files in a directory to an AndroidTestApp.
     */
    private static void addAllFiles(AndroidTestApp app, File projectDir) {
        for (String filePath : FileHelper.listFiles(projectDir)) {
            File file = new File(filePath);
            try {
                app.addFile(
                        new TestSourceFile(
                                file.getParent(),
                                file.getName(),
                                Files.toByteArray(new File(projectDir, filePath))));
            } catch (IOException e) {
                fail(e.toString());
            }
        }
    }

    @Override
    public Statement apply(final Statement base, Description description) {
        testDir = new File(outDir, description.getTestClass().getName());

        // Create separate directory based on test method name if @Rule is used.
        // getMethodName() is null if this rule is used as a @ClassRule.
        if (description.getMethodName() != null) {
            String dirName = description.getMethodName();
            dirName = dirName.replaceAll("[^a-zA-Z0-9_]", "_");
            testDir = new File(testDir, dirName);
        }
        testDir = new File(testDir, name);

        buildFile = new File(testDir, "build.gradle");
        sourceDir = new File(testDir, "src");

        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                if (testDir.exists()) {
                    deleteRecursive(testDir);
                }
                assertTrue(testDir.mkdirs());
                assertTrue(sourceDir.mkdirs());

                Files.copy(
                        new File(Builder.TEST_PROJECT_DIR, COMMON_HEADER),
                        new File(testDir.getParent(), COMMON_HEADER));
                Files.copy(
                        new File(Builder.TEST_PROJECT_DIR, COMMON_LOCAL_REPO),
                        new File(testDir.getParent(), COMMON_LOCAL_REPO));
                Files.copy(
                        new File(Builder.TEST_PROJECT_DIR, COMMON_BUILD_SCRIPT),
                        new File(testDir.getParent(), COMMON_BUILD_SCRIPT));
                Files.copy(
                        new File(Builder.TEST_PROJECT_DIR, COMMON_BUILD_SCRIPT_EXP),
                        new File(testDir.getParent(), COMMON_BUILD_SCRIPT_EXP));
                Files.copy(
                        new File(Builder.TEST_PROJECT_DIR, COMMON_GRADLE_PLUGIN_VERSION),
                        new File(testDir.getParent(), COMMON_GRADLE_PLUGIN_VERSION));

                if (testProject != null) {
                    testProject.write(
                            testDir,
                            testProject.containsFullBuildScript() ? "" :getGradleBuildscript());
                } else {
                    Files.write(
                            getGradleBuildscript(),
                            buildFile,
                            Charsets.UTF_8);
                }

                createLocalProp(testDir, sdkDir, ndkDir);
                createGradleProp();
                base.evaluate();
            }
        };
    }

    /**
     * Create a GradleTestProject representing a subproject.
     */
    public GradleTestProject getSubproject(String name) {
        return new GradleTestProject(name, this);
    }

    /**
     * Return the name of the test project.
     */
    public String getName() {
        return name;
    }

    /**
     * Return the directory containing the test project.
     */
    public File getTestDir() {
        return testDir;
    }

    /**
     * Return the build.gradle of the test project.
     */
    public File getBuildFile() {
        return buildFile;
    }

    /**
     * Return the directory containing the source files of the test project.
     */
    public File getSourceDir() {
        return sourceDir;
    }

    /**
     * Return the output directory from Android plugins.
     */
    public File getOutputDir() {
        return new File(testDir,
                Joiner.on(File.separator).join("build", AndroidProject.FD_OUTPUTS));
    }

    /**
     * Return a File under the output directory from Android plugins.
     */
    public File getOutputFile(String path) {
        return new File(getOutputDir(), path);
    }

    /**
     * Return the output apk File from the application plugin for the given dimension.
     *
     * Expected dimensions orders are:
     *   - product flavors
     *   - build type
     *   - other modifiers (e.g. "unsigned", "aligned")
     */
    public File getApk(String ... dimensions) {
        // TODO: Add overload for tests and splits.
        List<String> dimensionList = Lists.newArrayListWithExpectedSize(1 + dimensions.length);
        dimensionList.add(getName());
        dimensionList.addAll(Arrays.asList(dimensions));
        return getOutputFile(
                "apk/" + Joiner.on("-").join(dimensionList) + SdkConstants.DOT_ANDROID_PACKAGE);
    }

    /**
     * Return the output aar File from the library plugin for the given dimension.
     *
     * Expected dimensions orders are:
     *   - product flavors
     *   - build type
     *   - other modifiers (e.g. "unsigned", "aligned")
     */
    public File getAar(String ... dimensions) {
        // TODO: Add overload for tests and splits.
        List<String> dimensionList = Lists.newArrayListWithExpectedSize(1 + dimensions.length);
        dimensionList.add(getName());
        dimensionList.addAll(Arrays.asList(dimensions));
        return getOutputFile("aar/" + Joiner.on("-").join(dimensionList) + SdkConstants.DOT_AAR);
    }

    /**
     * Returns the SDK dir
     */
    public File getSdkDir() {
        return sdkDir;
    }

    /**
     * Returns the NDK dir
     */
    public File getNdkDir() {
        return ndkDir;
    }

    /**
     * Return the directory of the repository containing the necessary plugins for testing.
     */
    private File getRepoDir() {
        CodeSource source = getClass().getProtectionDomain().getCodeSource();
        assert (source != null);
        URL location = source.getLocation();
        try {
            File dir = new File(location.toURI());
            assertTrue(dir.getPath(), dir.exists());

            File f = dir.getParentFile().getParentFile().getParentFile().getParentFile()
                    .getParentFile().getParentFile().getParentFile();
            return new File(f, "out" + File.separator + "repo");
        } catch (URISyntaxException e) {
            fail(e.getLocalizedMessage());
        }
        return null;
    }

    /**
     * Returns a string that contains the gradle buildscript content
     */
    public String getGradleBuildscript() {
        return "apply from: \"../commonHeader.gradle\"\n" +
               "buildscript { apply from: \"../commonBuildScript" +
               (experimentalMode ? "Experimental" : "") + ".gradle\", to: buildscript }\n" +
               "\n" +
               "apply from: \"../commonLocalRepo.gradle\"\n";
    }

    /**
     * Return a list of all task names of the project.
     */
    public List<String> getTaskList() {
        ProjectConnection connection = getProjectConnection();
        try {
            GradleProject project = connection.getModel(GradleProject.class);
            List<String> tasks = Lists.newArrayList();
            for (GradleTask gradleTask : project.getTasks()) {
                tasks.add(gradleTask.getName());
            }
            return tasks;
        } finally {
            connection.close();
        }

    }

    /**
     * Runs gradle on the project.  Throws exception on failure.
     *
     * @param tasks Variadic list of tasks to execute.
     */
    public void execute(String ... tasks) {
        execute(Collections.<String>emptyList(), false, false, tasks);
    }

    public void execute(@NonNull List<String> arguments, String ... tasks) {
        execute(arguments, false, false, tasks);
    }

    public void executeConnectedCheck() {
        executeConnectedCheck(Collections.<String>emptyList());
    }

    public void executeConnectedCheck(List<String> arguments) {
        execute(arguments, REMOTE_TEST_PROVIDER == null ? "connectedCheck" : "deviceCheck");
    }

    /**
     * Runs gradle on the project, and returns the project model.  Throws exception on failure.
     *
     * @param tasks Variadic list of tasks to execute.
     *
     * @return the AndroidProject model for the project.
     */
    @NonNull
    public AndroidProject executeAndReturnModel(String ... tasks) {
        return executeAndReturnModel(false, tasks);
    }

    /**
     * Runs gradle on the project, and returns the project model.  Throws exception on failure.
     *
     * @param emulateStudio_1_0 whether to emulate an older IDE (studio 1.0) querying the model.
     * @param tasks Variadic list of tasks to execute.
     *
     * @return the AndroidProject model for the project.
     */
    @NonNull
    public AndroidProject executeAndReturnModel(boolean emulateStudio_1_0, String ... tasks) {
        //noinspection ConstantConditions
        return execute(Collections.<String>emptyList(), true, emulateStudio_1_0, tasks);
    }

    /**
     * Runs gradle on the project, and returns a project model for each sub-project.
     * Throws exception on failure.
     *
     * @param tasks Variadic list of tasks to execute.
     *
     * @return the AndroidProject model for the project.
     */
    @NonNull
    public Map<String, AndroidProject> executeAndReturnMultiModel(String ... tasks) {
        return executeAndReturnMultiModel(false, tasks);
    }

    /**
     * Runs gradle on the project, and returns a project model for each sub-project.
     * Throws exception on failure.
     *
     * @param emulateStudio_1_0 whether to emulate an older IDE (studio 1.0) querying the model.
     * @param tasks Variadic list of tasks to execute.
     *
     * @return the AndroidProject model for the project.
     */
    @NonNull
    public Map<String, AndroidProject> executeAndReturnMultiModel(boolean emulateStudio_1_0, String ... tasks) {
        ProjectConnection connection = getProjectConnection();
        try {
            executeBuild(Collections.<String>emptyList(), connection, tasks);

            return buildModel(connection, new GetAndroidModelAction(), emulateStudio_1_0);

        } finally {
            connection.close();
        }
    }

    /**
     * Returns the project model without building.
     *
     * This will fail if the project is a multi-project setup or if there are any sync issues
     * while loading the project.
     */
    @NonNull
    public AndroidProject getSingleModel() {
        return getSingleModel(false /* emulateStudio_1_0 */, true /*assertNodSyncIssues */);
    }

    /**
     * Returns the project model without building, querying it the way Studio 1.0 does.
     *
     * This will fail if the project is a multi-project setup or if there are any sync issues
     * while loading the project.
     */
    @NonNull
    public AndroidProject getSingleModelAsStudio1() {
        return getSingleModel(true /* emulateStudio_1_0 */, true /*assertNodSyncIssues */);
    }

    /**
     * Returns the project model without building.
     *
     * This will fail if the project is a multi-project setup.
     */
    @NonNull
    public AndroidProject getSingleModelIgnoringSyncIssues() {
        return getSingleModel(false /* emulateStudio_1_0 */, false /*assertNodSyncIssues */);
    }

    /**
     * Returns the project model without building, querying it the way Studio 1.0 does.
     *
     * This will fail if the project is a multi-project setup.
     */
    @NonNull
    public AndroidProject getSingleModelIgnoringSyncIssuesAsStudio1() {
        return getSingleModel(true /* emulateStudio_1_0 */, false /*assertNodSyncIssues */);
    }

    /**
     * Returns the project model without building.
     *
     * This will fail if the project is a multi-project setup.
     *
     * @param emulateStudio_1_0 whether to emulate an older IDE (studio 1.0) querying the model.
     * @param assertNoSyncIssues true if the presence of sync issues during the model evaluation
     *                           should raise a {@link AssertionError}s
     */
    @NonNull
    private AndroidProject getSingleModel(boolean emulateStudio_1_0, boolean assertNoSyncIssues) {
        ProjectConnection connection = getProjectConnection();
        try {
            Map<String, AndroidProject> modelMap = buildModel(
                    connection,
                    new GetAndroidModelAction(),
                    emulateStudio_1_0);

            // ensure there was only one project
            assertEquals("Quering GradleTestProject.getModel() with multi-project settings",
                    1, modelMap.size());

            AndroidProject androidProject = modelMap.get(":");
            if (assertNoSyncIssues) {
                assertNoSyncIssues(androidProject);
            }
            return androidProject;
        } finally {
            connection.close();
        }
    }

    /**
     * Returns a project model for each sub-project without building generating a
     * {@link AssertionError} if any sync issue is raised during the model loading.
     */
    @NonNull
    public Map<String, AndroidProject> getAllModels() {
        Map<String, AndroidProject> allModels = getAllModels(new GetAndroidModelAction(), false);
        for (AndroidProject project : allModels.values()) {
            assertNoSyncIssues(project);
        }
        return allModels;
    }

    private static void assertNoSyncIssues(AndroidProject project) {
        if (!project.getSyncIssues().isEmpty()) {
            StringBuilder msg = new StringBuilder();
            msg.append("Project ")
                    .append(project.getName())
                    .append(" had sync issues :\n");
            for (SyncIssue syncIssue : project.getSyncIssues()) {
                msg.append(syncIssue);
                msg.append("\n");
            }
            fail(msg.toString());
        }
    }

    /**
     * Returns a project model for each sub-project without building and ignoring potential sync
     * issues. Sync issues will still be returned for each {@link AndroidProject} that failed to
     * sync properly.
     */
    @NonNull
    public Map<String, AndroidProject> getAllModelsIgnoringSyncIssues() {
        return getAllModels(new GetAndroidModelAction(), false);
    }

    /**
     * Returns a project model for each sub-project without building.
     *
     * @param action the build action to gather the model
     */
    @NonNull
    public <K, V> Map<K, V> getAllModels(@NonNull BuildAction<Map<K, V>> action) {
        return getAllModels(action, false);
    }

    /**
     * Returns a project model for each sub-project without building.
     *
     * @param action the build action to gather the model
     * @param emulateStudio_1_0 whether to emulate an older IDE (studio 1.0) querying the model.
     */
    @NonNull
    public <K, V> Map<K, V> getAllModels(
            @NonNull BuildAction<Map<K, V>> action,
            boolean emulateStudio_1_0) {
        ProjectConnection connection = getProjectConnection();
        try {
            return buildModel(connection, action, emulateStudio_1_0);

        } finally {
            connection.close();
        }
    }

    public void evaluate() {
        getAllModels(new GetEmptyModelAction(), false);
    }

    /**
     * Runs gradle on the project.  Throws exception on failure.
     *
     * @param arguments List of arguments for the gradle command.
     * @param returnModel whether the model should be queried and returned.
     * @param emulateStudio_1_0 whether to emulate an older IDE (studio 1.0) querying the model.
     * @param tasks Variadic list of tasks to execute.
     *
     * @return the model, if <var>returnModel</var> was true, null otherwise
     */
    @Nullable
    private AndroidProject execute(
            @NonNull List<String> arguments,
            boolean returnModel,
            boolean emulateStudio_1_0,
            @NonNull String ... tasks) {
        ProjectConnection connection = getProjectConnection();
        try {
            executeBuild(arguments, connection, tasks);

            if (returnModel) {
                Map<String, AndroidProject> modelMap = buildModel(
                        connection,
                        new GetAndroidModelAction(),
                        emulateStudio_1_0);

                // ensure there was only one project
                assertEquals("Quering GradleTestProject.getModel() with multi-project settings",
                        1, modelMap.size());

                return modelMap.get(":");
            }
        } finally {
            connection.close();
        }

        return null;
    }

    private void executeBuild(List<String> arguments, ProjectConnection connection,
            String[] tasks) {
        List<String> args = Lists.newArrayListWithCapacity(3 + arguments.size());
        args.add("-i");
        args.add("-u");
        args.addAll(arguments);

        BuildLauncher launcher = connection.newBuild()
                .forTasks(tasks)
                .withArguments(Iterables.toArray(args, String.class));

        setJvmArguments(launcher);

        if (stdout != null) {
            launcher.setStandardOutput(stdout);
        } else {
            launcher.setStandardOutput(System.out);
        }
        if (stderr != null) {
            launcher.setStandardError(stderr);
        } else {
            launcher.setStandardError(System.err);
        }
        launcher.run();
    }

    private void setJvmArguments(LongRunningOperation launcher) {
        List<String> jvmArguments = new ArrayList<String>();

        if (!Strings.isNullOrEmpty(heapSize)) {
            jvmArguments.add("-Xmx" + heapSize);
        }

        jvmArguments.add("-XX:MaxPermSize=1024m");

        String debugIntegrationTest = System.getenv("DEBUG_INNER_TEST");
        if (!Strings.isNullOrEmpty(debugIntegrationTest)) {
            jvmArguments.add("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5006");
        }

        if (JacocoAgent.isJacocoEnabled()) {
            jvmArguments.add(JacocoAgent.getJvmArg());
        }

        launcher.setJvmArguments(Iterables.toArray(jvmArguments, String.class));
    }

    /**
     * Returns a project model for each sub-project without building.
     *
     * @param connection the opened ProjectConnection
     * @param action the build action to gather the model
     * @param emulateStudio_1_0 whether to emulate an older IDE (studio 1.0) querying the model.
     */
    @NonNull
    private <K,V> Map<K, V> buildModel(
            @NonNull ProjectConnection connection,
            @NonNull BuildAction<Map<K, V>> action,
            boolean emulateStudio_1_0) {

        BuildActionExecuter<Map<K, V>> executor = connection.action(action);

        List<String> arguments = Lists.newArrayListWithCapacity(emulateStudio_1_0 ? 2 : 3);
        arguments.add("-P" + AndroidProject.PROPERTY_BUILD_MODEL_ONLY + "=true");
        arguments.add("-P" + AndroidProject.PROPERTY_INVOKED_FROM_IDE + "=true");
        if (!emulateStudio_1_0) {
            arguments.add("-P" + AndroidProject.PROPERTY_BUILD_MODEL_ONLY_ADVANCED + "=true");
        }

        setJvmArguments(executor);

        executor.withArguments(Iterables.toArray(arguments, String.class));

        executor.setStandardOutput(System.out);
        executor.setStandardError(System.err);

        return executor.run();
    }

    /**
     * Return the stdout from all execute command.
     */
    public ByteArrayOutputStream getStdout() {
        return stdout;
    }

    /**
     * Return the stderr from all execute command.
     */
    public ByteArrayOutputStream getStderr() {
        return stderr;
    }

    /**
     * Create a File object.  getTestDir will be the base directory if a relative path is supplied.
     *
     * @param path Full path of the file.  May be a relative path.
     */
    public File file(String path) {
        File result = new File(path);
        if (result.isAbsolute()) {
            return result;
        } else {
            return new File(testDir, path);
        }
    }

    /**
     * Returns the NDK folder as built from the Android source tree.
     */
    private static File findNdkDir() {
        String androidHome = System.getenv("ANDROID_NDK_HOME");
        if (androidHome != null) {
            File f = new File(androidHome);
            if (f.isDirectory()) {
                return f;
            } else {
                System.out.println("Failed to find NDK in ANDROID_NDK_HOME=" + androidHome);
            }
        }
        return null;
    }

    /**
     * Returns a Gradle project Connection
     */
    @NonNull
    private ProjectConnection getProjectConnection() {
        GradleConnector connector = GradleConnector.newConnector();

        // Limit daemon idle time for tests. 10 seconds is enough for another test
        // to start and reuse the daemon.
        ((DefaultGradleConnector) connector).daemonMaxIdleTime(10, TimeUnit.SECONDS);

        return connector
                .useGradleVersion(targetGradleVersion)
                .forProjectDirectory(testDir)
                .connect();
    }

    private static File createLocalProp(
            @NonNull File project,
            @NonNull File sdkDir,
            @Nullable File ndkDir) throws IOException, StreamException {
        ProjectPropertiesWorkingCopy localProp = ProjectProperties.create(
                project.getAbsolutePath(), ProjectProperties.PropertyType.LOCAL);
        localProp.setProperty(ProjectProperties.PROPERTY_SDK, sdkDir.getAbsolutePath());
        if (ndkDir != null) {
            localProp.setProperty(ProjectProperties.PROPERTY_NDK, ndkDir.getAbsolutePath());
        }
        localProp.save();

        return (File) localProp.getFile();
    }

    private void createGradleProp() throws IOException {
        if (gradleProperties.isEmpty()) {
            return;
        }
        File propertyFile = file("gradle.properties");
        Files.write(Joiner.on('\n').join(gradleProperties), propertyFile, Charset.defaultCharset());
    }

    public static void assumeLocalDevice() {
        Assume.assumeTrue(
                "Install task not run against device provider",
                GradleTestProject.REMOTE_TEST_PROVIDER == null);
    }

    public static void assumeBuildToolsAtLeast(int major) {
        assumeBuildToolsAtLeast(
                major, FullRevision.IMPLICIT_MINOR_REV, FullRevision.IMPLICIT_MICRO_REV);
    }
    public static void assumeBuildToolsAtLeast(int major, int minor, int micro) {
        FullRevision currentVersion = FullRevision.parseRevision(DEFAULT_BUILD_TOOL_VERSION);
        Assume.assumeTrue("Test is only applicable to build tools > " + major,
                new FullRevision(major, minor, micro).compareTo(currentVersion) < 0);
    }
}

redpajama_set_name: RedPajamaGithub


Over his collegiate career at Ole Miss, former baseball standout Stephen Head helped lead the Rebels both at the plate and on the mound, but after spending six years in the minor league system as a position player, Head decided it was time for a change.
This season, he started from scratch as he now focuses solely on pitching.
Throughout his years in the minors, Head saw guys make it to the major leagues that he knew he could pitch just as well as, if not better than.
Head is currently on the roster for the Tri-City Dust Devils, the Class A Short-Season affiliate of the Colorado Rockies, and although he has proven his ability on the baseball diamond time and time again, Head isn't worried about the actual pitching as much as he is about how to pitch correctly.
Another aspect of being a professional pitcher Head had to get accustomed to was throwing nearly every day in the offseason.
The season for Head and the Dust Devils began Sunday, and it was not long before Head was called upon to see if his hard work in the offseason had paid off.
In his first outing, Head gave up no runs on one hit with five strikeouts in three innings pitched. He used his experiences of pitching in the Southeastern Conference to get him ready for his first appearance as a professional pitcher.
"That was my first legitimate professional game experience (as a pitcher). It went well. I was effective with just my fastball and changeup. Those were the only two pitches I threw, and I threw them for strikes.
Head hopes to rekindle the success he had while wearing the red and blue of Ole Miss, and make it to his goal of the major leagues.
During his tenure at Ole Miss, Head set numerous school records on his way to being named an All-American three different times, the most for anyone in school history.
After batting a team high .337 and recording a school-record 13 saves on the mound in his freshman season, Head was named National Freshman of the Year by Collegiate Baseball.
In 2005, Head helped the Rebels to a 48-20 record and reach their first ever appearance in a Super Regional, which they lost in a heart-pounding three-game series to eventual national champion Texas. He batted .331 with 18 home runs and 68 RBI and had a record of 7-3 with 8 saves and an ERA of 2.54 for the season.
Although Head and the Rebels came up just short against Texas, he believes there is a bright future for Ole Miss baseball despite the lackluster 2011 season.
As for the timetable for Head to make it as a big-time professional pitcher, he said it best.


text:
Della Volpe named NFCA's 2019 Humanitarian Award recipient
LOUISVILLE, Ky. —The National Fastpitch Coaches Association is pleased to announce that Joelle Della Volpe, head coach at St. Mary High School (N.J.), is the 2019 recipient of the Association's Humanitarian Award. Della Volpe is being recognized for her many charitable contributions to the softball and Essex County communities.
Partnering with the NFCA, Della Volpe successfully organized and coordinated the NFCA New Jersey High School Leadoff Classic, in tribute to the late Immaculate Heart Academy head coach and 2019 NFCA Hall of Fame inductee Anthony LaRezza. Aimed at celebrating LaRezza and the positive contributions he made to his players and fans, Della Volpe fulfilled his dream of starting a tournament that would help children, specifically those with cancer. In doing so, all proceeds from the tournament went to cancer-stricken children through Tackle Kids Cancer.
In 2016, Della Volpe started #ForLaRezza Day, a social media campaign that allowed fans and players, who had worked, met, or just knew LaRezza, share special moments through images and videos. Additionally, she organized a cancer walk in his honor, taking place on April 25 each year.
"Generous and energetic, Joelle is an exceptionally-effective leader and humanitarian; she can galvanize others to action, as well as taking the lead herself," said Blair Academy head coach Carolyn Conforti-Browse. "If there is one quality that I suspect best qualifies her for this award, it is that Joelle does not wait for someone else to do the job; when she sees a need she moves to help. She is a true leader and embodies commitment."
Conforti-Browse first came across Della Volpe's humanitarian work in 2012. While the head coach at Hackensack High School, Della Volpe organized a season-wide fundraiser for former Bergen County softball player Erin Kelly, who contracted a rare illness, acute transverse Mellitus, which resulted in sudden and devastating paralysis. The fundraiser raised over $100,000 for Kelly and her family.
"Joelle has always had a passion and drive to help and mentor young women in the sport of softball and in life," said Kimberly Lynch, assistant at Western Connecticut State University. "Joelle is a dedicated wife, mother, teacher, coach and mentor. She is the first person that comes to mind when I think of someone who is always willing to help. Joelle is a true humanitarian."
According to Conforti-Browse, Della Volpe makes life better for folks when they are facing tough struggles. She volunteers with the New Jersey FMBA, a charity fund for families of fallen firefighters, and engineers an annual sports equipment drive for donations to impoverished families in greater Essex and Passaic counties.
Della Volpe, the CEO of source4coaches, started the free mentoring program, which offers wellness clinics for new coaches to learn about mental awareness and fitness of athletes. She also assists high school students with finding and applying to colleges, the registration process for Essex County Schools of Technology and starting the process of getting into the local union.
"I have been doing this for some time now," Della Volpe said. "I derive so much joy doing as I believe in sharing the knowledge I have. It is a small way of giving back to the community that has given me so much."
The NFCA's Humanitarian Award recognizes a member coach who has selflessly dedicated time toward the long-term betterment of the community and/or engaged in charitable activities in the service of others. Della Volpe will be honored in front of her peers on Dec. 7 during the NFCA Awards Brunch at the 2019 NFCA Convention, held Dec. 4-7 at Harrah's Resort Atlantic City.

redpajama_set_name: RedPajamaCommonCrawl


text:
Weekly schedule of the Conference on Disarmament
Unofficial Disarmament Meeting Planner 2019
Information about United Nations Fellowships on Disarmament
United Nations Fellowships on Disarmament
Disarmament in Geneva
Disarmament and non-proliferation remain indispensable tools to help create a security environment favourable to ensuring human development, as enshrined in the letter and the spirit of the Charter of the United Nations. UNOG is a center venue for international diplomacy in this field. It is home to the Conference on Disarmament - the sole multilateral disarmament negotiating body - and provides, through the Geneva Branch of the Office for Disarmament Affairs, substantive and organisational support to a wide range of multilateral disarmament agreements. In addition, UNOG hosts a large number of disarmament-related conferences.
The Conference on Disarmament (CD), established in 1979 as the single multilateral disarmament negotiating forum of the international community, following the first Special Session on Disarmament (SSOD I) of the United Nations General Assembly held in 1978. The Director-General of UNOG is the Secretary-General of the Conference on Disarmament as well as the Personal Representative of the UN Secretary-General to the CD.
Under the Anti-Personnel Landmine Convention (APLC), the United Nations Secretariat has been given a number of tasks, which are carried out by the Geneva Branch of the Office for Disarmament Affairs. These include, inter alia, collecting Article 7 reports on measures taken to implement the Convention and updating the relevant database, maintaining the Article 8 (9) List of qualified experts, as well as the organisation of the meetings of States parties, which take place alternatively in a mine affected country and at the United Nations Office at Geneva.
As a result of prolonged efforts by the international community to establish a new instrument that would supplement the 1925 Geneva Protocol, the Biological Weapons Convention (BWC), the first multilateral disarmament treaty banning the production and use of an entire category of weapons, was opened for signature on 10 April 1972 and entered into force on 26 March 1975. All the meetings related to this instrument are currently being held in UNOG, and are serviced by the BWC Implementation Support Unit in the Geneva Branch of the Office for Disarmament Affairs.
The Convention on Cluster Munitions was concluded by the Dublin Diplomatic Conference on Cluster Munitions at Dublin on 30 May 2008. The tasks performed by the Secretary General of the United Nations are mandated in the text of the conventions and in relevant General Assembly resolutions. These include the collection and dissemination of national transparency reports (Article 7), the facilitation of clarification of compliance (Article 8); and the convening of the Meetings of States Parties (Article 11) and Review Conferences (Article 12).
The Convention on Prohibitions or Restrictions on the Use of Certain Conventional Weapons Which May Be Deemed to Be Excessively Injurious or to Have Indiscriminate Effects, also known as the Convention on Certain Conventional Weapons (CCW) or Inhumane Weapons Convention, comprises a convention and five protocols, which ban or restrict the use of various types of weapons that are considered to cause unnecessary suffering or that affect either soldiers or civilians indiscriminately. The weapons currently covered include weapons leaving undetectable fragments in the human body (Protocol I), mines, booby-traps and other devices (Protocol II), incendiary weapons (Protocol III), blinding laser weapons (Protocol IV) and explosive remnants of war (Protocol V). All the meetings related to this convention are currently being held in UNOG, and are serviced by the Geneva Branch of the Office for Disarmament Affairs.
In the field of Small Arms and Light Weapons (SALW) and of the Arms Trade Treaty (ATT), the Geneva Branch ensures both the liaison with the Office for Disarmament Affairs in New York as well as with the Geneva-based Non-Governmental and International Organizations, and represents the Office in related meetings held in Geneva.
In addition, UNOG is occasionally hosting other meetings related to disarmament and non-proliferation instruments such as certain sessions of the Advisory Board on Disarmament Matters, and certain sessions of the Preparatory Committee of the Review Conferences of the Nuclear Non-Proliferation Treaty (NPT), expert panels and seminars.
Geneva Branch Contacts
United Nations Office for Disarmament Affairs - New York
Disarmament and Non-Proliferation Education
Experience the Conference through the eyes of the diplomats
Never visited the UN building in Geneva? Join us on this drone journey around the Palais de Nations.
View AllPress Releases & Announcements


text:
President Uchtdorf lauded as a community builder
People attend the 48th Annual Humanitarian Awards event at the Rail Event Center in Salt Lake City on Thursday, March 19, 2015. Photo: Laura Seitz, Deseret News
President Dieter F. Uchtdorf, second counselor in the First Presidency of The Church of Jesus Christ of Latter-day Saints, Gina Cornia, Executive Director Utahns Against Hunger, and Professor Ronald F. Coleman, History Professor at the University of Utah, gather at the 48th Annual Humanitarian Awards event at the Rail Event Center in Salt Lake City on Thursday, March 19, 2015. Photo: Laura Seitz, Deseret News
Gina Cornia, Executive Director Utahns Against Hunger, Harriet Uchtdorf, President Dieter F. Uchtdorf, second counselor in the First Presidency of The Church of Jesus Christ of Latter-day Saints, and Professor Ronald F. Coleman, History Professor at the University of Utah, gather at the 48th Annual Humanitarian Awards event at the Rail Event Center in Salt Lake City on Thursday, March 19, 2015. Photo: Laura Seitz, Deseret News
Pamela Atkinson, advocate for the homeless, chats with Harriet Uchtdorf and President Dieter F. Uchtdorf, second counselor in the First Presidency of The Church of Jesus Christ of Latter-day Saints, at the 48th Annual Humanitarian Awards event at the Rail Event Center in Salt Lake City on Thursday, March 19, 2015. Photo: Laura Seitz, Deseret News
President Dieter F. Uchtdorf, second counselor in the First Presidency of The Church of Jesus Christ of Latter-day Saints, Gina Cornia, Executive Director of Utahns Against Hunger, and Professor Ronald F. Coleman, History Professor at the University of Utah, gather at the 48th Annual Humanitarian Awards event at the Rail Event Center in Salt Lake City on Thursday, March 19, 2015. Photo: Laura Seitz, Deseret News
Harriet Uchtdorf, Professor Ronald F. Coleman, History Professor at the University of Utah, President Dieter F. Uchtdorf, second counselor in the First Presidency of The Church of Jesus Christ of Latter-day Saints, and Gina Cornia, Executive Director Utahns Against Hunger, gather at the 48th Annual Humanitarian Awards event at the Rail Event Center in Salt Lake City on Thursday, March 19, 2015. Photo: Laura Seitz, Deseret News
By Jason Swensen
LDS Church News
The Inclusion Center for Community and Justice honored President Dieter F. Uchtdorf on March 19 for his ongoing commitment to bring people of all backgrounds together and to better their communities.
President Uchtdorf, second counselor in the First Presidency, was presented with the organization's Humanitarian Award during its annual awards social in Salt Lake City.
"President Uchtdorf is someone who transforms the world around him," said Paul Draper, the evening's emcee. "He is someone who leads people, mentors them and inspires them to be greater in their own lives and communities."
The Inclusion Center for Community and Justice is a human rights organization charged with building communities of respect and inclusion across all racial, religious and class lines. The center offers solutions through conflict resolution, education, advocacy and empowerment.
For almost a century, the Inclusion Center has recognized individuals and organizations whose efforts and actions help build inclusive communities.
Having been a refugee twice in his life, President Uchtdorf can relate to those who are hungry, feel discriminated against, bullied or talked down to.
Born in Ostrava, in the former Czechoslovakia, in 1940, the backdrop of his childhood was the devastation of war. He saw how innocent people suffered because of the cruel decisions and actions of others. When his father, Karl, was conscripted into the German army and Stalin's forces were pushing in from the east, his mother, Hilde, left their possessions behind and fled westward with their children. After the war, the family was reunited at Zwickau, Germany. Since Karl had opposed both the Nazi and communist regimes the family, once again, left behind their possessions and made their way to safety in Frankfurt, Germany.
Of this period President Uchtdorf has said: "We were refugees with an uncertain future. … I played in bombed-out houses and grew up with the ever-present consequences of a lost war and the awareness that my own country had inflicted terrible pain on many nations during the horrific World War II" (October 2002 general conference; Liahona and Ensign magazines, November 2002).
In his remarks at the awards ceremony, President Uchtdorf said the Church is making "great efforts" to make a difference for good in the lives of people across the world. He spoke of his support of the Inclusion Center's efforts to battle prejudices, bigotry and discrimination. He noted that he had spoken out against destructive actions such as bullying and gossiping in a recent general conference address.
His counsel then — and now — to anyone involved in such behavior? "Stop it!"
"We must move forward and lift up our fellow men, whoever they are," he said. "We must invite them in to our circles, wherever they are, and do it in a way that they do not feel excluded.
"We are all brothers and sisters," he added. "We are all children of our Heavenly Father."
At the conclusion of his remarks, President Uchtdorf presented the Inclusion Center leaders with a check of $10,000 as a gift from the Church.
Also honored with Humanitarian Awards at the event was University of Utah history professor Ronald F. Coleman; the advocacy group Utahns Against Hunger; and a pair of Inclusion Center volunteers.
In his remarks, Professor Coleman said he came to the Beehive State more than four decades ago to play football at the University of Utah. There he was mentored by many generous people who put him on his academic and professional path.
"No one gets through this journey of life alone," said the professor, who has published much of his research on the rich history of African-Americans in Utah.
Utah Against Hunger was also lauded for its tireless work to ensure that Utah families in need do not go hungry. The organization's executive director, Gina Cornia, accepted the award. She invited all to take action and do what they can so people have sufficient food.
"The road to social justice may be long and it may be hard, but it is worth it," she said.
The Inclusion Center also recognized a pair of volunteers — Levi Webb and Zayla Long — for their exemplary service.
The proceeds from the event — including the donation from the Church — will provide scholarships for youth and local schools to attend the organization's human relations leadership retreats and workshops. Conducted in the Utah mountains, the retreats bring together diverse populations and build connections and unity through empathy and respect.
[email protected] @JNSwensen


text:
package com.github.q120011676.xhttp;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

/**
 * Created by say on 1/26/16.
 */
public class C {
    public static void main(String[] args) throws UnsupportedEncodingException {
        System.out.println(URLEncoder.encode("=tps发起post请","UTF-8"));
    }
}


text:
Nicolae Bejenaru (born 30 May 1968) is a Romanian gymnast. He competed at the 1988 Summer Olympics and the 1992 Summer Olympics.

References

1968 births
Living people
Romanian male artistic gymnasts
Olympic gymnasts of Romania
Gymnasts at the 1988 Summer Olympics
Gymnasts at the 1992 Summer Olympics
Gymnasts from Bucharest
20th-century Romanian people

redpajama_set_name: RedPajamaWikipedia


Here is a full detailed guide to Download and Install Lineage OS 14.1 On UMIDIGI S2 Lite Nougat Rom. Good News for all UMIDIGI S2 Lite Customer. Today you can enjoy the build of Lineage OS 14.1 on UMIDIGI S2 Lite (CM14.1 base ROM). Android 7.1.2 Nougat comes with handful of features such as App Shortcuts, Multi Window support, restart setting to power menu and many more.
As CyanogenMod is dead and now the same team gave birth to new Lineage OS. Unofficial Lineage OS builds Lineage OS 14.1 is now available for UMIDIGI S2 Lite. UMIDIGI S2 Lite users can Install and experience the stock Android UI. This is a leaked unofficial build, so don't expect everything to be fully working, but it does seem to be ready for daily use.


text:
Q: Import Maps not using precompiled JavaScript assets in pipeline in production environment only (Rails 7) Anyone managed to wrap their head around importmaps in Rails 7? I have a headscratcher.
If I run ./bin/importmap json in development, I get this (as expected):
{
  "imports": {
    "application": "/assets/application-a7fd3fc58be844f89656edec1ec73e18f9ab627e54b2aea67a97aad4613b6305.js",
    "@hotwired/turbo-rails": "/assets/turbo.min-96cbf52c71021ba210235aaeec4720012d2c1df7d2dab3770cfa49eea3bb09da.js",
    "@hotwired/stimulus": "/assets/stimulus.min-900648768bd96f3faeba359cf33c1bd01ca424ca4d2d05f36a5d8345112ae93c.js",
    "@hotwired/stimulus-loading": "/assets/stimulus-loading-1fc59770fb1654500044afd3f5f6d7d00800e5be36746d55b94a2963a7a228aa.js",
    "stimulus": "https://ga.jspm.io/npm:stimulus@2.0.0/dist/stimulus.umd.js",
    "stimulus-use": "https://ga.jspm.io/npm:stimulus-use@0.41.0/dist/index.js",
    "hotkeys-js": "https://ga.jspm.io/npm:hotkeys-js@3.8.8/dist/hotkeys.esm.js",
    "trix": "/assets/trix-1563ff9c10f74e143b3ded40a8458497eaf2f87a648a5cbbfebdb7dec3447a5e.js",
    "@rails/actiontext": "/assets/actiontext-28c61f5197c204db043317a8f8826a87ab31495b741f854d307ca36122deefce.js"
  }
}

...and all my JavaScript works fine.
If, however, I run the same command in production, I get the following:
{
  "imports": {
    "application": "/application.js",
    "@hotwired/turbo-rails": "/turbo.min.js",
    "@hotwired/stimulus": "/stimulus.min.js",
    "@hotwired/stimulus-loading": "/stimulus-loading.js",
    "stimulus": "https://ga.jspm.io/npm:stimulus@2.0.0/dist/stimulus.umd.js",
    "stimulus-use": "https://ga.jspm.io/npm:stimulus-use@0.41.0/dist/index.js",
    "hotkeys-js": "https://ga.jspm.io/npm:hotkeys-js@3.8.8/dist/hotkeys.esm.js",
    "trix": "/trix.js",
    "@rails/actiontext": "/actiontext.js"
  }
}

...and nothing (JavaScript) works, because requesting /application.js returns a 404, though curiously I can see the assets compiling to fingerprinted files within the /assets directory on deploy - it's just then the app tries to use the original scripts, which (being in the app/javascript directory) are not served for the app.
FWIW, I am using render.com for deployment (though the same issue occurs in Heroku). Build script as follows:
#!/usr/bin/env bash
# exit on error
set -o errexit

bundle install
bundle exec rake assets:precompile
bundle exec rake assets:clean
bundle exec rake db:migrate

and in my production.rb I have the following (as per render docs):
config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? || ENV['RENDER'].present?

...which (in production) evaluates to true.
Any thoughts?

A: Encountered a similar issue to yours, given that like me you've come from an older rails version (probably tried to use a package manager or js-bundling), You probably have this configuration somewhere
# REMOVE THIS
Rails.application.config.assets.paths << Rails.root.join('app', 'javascript', 'controllers')

Removing that fixed my issue. My guess is this somehow messes with what importmap trying to do.

redpajama_set_name: RedPajamaStackExchange