private TConflictItem ResolveConflict(TConflictItem item1, TConflictItem item2, bool logUnresolvedConflicts) { var winner = _packageOverrideResolver.Resolve(item1, item2); if (winner != null) { return(winner); } string conflictMessage = string.Format(CultureInfo.CurrentCulture, Strings.EncounteredConflict, item1.DisplayName, item2.DisplayName); var exists1 = item1.Exists; var exists2 = item2.Exists; if (!exists1 && !exists2) { // If neither file exists, then don't report a conflict, as both items should be resolved (or not) to the same reference assembly return(null); } if (!exists1 || !exists2) { if (logUnresolvedConflicts) { string fileMessage = conflictMessage + SENTENCE_SPACING + string.Format(CultureInfo.CurrentCulture, Strings.CouldNotDetermineWinner_DoesntExist, !exists1 ? item1.DisplayName : item2.DisplayName); _log.LogMessage(fileMessage); } return(null); } var assemblyVersion1 = item1.AssemblyVersion; var assemblyVersion2 = item2.AssemblyVersion; // if only one is missing version stop: something is wrong when we have a conflict between assembly and non-assembly if (assemblyVersion1 == null ^ assemblyVersion2 == null) { if (logUnresolvedConflicts) { var nonAssembly = assemblyVersion1 == null ? item1.DisplayName : item2.DisplayName; string assemblyMessage = conflictMessage + SENTENCE_SPACING + string.Format(CultureInfo.CurrentCulture, Strings.CouldNotDetermineWinner_NotAnAssembly, nonAssembly); _log.LogMessage(assemblyMessage); } return(null); } // only handle cases where assembly version is different, and not null (implicit here due to xor above) if (assemblyVersion1 != assemblyVersion2) { string winningDisplayName; Version winningVersion; Version losingVersion; if (assemblyVersion1 > assemblyVersion2) { winningDisplayName = item1.DisplayName; winningVersion = assemblyVersion1; losingVersion = assemblyVersion2; } else { winningDisplayName = item2.DisplayName; winningVersion = assemblyVersion2; losingVersion = assemblyVersion1; } string assemblyMessage = conflictMessage + SENTENCE_SPACING + string.Format(CultureInfo.CurrentCulture, Strings.ChoosingAssemblyVersion, winningDisplayName, winningVersion, losingVersion); _log.LogMessage(assemblyMessage); if (assemblyVersion1 > assemblyVersion2) { return(item1); } if (assemblyVersion2 > assemblyVersion1) { return(item2); } } var fileVersion1 = item1.FileVersion; var fileVersion2 = item2.FileVersion; // if only one is missing version if (fileVersion1 == null ^ fileVersion2 == null) { if (logUnresolvedConflicts) { var nonVersion = fileVersion1 == null ? item1.DisplayName : item2.DisplayName; string fileVersionMessage = conflictMessage + SENTENCE_SPACING + string.Format(CultureInfo.CurrentCulture, Strings.CouldNotDetermineWinner_FileVersion, nonVersion); } return(null); } if (fileVersion1 != fileVersion2) { string winningDisplayName; Version winningVersion; Version losingVersion; if (fileVersion1 > fileVersion2) { winningDisplayName = item1.DisplayName; winningVersion = fileVersion1; losingVersion = fileVersion2; } else { winningDisplayName = item2.DisplayName; winningVersion = fileVersion2; losingVersion = fileVersion1; } string fileVersionMessage = conflictMessage + SENTENCE_SPACING + string.Format(CultureInfo.CurrentCulture, Strings.ChoosingFileVersion, winningDisplayName, winningVersion, losingVersion); _log.LogMessage(fileVersionMessage); if (fileVersion1 > fileVersion2) { return(item1); } if (fileVersion2 > fileVersion1) { return(item2); } } var packageRank1 = _packageRank.GetPackageRank(item1.PackageId); var packageRank2 = _packageRank.GetPackageRank(item2.PackageId); if (packageRank1 < packageRank2) { string packageRankMessage = conflictMessage + SENTENCE_SPACING + string.Format(CultureInfo.CurrentCulture, Strings.ChoosingPreferredPackage, item1.DisplayName); _log.LogMessage(packageRankMessage); return(item1); } if (packageRank2 < packageRank1) { string packageRankMessage = conflictMessage + SENTENCE_SPACING + string.Format(CultureInfo.CurrentCulture, Strings.ChoosingPreferredPackage, item2.DisplayName); return(item2); } var isPlatform1 = item1.ItemType == ConflictItemType.Platform; var isPlatform2 = item2.ItemType == ConflictItemType.Platform; if (isPlatform1 && !isPlatform2) { string platformMessage = conflictMessage + SENTENCE_SPACING + string.Format(CultureInfo.CurrentCulture, Strings.ChoosingPlatformItem, item1.DisplayName); _log.LogMessage(platformMessage); return(item1); } if (!isPlatform1 && isPlatform2) { string platformMessage = conflictMessage + SENTENCE_SPACING + string.Format(CultureInfo.CurrentCulture, Strings.ChoosingPlatformItem, item2.DisplayName); _log.LogMessage(platformMessage); return(item2); } if (logUnresolvedConflicts) { string message = conflictMessage + SENTENCE_SPACING + string.Format(CultureInfo.CurrentCulture, Strings.ConflictCouldNotDetermineWinner); _log.LogMessage(message); } return(null); }
private TConflictItem ResolveConflict(TConflictItem item1, TConflictItem item2, bool logUnresolvedConflicts) { var winner = _packageOverrideResolver.Resolve(item1, item2); if (winner != null) { return(winner); } string conflictMessage = string.Format(CultureInfo.CurrentCulture, Strings.EncounteredConflict_Info, item1.DisplayName, item2.DisplayName); var exists1 = item1.Exists; var exists2 = item2.Exists; if (!exists1 && !exists2) { // If neither file exists, then don't report a conflict, as both items should be resolved (or not) to the same reference assembly return(null); } if (!exists1 || !exists2) { if (logUnresolvedConflicts) { LogMessage(conflictMessage, Strings.CouldNotDetermineWinner_DoesNotExist_Info, !exists1 ? item1.DisplayName : item2.DisplayName); } return(null); } var assemblyVersion1 = item1.AssemblyVersion; var assemblyVersion2 = item2.AssemblyVersion; // if only one is missing version stop: something is wrong when we have a conflict between assembly and non-assembly if (assemblyVersion1 == null ^ assemblyVersion2 == null) { if (logUnresolvedConflicts) { var nonAssembly = assemblyVersion1 == null ? item1.DisplayName : item2.DisplayName; LogMessage(conflictMessage, Strings.CouldNotDetermineWinner_NotAnAssembly_Info, nonAssembly); } return(null); } // only handle cases where assembly version is different, and not null (implicit here due to xor above) if (assemblyVersion1 != assemblyVersion2) { string winningDisplayName; Version winningVersion; Version losingVersion; if (assemblyVersion1 > assemblyVersion2) { winningDisplayName = item1.DisplayName; winningVersion = assemblyVersion1; losingVersion = assemblyVersion2; } else { winningDisplayName = item2.DisplayName; winningVersion = assemblyVersion2; losingVersion = assemblyVersion1; } LogMessage(conflictMessage, Strings.ChoosingAssemblyVersion_Info, winningDisplayName, winningVersion, losingVersion); if (assemblyVersion1 > assemblyVersion2) { return(item1); } if (assemblyVersion2 > assemblyVersion1) { return(item2); } } var fileVersion1 = item1.FileVersion; var fileVersion2 = item2.FileVersion; // if only one is missing version if (fileVersion1 == null ^ fileVersion2 == null) { if (logUnresolvedConflicts) { var nonVersion = fileVersion1 == null ? item1.DisplayName : item2.DisplayName; LogMessage(conflictMessage, Strings.CouldNotDetermineWinner_NoFileVersion_Info, nonVersion); } return(null); } if (fileVersion1 != fileVersion2) { string winningDisplayName; Version winningVersion; Version losingVersion; if (fileVersion1 > fileVersion2) { winningDisplayName = item1.DisplayName; winningVersion = fileVersion1; losingVersion = fileVersion2; } else { winningDisplayName = item2.DisplayName; winningVersion = fileVersion2; losingVersion = fileVersion1; } LogMessage(conflictMessage, Strings.ChoosingFileVersion_Info, winningDisplayName, winningVersion, losingVersion); if (fileVersion1 > fileVersion2) { return(item1); } if (fileVersion2 > fileVersion1) { return(item2); } } var packageRank1 = _packageRank.GetPackageRank(item1.PackageId); var packageRank2 = _packageRank.GetPackageRank(item2.PackageId); if (packageRank1 < packageRank2) { LogMessage(conflictMessage, Strings.ChoosingPreferredPackage_Info, item1.DisplayName); return(item1); } if (packageRank2 < packageRank1) { LogMessage(conflictMessage, Strings.ChoosingPreferredPackage_Info, item2.DisplayName); return(item2); } var isPlatform1 = item1.ItemType == ConflictItemType.Platform; var isPlatform2 = item2.ItemType == ConflictItemType.Platform; if (isPlatform1 && !isPlatform2) { LogMessage(conflictMessage, Strings.ChoosingPlatformItem_Info, item1.DisplayName); return(item1); } if (!isPlatform1 && isPlatform2) { LogMessage(conflictMessage, Strings.ChoosingPlatformItem_Info, item2.DisplayName); return(item2); } if (item1.ItemType == ConflictItemType.CopyLocal && item2.ItemType == ConflictItemType.CopyLocal) { // If two items are copy local, we must pick one even if versions are identical, as only // one of them can be copied locally. The policy here must be deterministic, but it can // be chosen arbitrarily. The assumption is that the assemblies are fully semantically // equivalent. // // We choose ordinal string comparison of package id as a final tie-breaker for this case. // We will get here in the real case of frameworks with overlapping assemblies (including // version) and self-contained apps. The assembly we choose here is not guaranteed to match // the assembly that would be chosen by the host for a framework-dependent app. The host // is free to make its own deterministic but arbitrary choice. int cmp = string.CompareOrdinal(item1.PackageId, item2.PackageId); if (cmp != 0) { var arbitraryWinner = cmp < 0 ? item1 : item2; LogMessage(conflictMessage, Strings.ChoosingCopyLocalArbitrarily_Info, arbitraryWinner.DisplayName); return(arbitraryWinner); } } if (logUnresolvedConflicts) { LogMessage(conflictMessage, Strings.CouldNotDetermineWinner_EqualVersions_Info); } return(null); }