Esempio n. 1
0
        private IEnumerable <string> CollectOutputs(BuildUpToDateCheckLogger logger, State state)
        {
            if (state.CustomOutputs.Count != 0)
            {
                logger.Verbose("Adding " + UpToDateCheckOutput.SchemaName + " outputs:");

                // TODO remove pragmas when https://github.com/dotnet/roslyn/issues/37040 is fixed
#pragma warning disable CS8622
                foreach (string output in state.CustomOutputs.Select(_configuredProject.UnconfiguredProject.MakeRooted))
#pragma warning restore CS8622
                {
                    logger.Verbose("    '{0}'", output);
                    yield return(output);
                }
            }

            if (state.BuiltOutputs.Count != 0)
            {
                logger.Verbose("Adding " + UpToDateCheckBuilt.SchemaName + " outputs:");

                // TODO remove pragmas when https://github.com/dotnet/roslyn/issues/37040 is fixed
#pragma warning disable CS8622
                foreach (string output in state.BuiltOutputs.Select(_configuredProject.UnconfiguredProject.MakeRooted))
#pragma warning restore CS8622
                {
                    logger.Verbose("    '{0}'", output);
                    yield return(output);
                }
            }
        }
Esempio n. 2
0
        private bool CheckMarkers(BuildUpToDateCheckLogger logger, IDictionary <string, DateTime> timestampCache, State state)
        {
            // Reference assembly copy markers are strange. The property is always going to be present on
            // references to SDK-based projects, regardless of whether or not those referenced projects
            // will actually produce a marker. And an item always will be present in an SDK-based project,
            // regardless of whether or not the project produces a marker. So, basically, we only check
            // here if the project actually produced a marker and we only check it against references that
            // actually produced a marker.

            if (string.IsNullOrWhiteSpace(state.MarkerFile) || !state.CopyReferenceInputs.Any())
            {
                return(true);
            }

            string markerFile = _configuredProject.UnconfiguredProject.MakeRooted(state.MarkerFile);

            logger.Verbose("Adding input reference copy markers:");

            foreach (string referenceMarkerFile in state.CopyReferenceInputs)
            {
                logger.Verbose("    '{0}'", referenceMarkerFile);
            }

            logger.Verbose("Adding output reference copy marker:");
            logger.Verbose("    '{0}'", markerFile);

            (DateTime latestInputMarkerTime, string?latestInputMarkerPath) = GetLatestInput(state.CopyReferenceInputs, timestampCache);

            if (latestInputMarkerPath != null)
            {
                logger.Info("Latest write timestamp on input marker is {0} on '{1}'.", latestInputMarkerTime, latestInputMarkerPath);
            }
            else
            {
                logger.Info("No input markers exist, skipping marker check.");
                return(true);
            }

            DateTime?outputMarkerTime = GetTimestampUtc(markerFile, timestampCache);

            if (outputMarkerTime != null)
            {
                logger.Info("Write timestamp on output marker is {0} on '{1}'.", outputMarkerTime, markerFile);
            }
            else
            {
                logger.Info("Output marker '{0}' does not exist, skipping marker check.", markerFile);
                return(true);
            }

            if (outputMarkerTime < latestInputMarkerTime)
            {
                return(Fail(logger, "Marker", "Input marker is newer than output marker, not up to date."));
            }

            return(true);
        }
Esempio n. 3
0
        // Reference assembly copy markers are strange. The property is always going to be present on
        // references to SDK-based projects, regardless of whether or not those referenced projects
        // will actually produce a marker. And an item always will be present in an SDK-based project,
        // regardless of whether or not the project produces a marker. So, basically, we only check
        // here if the project actually produced a marker and we only check it against references that
        // actually produced a marker.
        private bool CheckMarkers(BuildUpToDateCheckLogger logger, IDictionary <string, DateTime> timestampCache, State state)
        {
            if (string.IsNullOrWhiteSpace(state.MarkerFile) || !state.CopyReferenceInputs.Any())
            {
                return(true);
            }

            string markerFile = _configuredProject.UnconfiguredProject.MakeRooted(state.MarkerFile);

            logger.Verbose("Adding input reference copy markers:");

            foreach (string referenceMarkerFile in state.CopyReferenceInputs)
            {
                logger.Verbose("    '{0}'", referenceMarkerFile);
            }

            logger.Verbose("Adding output reference copy marker:");
            logger.Verbose("    '{0}'", markerFile);

            (DateTime latestInputMarkerTime, string?latestInputMarkerPath) = GetLatestInput(state.CopyReferenceInputs, timestampCache);

            if (latestInputMarkerPath != null)
            {
                logger.Info("Latest write timestamp on input marker is {0} on '{1}'.", latestInputMarkerTime, latestInputMarkerPath);
            }
            else
            {
                logger.Info("No input markers exist, skipping marker check.");
                return(true);
            }

            DateTime?outputMarkerTime = GetTimestampUtc(markerFile, timestampCache);

            if (outputMarkerTime != null)
            {
                logger.Info("Write timestamp on output marker is {0} on '{1}'.", outputMarkerTime, markerFile);
            }
            else
            {
                logger.Info("Output marker '{0}' does not exist, skipping marker check.", markerFile);
                return(true);
            }

            if (outputMarkerTime < latestInputMarkerTime)
            {
                return(Fail(logger, "Marker", "Input marker is newer than output marker, not up to date."));
            }

            return(true);
        }
