private bool CheckGlobalConditions(Log log, DateTime lastCheckedAtUtc, UpToDateCheckImplicitConfiguredInput state) { if (!_tasksService.IsTaskQueueEmpty(ProjectCriticalOperation.Build)) { return(log.Fail("CriticalTasks", "Critical build tasks are running, not up to date.")); } if (state.LastVersionSeen == null || _configuredProject.ProjectVersion.CompareTo(state.LastVersionSeen) > 0) { return(log.Fail("ProjectInfoOutOfDate", "Project information is older than current project version, not up to date.")); } if (state.IsDisabled) { return(log.Fail("Disabled", "The 'DisableFastUpToDateCheck' property is true, not up to date.")); } if (lastCheckedAtUtc == DateTime.MinValue) { return(log.Fail("FirstRun", "The up-to-date check has not yet run for this project. Not up-to-date.")); } string copyAlwaysItemPath = state.ItemsByItemType.SelectMany(kvp => kvp.Value).FirstOrDefault(item => item.CopyType == CopyType.CopyAlways).Path; if (copyAlwaysItemPath != null) { return(log.Fail("CopyAlwaysItemExists", "Item '{0}' has CopyToOutputDirectory set to 'Always', not up to date.", _configuredProject.UnconfiguredProject.MakeRooted(copyAlwaysItemPath))); } return(true); }
private bool CheckGlobalConditions(Log log, DateTime lastCheckedAtUtc, UpToDateCheckImplicitConfiguredInput state) { if (!_tasksService.IsTaskQueueEmpty(ProjectCriticalOperation.Build)) { return(log.Fail("CriticalTasks", "Critical build tasks are running, not up to date.")); } if (state.LastVersionSeen == null || _configuredProject.ProjectVersion.CompareTo(state.LastVersionSeen) > 0) { return(log.Fail("ProjectInfoOutOfDate", "Project information is older than current project version, not up to date.")); } if (state.IsDisabled) { return(log.Fail("Disabled", "The 'DisableFastUpToDateCheck' property is true, not up to date.")); } if (lastCheckedAtUtc == DateTime.MinValue) { return(log.Fail("FirstRun", "The up-to-date check has not yet run for this project. Not up-to-date.")); } foreach ((_, ImmutableArray <(string Path, string?Link, CopyType CopyType)> items) in state.ItemsByItemType) { foreach ((string path, _, CopyType copyType) in items) { if (copyType == CopyType.CopyAlways) { return(log.Fail("CopyAlwaysItemExists", "Item '{0}' has CopyToOutputDirectory set to 'Always', not up to date.", _configuredProject.UnconfiguredProject.MakeRooted(path))); } } } return(true); }
private bool CheckGlobalConditions(Log log, DateTime lastCheckedAtUtc, UpToDateCheckImplicitConfiguredInput state) { if (!_tasksService.IsTaskQueueEmpty(ProjectCriticalOperation.Build)) { return(log.Fail("CriticalTasks", "Critical build tasks are running, not up to date.")); } if (state.IsDisabled) { return(log.Fail("Disabled", "The 'DisableFastUpToDateCheck' property is true, not up to date.")); } if (!state.WasStateRestored && lastCheckedAtUtc == DateTime.MinValue) { // We had no persisted state, and this is the first run. We cannot know if the project is up-to-date // or not, so schedule a build. return(log.Fail("FirstRun", "The up-to-date check has not yet run for this project. Not up-to-date.")); } foreach ((_, ImmutableArray <(string Path, string?TargetPath, CopyType CopyType)> items) in state.ItemsByItemType) { foreach ((string path, _, CopyType copyType) in items) { if (copyType == CopyType.CopyAlways) { return(log.Fail("CopyAlwaysItemExists", "Item '{0}' has CopyToOutputDirectory set to 'Always', not up to date.", _configuredProject.UnconfiguredProject.MakeRooted(path))); } } } return(true); }
public void Update_InitialItemDataDoesNotUpdateLastItemsChangedAtUtc() { // This test covers a false negative described in https://github.com/dotnet/project-system/issues/5386 // where the initial snapshot of items sets LastItemsChangedAtUtc, so if a project is up to date when // it is loaded, then the items are considered changed *after* the last build, but MSBuild's up-to-date // check will determine the project doesn't require a rebuild and so the output timestamps won't update. // This previously left the project in a state where it would be considered out of date endlessly. var projectSnapshot = new Dictionary <string, IProjectRuleSnapshotModel>() { [UpToDateCheckBuilt.SchemaName] = SimpleItems("BuiltOutputPath1") }; var sourceSnapshot1 = new Dictionary <string, IProjectRuleSnapshotModel>() { [Compile.SchemaName] = SimpleItems("ItemPath1") }; var sourceSnapshot2 = new Dictionary <string, IProjectRuleSnapshotModel>() { [Compile.SchemaName] = SimpleItems("ItemPath1", "ItemPath2") }; var state = UpToDateCheckImplicitConfiguredInput.CreateEmpty(ProjectConfigurationFactory.Create("testConfiguration")); Assert.Equal(DateTime.MinValue, state.LastItemsChangedAtUtc); // Initial change does NOT set LastItemsChangedAtUtc state = UpdateState( state, projectSnapshot, sourceSnapshot1); Assert.Equal(DateTime.MinValue, state.LastItemsChangedAtUtc); // Broadcasting an update with no change to items does NOT set LastItemsChangedAtUtc state = UpdateState(state); Assert.Equal(DateTime.MinValue, state.LastItemsChangedAtUtc); // Broadcasting changed items DOES set LastItemsChangedAtUtc state = UpdateState( state, projectSnapshot, sourceSnapshot2); Assert.NotEqual(DateTime.MinValue, state.LastItemsChangedAtUtc); }
private bool CheckGlobalConditions(Log log, DateTime lastSuccessfulBuildStartTimeUtc, bool validateFirstRun, UpToDateCheckImplicitConfiguredInput state) { if (!_tasksService.IsTaskQueueEmpty(ProjectCriticalOperation.Build)) { return(log.Fail("CriticalTasks", nameof(Resources.FUTD_CriticalBuildTasksRunning))); } if (state.IsDisabled) { return(log.Fail("Disabled", nameof(Resources.FUTD_DisableFastUpToDateCheckTrue))); } if (validateFirstRun && !state.WasStateRestored && lastSuccessfulBuildStartTimeUtc == DateTime.MinValue) { // We had no persisted state, and this is the first run. We cannot know if the project is up-to-date // or not, so schedule a build. return(log.Fail("FirstRun", nameof(Resources.FUTD_FirstRun))); } if (state.IsCopyAlwaysOptimizationDisabled) { // By default, we optimize CopyAlways to only copy if the time stamps or file sizes differ. // If we got here, then the user has opted out of that optimisation, and we must fail if any CopyAlways items exist. foreach ((string itemType, ImmutableArray <UpToDateCheckInputItem> items) in state.InputSourceItemsByItemType) { foreach (UpToDateCheckInputItem item in items) { if (item.CopyType == CopyType.Always) { return(log.Fail("CopyAlwaysItemExists", nameof(Resources.FUTD_CopyAlwaysItemExists_2), itemType, _configuredProject.UnconfiguredProject.MakeRooted(item.Path))); } } } } return(true); }
private bool CheckGlobalConditions(Log log, DateTime lastSuccessfulBuildStartTimeUtc, bool validateFirstRun, UpToDateCheckImplicitConfiguredInput state) { if (!_tasksService.IsTaskQueueEmpty(ProjectCriticalOperation.Build)) { return(log.Fail("CriticalTasks", nameof(Resources.FUTD_CriticalBuildTasksRunning))); } if (state.IsDisabled) { return(log.Fail("Disabled", nameof(Resources.FUTD_DisableFastUpToDateCheckTrue))); } if (validateFirstRun && !state.WasStateRestored && lastSuccessfulBuildStartTimeUtc == DateTime.MinValue) { // We had no persisted state, and this is the first run. We cannot know if the project is up-to-date // or not, so schedule a build. return(log.Fail("FirstRun", nameof(Resources.FUTD_FirstRun))); } if (lastSuccessfulBuildStartTimeUtc < state.LastItemsChangedAtUtc) { log.Fail("ProjectItemsChangedSinceLastSuccessfulBuildStart", nameof(Resources.FUTD_SetOfItemsChangedMoreRecentlyThanOutput_2), state.LastItemsChangedAtUtc, lastSuccessfulBuildStartTimeUtc); if (log.Level >= LogLevel.Info) { log.Indent++; if (state.LastItemChanges.Length == 0) { log.Info(nameof(Resources.FUTD_SetOfChangedItemsIsEmpty)); } else { foreach ((bool isAdd, string itemType, UpToDateCheckInputItem item) in state.LastItemChanges.OrderBy(change => change.ItemType).ThenBy(change => change.Item.Path)) { log.Info(isAdd ? nameof(Resources.FUTD_ChangedItemsAddition_4) : nameof(Resources.FUTD_ChangedItemsRemoval_4), itemType, item.Path, item.CopyType, item.TargetPath ?? ""); } } log.Indent--; } return(false); } if (state.IsCopyAlwaysOptimizationDisabled) { // By default, we optimize CopyAlways to only copy if the time stamps or file sizes differ. // If we got here, then the user has opted out of that optimisation, and we must fail if any CopyAlways items exist. foreach ((string itemType, ImmutableArray <UpToDateCheckInputItem> items) in state.InputSourceItemsByItemType) { foreach (UpToDateCheckInputItem item in items) { if (item.CopyType == CopyType.Always) { return(log.Fail("CopyAlwaysItemExists", nameof(Resources.FUTD_CopyAlwaysItemExists_2), itemType, _configuredProject.UnconfiguredProject.MakeRooted(item.Path))); } } } } return(true); }
private bool CheckGlobalConditions(Log log, DateTime lastCheckedAtUtc, bool validateFirstRun, UpToDateCheckImplicitConfiguredInput state) { if (!_tasksService.IsTaskQueueEmpty(ProjectCriticalOperation.Build)) { return(log.Fail("CriticalTasks", nameof(Resources.FUTD_CriticalBuildTasksRunning))); } if (state.IsDisabled) { return(log.Fail("Disabled", nameof(Resources.FUTD_DisableFastUpToDateCheckTrue))); } if (validateFirstRun && !state.WasStateRestored && lastCheckedAtUtc == DateTime.MinValue) { // We had no persisted state, and this is the first run. We cannot know if the project is up-to-date // or not, so schedule a build. return(log.Fail("FirstRun", nameof(Resources.FUTD_FirstRun))); } foreach ((_, ImmutableArray <UpToDateCheckInputItem> items) in state.InputSourceItemsByItemType) { foreach (UpToDateCheckInputItem item in items) { if (item.CopyType == CopyType.CopyAlways) { return(log.Fail("CopyAlwaysItemExists", nameof(Resources.FUTD_CopyAlwaysItemExists_1), _configuredProject.UnconfiguredProject.MakeRooted(item.Path))); } } } return(true); }