/// <summary>
        /// Run the requested executable and produce a report of the results.
        /// </summary>
        /// <param name="executionRequest">The execution request.</param>
        /// <returns>A report of the results.</returns>
        private CloudExecutionReport RunAnExecutable(CloudExecutionRequest executionRequest)
        {
            // REVIEW: How/whether to use this.
            BuildObject diagnosticsBase = new BuildObject(Path.Combine("nuobj", "diagnostics", "process"));

            // Prep working directory with input files and output dirs.
            // TODO: The below will throw cache exceptions if something
            // isn't there (they should all be though).  Need to catch
            // these and fail the execution request when this happens.
            WorkingDirectory workingDirectory = new WorkingDirectory(this.virtualIronRoot);

            foreach (BuildObjectValuePointer inputFile in executionRequest.InputFileMappings)
            {
                // REVIEW: How to determine cache container here.
                ItemCacheContainer container = ItemCacheContainer.Sources;
                if (this.multiplexedItemCache.GetItemSize(container, inputFile.ObjectHash) == -1)
                {
                    container = ItemCacheContainer.Objects;
                }

                // TODO: Move path/directory manipulation code into
                // WorkingDirectory and/or ItemCache.
                string inputFilePath = workingDirectory.PathTo(inputFile.RelativePath);
                Directory.CreateDirectory(Path.GetDirectoryName(inputFilePath));  // REVIEW: Still neeeded?
                this.multiplexedItemCache.FetchItemToFile(
                    container,
                    inputFile.ObjectHash,
                    inputFilePath);
            }

            foreach (BuildObject outputFile in executionRequest.OutputFiles)
            {
                workingDirectory.CreateDirectoryFor(outputFile);
            }

            // Run executable.
            ProcessInvoker pinv = new ProcessInvoker(
                workingDirectory,
                executionRequest.Executable,
                new string[] { executionRequest.Arguments },
                diagnosticsBase,
                null,  // This is captureStdout.  TODO: Should cleanup how this is used in ProcessInvoker.
                null); // This is dbgText.  REVIEW: How/whether to use this.

            // When ProcessInvoker's constructor returns, the process has
            // finished running.
            Console.WriteLine("Request {0} completed in {1} seconds.", executionRequest.Identifier, pinv.CpuTime);

            // Store output files in the (cloud) item cache, and create a
            // list of the mappings.
            List <BuildObjectValuePointer> outputFileMappings = new List <BuildObjectValuePointer>();

            foreach (BuildObject outFile in executionRequest.OutputFiles)
            {
                if (File.Exists(workingDirectory.PathTo(outFile)))
                {
                    string fileHash = Util.hashFilesystemPath(workingDirectory.PathTo(outFile));
                    Util.Assert(!string.IsNullOrEmpty(fileHash));

                    // Note we explicitly write to the cloud cache here.
                    this.cloudCache.StoreItemFromFile(ItemCacheContainer.Objects, fileHash, workingDirectory.PathTo(outFile));
                    outputFileMappings.Add(new BuildObjectValuePointer(fileHash, outFile.getRelativePath()));
                }
            }

            // Collect the results into a report.
            CloudExecutionReport report = new CloudExecutionReport(
                executionRequest.Identifier,
                CloudExecutionReport.StatusCode.Completed,
                pinv.ExitCode,
                pinv.GetStdout(),
                pinv.GetStderr(),
                pinv.CpuTime,
                outputFileMappings);

            return(report);
        }