예제 #1
0
        public async ValueTask <object?> Run(string solutionFilePath, string projectName, CancellationToken cancellationToken = default)
        {
            _logger.LogDebug("Loading solution from {0}", solutionFilePath);
            var solution = await _solutionFactory.ParseFromFileAsync(solutionFilePath).ConfigureAwait(false);

            _logger.LogDebug("Found solution");

            _logger.LogDebug("Creating build order");

            var transitiveDependencies = ProjectDependencyOrganizer
                                         .GetTransitiveDependencies(solution.Projects, projectName);
            var buildOrder = ProjectDependencyOrganizer
                             .CreateBuildOrder(transitiveDependencies);

            if (_logger.IsEnabled(LogLevel.Debug))
            {
                _logger.LogDebug($"Build order is {string.Join(",", buildOrder.Select(x => x.Name))}");
            }

            _logger.LogDebug("Loading dependencies");
            var assemblyLoadContext = new AssemblyLoadContext(name: null, isCollectible: true);

            try
            {
                var projects = await LoadProjects(
                    solution,
                    buildOrder,
                    assemblyLoadContext,
                    cancellationToken);

                _logger.LogDebug("Compiling projects");
                Assembly?assembly = null;
                foreach (var project in projects)
                {
                    assembly = TryCompileProjectInMemory(
                        assemblyLoadContext,
                        project);

                    if (assembly is null)
                    {
                        return(null);
                    }
                }

                if (assembly !.EntryPoint is null)
                {
                    throw new FlcException($"{projectName} does not have a Main method suitable for entry");
                }

                _logger.LogDebug("Running {0}", projectName);
                return(assembly.EntryPoint.Invoke(null, null));
            }
            finally
            {
                assemblyLoadContext.Unload();
            }
        }
예제 #2
0
        public void ShouldDetectSimpleCycles()
        {
            var projects = new[]
            {
                Project("p1", "p2"),
                Project("p2", "p1"),
            };

            Assert.Throws <FlcException>(() => ProjectDependencyOrganizer.CreateBuildOrder(projects).ToList());
        }
예제 #3
0
        public void ShouldOrderDependenciesInPassedInOrderWhenMultipleAvailable()
        {
            var projects = new[]
            {
                Project("p1"),
                Project("p4", "p2", "p3"),
                Project("p2", "p1"),
                Project("p3", "p1"),
            };

            Assert.Equal(
                new[] { projects[0], projects[2], projects[3], projects[1] },
                ProjectDependencyOrganizer.CreateBuildOrder(projects));
        }
예제 #4
0
        public void ShouldIgnoreNonProjectReferences()
        {
            var projects = new[]
            {
                new ProjectInfo(
                    "p1",
                    new Version(0, 0),
                    ImmutableArray.Create(""),
                    references: ImmutableArray.Create(new Reference(Reference.ReferenceType.Assembly, "", ""))),
            };

            Assert.Equal(
                projects,
                ProjectDependencyOrganizer.CreateBuildOrder(projects));
        }
예제 #5
0
        public async ValueTask <bool> Build(string solutionFilePath, string outputDirectory, bool outputCSharp, bool test, CancellationToken cancellationToken = default)
        {
            _logger.LogDebug("Loading solution from {0}", solutionFilePath);
            var solution = await _solutionFactory.ParseFromFileAsync(solutionFilePath).ConfigureAwait(false);

            _logger.LogDebug("Found solution");

            _logger.LogDebug("Creating build order");
            var buildOrder = ProjectDependencyOrganizer.CreateBuildOrder(solution.Projects).ToList();

            if (_logger.IsEnabled(LogLevel.Debug))
            {
                _logger.LogDebug($"Build order is {string.Join(",", buildOrder.Select(x => x.Name))}");
            }

            _logger.LogDebug("Loading dependencies");
            var assemblyLoadContext = new AssemblyLoadContext(name: null, isCollectible: true);

            try
            {
                var projects = await LoadProjects(
                    solution,
                    buildOrder,
                    assemblyLoadContext,
                    cancellationToken);

                _logger.LogDebug("Compiling projects");
                var assemblies = new List <Assembly>();
                foreach (var project in projects)
                {
                    var assembly = await TryCompileProject(
                        outputDirectory,
                        outputCSharp,
                        assemblyLoadContext,
                        project,
                        cancellationToken);

                    if (assembly is null)
                    {
                        return(false);
                    }
                    assemblies.Add(assembly);
                }

                if (test)
                {
                    _logger.LogDebug("Running tests");
                    TestResult?testResults = null;
                    foreach (var(project, assembly) in buildOrder.Zip(assemblies))
                    {
                        if (project.IsTest)
                        {
                            var results = TestRunner.RunTests(assembly);
                            testResults = testResults is null ? results : results.Merge(testResults);
                        }
                    }

                    _logger.LogInformation(testResults?.GetMessage() ?? "No tests found to run");

                    if (testResults is TestResult.Failure)
                    {
                        return(false);
                    }
                }

                return(true);
            }
            finally
            {
                assemblyLoadContext.Unload();
            }
        }