Esempio n. 4
0
        public Task <bool> IsUpToDateAsync(BuildAction buildAction, TextWriter logWriter, CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();

            return(ExecuteUnderLockAsync(IsUpToDateInternalAsync, cancellationToken));

            async Task <bool> IsUpToDateInternalAsync(CancellationToken token)
            {
                token.ThrowIfCancellationRequested();

                var sw = Stopwatch.StartNew();

                await InitializeAsync(token);

                LogLevel requestedLogLevel = await _projectSystemOptions.GetFastUpToDateLoggingLevelAsync(token);

                var logger = new BuildUpToDateCheckLogger(logWriter, requestedLogLevel, _configuredProject.UnconfiguredProject.FullPath);

                try
                {
                    State state = _state;

                    if (!CheckGlobalConditions(buildAction, logger, state))
                    {
                        return(false);
                    }

                    // Short-lived cache of timestamp by path
                    var timestampCache = new Dictionary <string, DateTime>(StringComparers.Paths);

                    if (!CheckInputsAndOutputs(logger, timestampCache, state) ||
                        !CheckMarkers(logger, timestampCache, state) ||
                        !CheckCopyToOutputDirectoryFiles(logger, timestampCache, state) ||
                        !CheckCopiedOutputFiles(logger, timestampCache, state))
                    {
                        return(false);
                    }

                    _telemetryService.PostEvent(TelemetryEventName.UpToDateCheckSuccess);
                    logger.Info("Project is up to date.");
                    return(true);
                }
                finally
                {
                    lock (_stateLock)
                    {
                        _state = _state.WithLastCheckedAtUtc(DateTime.UtcNow);
                    }

                    logger.Verbose("Up to date check completed in {0:N1} ms", sw.Elapsed.TotalMilliseconds);
                }
            }
        }
Esempio n. 5
0
        private IEnumerable <string> CollectOutputs(BuildUpToDateCheckLogger logger, State state)
        {
            if (state.CustomOutputs.Count != 0)
            {
                logger.Verbose("Adding " + UpToDateCheckOutput.SchemaName + " outputs:");

                foreach (string output in state.CustomOutputs.Select(_configuredProject.UnconfiguredProject.MakeRooted))
                {
                    logger.Verbose("    '{0}'", output);
                    yield return(output);
                }
            }

            if (state.BuiltOutputs.Count != 0)
            {
                logger.Verbose("Adding " + UpToDateCheckBuilt.SchemaName + " outputs:");

                foreach (string output in state.BuiltOutputs.Select(_configuredProject.UnconfiguredProject.MakeRooted))
                {
                    logger.Verbose("    '{0}'", output);
                    yield return(output);
                }
            }
        }
Esempio n. 6
0
        private IEnumerable <string> CollectInputs(BuildUpToDateCheckLogger logger, State state)
        {
            if (state.MSBuildProjectFullPath != null)
            {
                logger.Verbose("Adding project file inputs:");
                logger.Verbose("    '{0}'", state.MSBuildProjectFullPath);
                yield return(state.MSBuildProjectFullPath);
            }

            if (state.NewestImportInput != null)
            {
                logger.Verbose("Adding newest import input:");
                logger.Verbose("    '{0}'", state.NewestImportInput);
                yield return(state.NewestImportInput);
            }

            foreach ((string itemType, ImmutableHashSet <(string path, string?link, CopyToOutputDirectoryType copyType)> changes) in state.ItemsByItemType)
            {
                if (!NonCompilationItemTypes.Contains(itemType))
                {
                    logger.Verbose("Adding {0} inputs:", itemType);

                    foreach (string input in changes.Select(item => _configuredProject.UnconfiguredProject.MakeRooted(item.path)))
                    {
                        logger.Verbose("    '{0}'", input);
                        yield return(input);
                    }
                }
            }

            if (state.AnalyzerReferences.Count != 0)
            {
                logger.Verbose("Adding " + ResolvedAnalyzerReference.SchemaName + " inputs:");
                foreach (string input in state.AnalyzerReferences)
                {
                    logger.Verbose("    '{0}'", input);
                    yield return(input);
                }
            }

            if (state.CompilationReferences.Count != 0)
            {
                logger.Verbose("Adding " + ResolvedCompilationReference.SchemaName + " inputs:");
                foreach (string input in state.CompilationReferences)
                {
                    logger.Verbose("    '{0}'", input);
                    yield return(input);
                }
            }

            if (state.CustomInputs.Count != 0)
            {
                logger.Verbose("Adding " + UpToDateCheckInput.SchemaName + " inputs:");
                foreach (string input in state.CustomInputs.Select(_configuredProject.UnconfiguredProject.MakeRooted))
                {
                    logger.Verbose("    '{0}'", input);
                    yield return(input);
                }
            }
        }