/// <summary> /// Extract the package contents to the specified directory. Standard metadata will be deleted, e.g. _rels folder, .nuspec file, etc. /// </summary> /// <param name="destinationDirectory">The directory where the package will be extracted.</param> public void Extract(string destinationDirectory, IEnumerable <string> exclusionPatterns) { if (Directory.Exists(destinationDirectory)) { Directory.Delete(destinationDirectory, recursive: true); } Directory.CreateDirectory(destinationDirectory); ZipFile.ExtractToDirectory(PackagePath, destinationDirectory); // Remove unnecessary files and directories Utils.DeleteDirectory(Path.Combine(destinationDirectory, "_rels")); Utils.DeleteDirectory(Path.Combine(destinationDirectory, "package")); Utils.DeleteFile(Path.Combine(destinationDirectory, ".signature.p7s")); Utils.DeleteFile(Path.Combine(destinationDirectory, "[Content_Types].xml")); Utils.DeleteFile(Path.Combine(destinationDirectory, $"{Id}.nuspec")); if (exclusionPatterns.Count() > 0) { IEnumerable <string> allFiles = Directory.EnumerateFiles(destinationDirectory, "*.*", SearchOption.AllDirectories); IEnumerable <string> filesToDelete = allFiles.Where(f => exclusionPatterns.Any(p => Regex.IsMatch(f, p))); Log?.LogMessage(MessageImportance.High, $"Found {filesToDelete.Count()} files matching exclusion patterns."); foreach (string file in filesToDelete) { Log?.LogMessage(MessageImportance.High, $"Deleting '{file}'."); File.Delete(file); } } }
SolutionNode AddProject( string projectPath, string solutionFolder = null, Guid projectGuid = default) { if (projectPath == null) { throw new ArgumentNullException(nameof(projectPath)); } var solutionDirectory = Path.GetDirectoryName(FileName); if (string.IsNullOrEmpty(solutionDirectory)) { solutionDirectory = "."; } var relativePath = MakeRelativePath(solutionDirectory, projectPath); if (projectGuid == default) { // for the GUID, force path separators so Win vs Mac produces the same projectGuid = GuidV5(solutionGuid, relativePath.Replace('\\', '/')); } var parentNode = solution; if (!string.IsNullOrEmpty(solutionFolder)) { foreach (var name in solutionFolder.Split('\\', '/')) { var folderAddOperation = parentNode.AddFolder(name); parentNode = folderAddOperation.node; if (folderAddOperation.added) { log?.LogMessage(MessageImportance.Normal, $"Added solution folder: {solutionFolder}"); } } } log?.LogMessage(MessageImportance.Normal, $"Adding project: {relativePath}"); var(projectNode, addedProject) = parentNode.AddProject( projectGuid, relativePath); if (addedProject && log != null) { log.LogMessage(MessageImportance.Normal, $"Added project: {relativePath} ({projectGuid})"); log.LogMessage(MessageImportance.Low, $" solutionDirectory: {solutionDirectory}"); log.LogMessage(MessageImportance.Low, $" projectPath: {projectPath}"); } return(projectNode); }
/// <summary> /// Creates a <see cref="VisualStudioComponent"/> using a workload definition. /// </summary> /// <param name="manifest"></param> /// <param name="workload"></param> /// <param name="componentVersions"></param> /// <param name="shortNames"></param> /// <param name="shortNameMetadata"></param> /// <param name="componentResources"></param> /// <returns></returns> public static VisualStudioComponent Create(TaskLoggingHelper log, WorkloadManifest manifest, WorkloadDefinition workload, ITaskItem[] componentVersions, ITaskItem[] shortNames, ITaskItem[] componentResources, ITaskItem[] missingPacks) { log?.LogMessage("Creating Visual Studio component"); string workloadId = $"{workload.Id}"; // If there's an explicit version mapping we use that, otherwise we fall back to the manifest version // and normalize it since it can have semantic information and Visual Studio components do not support that. ITaskItem versionItem = componentVersions?.Where(v => string.Equals(v.ItemSpec, workloadId, StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); Version version = (versionItem != null) && !string.IsNullOrWhiteSpace(versionItem.GetMetadata(Metadata.Version)) ? new Version(versionItem.GetMetadata(Metadata.Version)) : (new NuGetVersion(manifest.Version)).Version; ITaskItem resourceItem = componentResources?.Where( r => string.Equals(r.ItemSpec, workloadId, StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); // Workload definitions do not have separate title/description fields so the only option // is to default to the workload description for both. string title = resourceItem?.GetMetadata(Metadata.Title) ?? workload.Description; string description = resourceItem?.GetMetadata(Metadata.Description) ?? workload.Description; string category = resourceItem?.GetMetadata(Metadata.Category) ?? ".NET"; string isUiGroup = workload.IsAbstract ? "yes" : "no"; VisualStudioComponent component = new(Utils.ToSafeId(workloadId), description, title, version, isUiGroup, shortNames, category); IEnumerable <string> missingPackIds = missingPacks.Select(p => p.ItemSpec); log?.LogMessage(MessageImportance.Low, $"Missing packs: {string.Join(", ", missingPackIds)}"); // If the work extends other workloads, we add those as component dependencies before // processing direct pack dependencies if (workload.Extends?.Count() > 0) { foreach (WorkloadDefinitionId dependency in workload.Extends) { // Component dependencies, aka. workload extensions only have minimum version dependencies. component.AddDependency($"{Utils.ToSafeId(dependency.ToString())}", new Version("1.0.0.0"), maxVersion: null); } } // Visual Studio is case-insensitive. IEnumerable <WorkloadPackId> packIds = workload.Packs.Where(p => !missingPackIds.Contains($"{p}", StringComparer.OrdinalIgnoreCase)); log?.LogMessage(MessageImportance.Low, $"Packs: {string.Join(", ", packIds.Select(p=>$"{p}"))}"); foreach (WorkloadPackId packId in packIds) { log?.LogMessage(MessageImportance.Low, $"Adding component dependency for {packId} "); component.AddDependency(manifest.Packs[packId]); } return(component); }
private static Assembly AssemblyResolve(object sender, ResolveEventArgs args) { var name = new AssemblyName(args.Name); if (!name.Name.Equals("System.Collections.Immutable", StringComparison.OrdinalIgnoreCase)) { return(null); } var fullPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "System.Collections.Immutable.dll"); Assembly sci; try { sci = Assembly.LoadFile(fullPath); } catch (Exception e) { Log?.LogWarning($"AssemblyResolve: exception while loading '{fullPath}': {e.Message}"); return(null); } if (name.Version <= sci.GetName().Version) { Log?.LogMessage(MessageImportance.Low, $"AssemblyResolve: loaded '{fullPath}' to {AppDomain.CurrentDomain.FriendlyName}"); return(sci); } return(null); }
public void Log <TState>(Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, TState state, Exception exception, Func <TState, Exception, string> formatter) { if (formatter == null) { throw new ArgumentNullException(nameof(formatter)); } var message = formatter(state, exception); if (string.IsNullOrEmpty(message)) { return; } switch (logLevel) { case Microsoft.Extensions.Logging.LogLevel.Error: _taskLog?.LogError(message); break; case Microsoft.Extensions.Logging.LogLevel.Warning: _taskLog?.LogWarning(message); break; case Microsoft.Extensions.Logging.LogLevel.Information: _taskLog?.LogMessage(MessageImportance.Normal, message); break; case Microsoft.Extensions.Logging.LogLevel.Debug: _taskLog?.LogMessage(MessageImportance.Low, message); break; default: _taskLog?.LogMessage(message); break; } }
/// <summary> /// Creates a <see cref="VisualStudioComponent"/> using a workload definition. /// </summary> /// <param name="manifest"></param> /// <param name="workload"></param> /// <param name="componentVersion"></param> /// <param name="shortNames"></param> /// <param name="shortNameMetadata"></param> /// <param name="componentResources"></param> /// <returns></returns> public static VisualStudioComponent Create(TaskLoggingHelper log, WorkloadManifest manifest, WorkloadDefinition workload, string componentVersion, ITaskItem[] shortNames, ITaskItem[] componentResources, ITaskItem[] missingPacks) { log?.LogMessage("Creating Visual Studio component"); Version version = string.IsNullOrWhiteSpace(componentVersion) ? new Version($"{manifest.Version}.0") : new Version(componentVersion); ITaskItem resourceItem = componentResources?.Where( r => string.Equals(r.ItemSpec, workload.Id.ToString(), StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); // Workload definitions do not have separate title/description fields so the only option // is to default to the workload description for both. string title = resourceItem?.GetMetadata(Metadata.Title) ?? workload.Description; string description = resourceItem?.GetMetadata(Metadata.Description) ?? workload.Description; string category = resourceItem?.GetMetadata(Metadata.Category) ?? ".NET"; VisualStudioComponent component = new(Utils.ToSafeId(workload.Id.ToString()), description, title, version, shortNames, category); IEnumerable <string> missingPackIds = missingPacks.Select(p => p.ItemSpec); log?.LogMessage(MessageImportance.Low, $"Missing packs: {string.Join(", ", missingPackIds)}"); // Visual Studio is case-insensitive. IEnumerable <WorkloadPackId> packIds = workload.Packs.Where(p => !missingPackIds.Contains($"{p}", StringComparer.OrdinalIgnoreCase)); log?.LogMessage(MessageImportance.Low, $"Packs: {string.Join(", ", packIds.Select(p=>$"{p}"))}"); foreach (WorkloadPackId packId in packIds) { log?.LogMessage(MessageImportance.Low, $"Adding component dependency for {packId} "); component.AddDependency(manifest.Packs[packId]); } return(component); }
/// <summary> /// Store a POString in the dictionary, unless another string with the same msgid already exists. /// </summary> public static void StoreString(Dictionary <string, POString> dictTrans, POString poStr, TaskLoggingHelper log) { if (poStr.IsObsolete) { return; } var msgid = poStr.MsgIdAsString(); if (dictTrans.ContainsKey(msgid)) { log?.LogMessage("The message id '{0}' already exists. Ignoring this occurrence around line {1}.", msgid, POString.InputLineNumber); } else { dictTrans.Add(msgid, poStr); } }
public void LogMessage(MessageImportance importance, string message, params object[] messageArgs) { _log.LogMessage(importance, message, messageArgs); }
public static void LogTaskProperty(this TaskLoggingHelper log, string propertyName, int value) { log.LogMessage(TaskPropertyImportance, " {0}: {1}", propertyName, value); }
public static async Task <HttpResponseMessage> RequestWithRetry(TaskLoggingHelper loggingHelper, HttpClient client, Func <HttpRequestMessage> createRequest, Func <HttpResponseMessage, bool> validationCallback = null, int retryCount = 5, int retryDelaySeconds = 5) { if (loggingHelper == null) { throw new ArgumentNullException(nameof(loggingHelper)); } if (client == null) { throw new ArgumentNullException(nameof(client)); } if (createRequest == null) { throw new ArgumentNullException(nameof(createRequest)); } if (retryCount < 1) { throw new ArgumentException(nameof(retryCount)); } if (retryDelaySeconds < 1) { throw new ArgumentException(nameof(retryDelaySeconds)); } int retries = 0; HttpResponseMessage response = null; // add a bit of randomness to the retry delay var rng = new Random(); while (retries < retryCount) { if (retries > 0) { if (response != null) { response.Dispose(); response = null; } int delay = retryDelaySeconds * retries * rng.Next(1, 5); loggingHelper.LogMessage(MessageImportance.Low, "Waiting {0} seconds before retry", delay); await System.Threading.Tasks.Task.Delay(delay * 1000); } try { using (var request = createRequest()) response = await client.SendAsync(request); } catch (Exception e) { loggingHelper.LogWarningFromException(e, true); // if this is the final iteration let the exception bubble up if (retries + 1 == retryCount) { throw; } } // response can be null if we fail to send the request if (response != null) { if (validationCallback == null) { // check if the response code is within the range of failures if (IsWithinRetryRange(response.StatusCode)) { loggingHelper.LogWarning("Request failed with status code {0}", response.StatusCode); } else { loggingHelper.LogMessage(MessageImportance.Low, "Response completed with status code {0}", response.StatusCode); return(response); } } else { bool isSuccess = validationCallback(response); if (!isSuccess) { loggingHelper.LogMessage("Validation callback returned retry for status code {0}", response.StatusCode); } else { loggingHelper.LogMessage("Validation callback returned success for status code {0}", response.StatusCode); return(response); } } } ++retries; } // retry count exceeded loggingHelper.LogWarning("Retry count {0} exceeded", retryCount); // set some default values in case response is null var statusCode = "None"; var contentStr = "Null"; if (response != null) { statusCode = response.StatusCode.ToString(); contentStr = await response.Content.ReadAsStringAsync(); response.Dispose(); } throw new HttpRequestException(string.Format("Request failed with status {0} response {1}", statusCode, contentStr)); }
public void WriteLine() { taskLog.LogMessage("\n"); }
public static void LogDebugMessage(this TaskLoggingHelper log, string message, params object[] messageArgs) { log.LogMessage(MessageImportance.Low, message, messageArgs); }
/// <summary> /// Creates a new <see cref="SolutionBuilder"/> from an MSBuild traversal project. /// </summary> /// <param name="projectPath"> /// The path to the traversal project from which to populate the returned <see cref="SolutionBuilder"/>. /// </param> /// <param name="solutionOutputPath"> /// The path to the solution that the returned <see cref="SolutionBuilder"/> should /// represent. This path is used to compute the relative path to projects. /// </param> /// <param name="addTransitiveProjectReferences"> /// Whether or not to add transitive `<ProjectReference>` projects to the solution. /// </param> /// <param name="log"> /// An optional logger. /// </param> public static SolutionBuilder FromTraversalProject( string projectPath, string solutionOutputPath = null, bool addTransitiveProjectReferences = true, TaskLoggingHelper log = null) { if (projectPath == null) { throw new ArgumentNullException(nameof(projectPath)); } if (!File.Exists(projectPath)) { throw new FileNotFoundException($"project does not exist: {projectPath}"); } projectPath = ResolveFullPath(projectPath); if (string.IsNullOrEmpty(solutionOutputPath)) { solutionOutputPath = Path.ChangeExtension(projectPath, ".sln"); } log?.LogMessage(MessageImportance.High, "Generating solution from traversal project"); log?.LogMessage(MessageImportance.Normal, $" projectPath: {projectPath}"); log?.LogMessage(MessageImportance.Normal, $" solutionOutputPath: {solutionOutputPath}"); log?.LogMessage(MessageImportance.Normal, $" addTransitiveProjectReferences: {addTransitiveProjectReferences}"); var solution = new SolutionBuilder(solutionOutputPath, log); var traversalProject = new ProjectCollection().LoadProject(projectPath); // Add the explicit solution configurations foreach (var item in traversalProject.GetItems("SolutionConfiguration")) { solution.AddSolutionConfiguration(ConfigurationPlatform.Parse(item.EvaluatedInclude)); } // For each solution configuration, re-evaluate the whole project collection // with the mapped solution -> project configurations. This can result in // different project references (e.g. cross platform projects that might build // on windows and not mac, etc.). foreach (var item in traversalProject.GetItems("SolutionConfiguration")) { var solutionConfigurationPlatform = ConfigurationPlatform.Parse(item.EvaluatedInclude); var projectConfigurationPlatform = new ConfigurationPlatform( item.GetMetadataValue("Configuration") ?? solutionConfigurationPlatform.Configuration, item.GetMetadataValue("Platform") ?? solutionConfigurationPlatform.Platform); var globalProperties = new List <(string, string)> { ("IsGeneratingSolution", "true"), ("Configuration", projectConfigurationPlatform.Configuration), ("Platform", projectConfigurationPlatform.Platform) }; globalProperties.AddRange(item.Metadata.Select(m => (m.Name, m.EvaluatedValue))); var graph = DependencyGraph .Create(projectPath, globalProperties) .LoadGraph(); // Add each project. Projects may fail to load in MSBuild, for example, if an SDK // is not available via the running MSBuild toolchain. If this is the case, we // still need to handle adding the project to the solution, we just can't infer // anything therein. foreach (var node in graph.TopologicallySortedProjects) { // Don't add the root traversal project to the solution if (node.Parents.Count == 0) { continue; } // Prefer an explicit project GUID if one exists (old style projects) Guid projectGuid = default; var explicitProjectGuid = node.Project == null ? XDocument .Load(node.ProjectPath) .Root .Elements() .FirstOrDefault(e => !e.HasAttributes && string.Equals( e.Name.LocalName, "PropertyGroup", StringComparison.OrdinalIgnoreCase)) ?.Elements() .FirstOrDefault(e => string.Equals( e.Name.LocalName, "ProjectGuid", StringComparison.OrdinalIgnoreCase)) ?.Value : node.Project.GetPropertyValue("ProjectGuid"); if (!string.IsNullOrEmpty(explicitProjectGuid)) { Guid.TryParse(explicitProjectGuid, out projectGuid); } string solutionFolder = null; var includeInSolution = true; foreach (var projectReference in node.ProjectReferenceItems) { if (string.Equals( projectReference.GetMetadataValue("IncludeInSolution"), "false", StringComparison.OrdinalIgnoreCase)) { includeInSolution = false; break; } projectConfigurationPlatform = projectConfigurationPlatform .WithConfiguration(projectReference.GetMetadataValue("Configuration")) .WithPlatform(projectReference.GetMetadataValue("Platform")); var _solutionFolder = projectReference.GetMetadataValue("SolutionFolder"); if (!string.IsNullOrEmpty(_solutionFolder)) { solutionFolder = _solutionFolder; } } if (!includeInSolution) { continue; } var solutionNode = solution.AddProject( node.ProjectPath, solutionFolder, projectGuid); solutionNode.AddConfigurationMap(new SolutionConfigurationPlatformMap( solutionConfigurationPlatform, projectConfigurationPlatform)); } } return(solution); }
/// <summary> /// /// </summary> /// <param name="descriptors"></param> /// <param name="filePaths"></param> /// <param name="log"></param> /// <returns></returns> internal bool TryExecuteAssemblyInfoBumpVersion(IEnumerable <IBumpVersionDescriptor> descriptors , IEnumerable <string> filePaths, TaskLoggingHelper log = null) { /* ProjectFilename should be based on ProjectFullPath, * which should be relayed to us as the $(ProjectPath). */ var projectFilename = ProjectFilename; // TODO: TBD: should consider logging the descriptors we do have here... // TODO: TBD: or possibly as a function of the targets themselves, if possible... // Ensure that we are dealing only with the Descriptors we can. descriptors = descriptors.Where(descriptor => descriptor.Kind.ContainedBy(AssemblyVersion , AssemblyFileVersion, AssemblyInformationalVersion)).ToArray(); if (!descriptors.Any()) { return(false); } var services = descriptors.Select(d => d.MakeAssemblyInfoBumpVersionService(log)) .Where(x => x != null).ToArray(); // ReSharper disable once CollectionNeverQueried.Local var results = new List <bool>(); void OnUsingStatementAdded(object sender, UsingStatementAddedEventArgs e) { log?.LogMessage(High, $"'{projectFilename}': Adding statement '{e.UsingStatement}'"); } void OnBumpResultFound(object sender, BumpResultEventArgs e) { // ReSharper disable once InvertIf if (e.Result is IAssemblyInfoBumpResult assyInfoResult) { (assyInfoResult.DidBump ? log : null)?.LogMessage(High, GetMessage()); string GetMessage() => $"'{projectFilename}': Bumped '{assyInfoResult.AttributeType.FullName}'" + $" from '{e.Result.OldVersionAndSemanticString}'" + $" to '{e.Result.VersionAndSemanticString}'"; } } services.ToList().ForEach(service => { service.UsingStatementAdded += OnUsingStatementAdded; service.BumpResultFound += OnBumpResultFound; }); foreach (var fullPath in filePaths.Where(Exists)) { var bumped = false; // ReSharper disable once InvertIf if (TryReadingFileLines(fullPath, out var givenLines)) { #if TASK_LOGGING_HELPER_DIAGNOSTICS log?.LogWarning($"Lines read from '{fullPath}'."); #endif foreach (var service in services) { service.Log = log; #if TASK_LOGGING_HELPER_DIAGNOSTICS log?.LogWarning($"Trying to bump lines from '{fullPath}'."); #endif // ReSharper disable once PossibleMultipleEnumeration if (service.TryBumpVersion(givenLines, out var bumpedLines)) { #if TASK_LOGGING_HELPER_DIAGNOSTICS log?.LogWarning($"Lines bumped for '{fullPath}'."); #endif // ReSharper disable once PossibleMultipleEnumeration bumped = bumped || !bumpedLines // ReSharper disable once PossibleMultipleEnumeration .SequenceEqual(givenLines); if (!bumped) { continue; } // ReSharper disable once PossibleMultipleEnumeration givenLines = bumpedLines.ToArray(); } } if (!bumped) { continue; } #if TASK_LOGGING_HELPER_DIAGNOSTICS log?.LogWarning($"Writing lines to file '{fullPath}' ..."); #endif // ReSharper disable once PossibleMultipleEnumeration results.Add(TryWritingFileLines(fullPath, givenLines.ToArray())); } else { #if TASK_LOGGING_HELPER_DIAGNOSTICS log?.LogWarning($"Lines not read from '{fullPath}'."); #endif results.Add(false); } } services.ToList().ForEach(service => { service.UsingStatementAdded -= OnUsingStatementAdded; service.BumpResultFound -= OnBumpResultFound; }); return(true); }
internal void Go(bool doStrongNameCheck) { VerifyCertificates(_log); if (_log.HasLoggedErrors) { return; } // Next remove public signing from all of the assemblies; it can interfere with the signing process. RemovePublicSign(); // Next sign all of the files if (!SignFiles()) { _log.LogError("Error during execution of signing process."); return; } if (!CopyFiles()) { return; } // Check that all files have a strong name signature if (doStrongNameCheck) { VerifyStrongNameSigning(); } // Validate the signing worked and produced actual signed binaries in all locations. // This is a recursive process since we process nested containers. foreach (var file in _batchData.FilesToSign) { VerifyAfterSign(file); } if (_log.HasLoggedErrors) { return; } _log.LogMessage(MessageImportance.High, "Build artifacts signed and validated."); }
/// <summary> /// Determine whether a local package is the same as a package on an AzDO feed. /// </summary> /// <param name="localPackageFullPath"></param> /// <param name="packageContentUrl"></param> /// <param name="client"></param> /// <param name="log"></param> /// <param name="retryHandler"></param> /// <returns></returns> /// <remarks> /// Open a stream to the local file and an http request to the package. There are a couple possibilities: /// - The returned headers include a content MD5 header, in which case we can /// hash the local file and just compare those. /// - No content MD5 hash, and the streams must be compared in blocks. This is a bit trickier to do efficiently, /// since we do not necessarily want to read all bytes if we can help it. Thus, we should compare in blocks. However, /// the streams make no guarantee that they will return a full block each time when read operations are performed, so we /// must be sure to only compare the minimum number of bytes returned. /// </remarks> public static async Task <PackageFeedStatus> CompareLocalPackageToFeedPackage( string localPackageFullPath, string packageContentUrl, HttpClient client, TaskLoggingHelper log, IRetryHandler retryHandler) { log.LogMessage($"Getting package content from {packageContentUrl} and comparing to {localPackageFullPath}"); PackageFeedStatus result = PackageFeedStatus.Unknown; bool success = await retryHandler.RunAsync(async attempt => { try { using (Stream localFileStream = File.OpenRead(localPackageFullPath)) using (HttpResponseMessage response = await client.GetAsync(packageContentUrl)) { response.EnsureSuccessStatusCode(); // Check the headers for content length and md5 bool md5HeaderAvailable = response.Headers.TryGetValues("Content-MD5", out var md5); bool lengthHeaderAvailable = response.Headers.TryGetValues("Content-Length", out var contentLength); if (lengthHeaderAvailable && long.Parse(contentLength.Single()) != localFileStream.Length) { log.LogMessage(MessageImportance.Low, $"Package '{localPackageFullPath}' has different length than remote package '{packageContentUrl}'."); result = PackageFeedStatus.ExistsAndDifferent; return(true); } if (md5HeaderAvailable) { var localMD5 = AzureStorageUtils.CalculateMD5(localPackageFullPath); if (!localMD5.Equals(md5.Single(), StringComparison.OrdinalIgnoreCase)) { log.LogMessage(MessageImportance.Low, $"Package '{localPackageFullPath}' has different MD5 hash than remote package '{packageContentUrl}'."); } result = PackageFeedStatus.ExistsAndDifferent; return(true); } const int BufferSize = 64 * 1024; // Otherwise, compare the streams var remoteStream = await response.Content.ReadAsStreamAsync(); var streamsMatch = await GeneralUtils.CompareStreamsAsync(localFileStream, remoteStream, BufferSize); result = streamsMatch ? PackageFeedStatus.ExistsAndIdenticalToLocal : PackageFeedStatus.ExistsAndDifferent; return(true); } } // String based comparison because the status code isn't exposed in HttpRequestException // see here: https://github.com/dotnet/runtime/issues/23648 catch (HttpRequestException e) { if (e.Message.Contains("404 (Not Found)")) { result = PackageFeedStatus.DoesNotExist; return(true); } // Retry this. Could be an http client timeout, 500, etc. return(false); } }); return(result); }
private void ImportantMessage(string msg, params object[] msgParams) { m_log.LogMessage(MessageImportance.High, msg, msgParams); }
/// <summary>See <see cref="Task.Execute"/>.</summary> public override bool Execute() { const string VsSdkInstallDirEnvironmentVariable = "VsSDKInstall"; const string VsSdkVersionsRegistryPath = @"SOFTWARE\Microsoft\VisualStudio\VSIP"; const string VsSdkInstallDirRegistryValue = "InstallDir"; const string VsSdkIncludeFilesSubdirectory = @"VisualStudioIntegration\Common\Inc"; const string VsSdkToolsSubdirectory = @"VisualStudioIntegration\Tools\Bin"; const string VsSdkRedistributablesSubdirectory = @"VisualStudioIntegration\Redistributables"; TaskLoggingHelper log = base.Log; // Try to find the VsSDK installation directory by first checking the environment variable, and then by checking the specified version listed in the registry. string installDir = Environment.GetEnvironmentVariable(VsSdkInstallDirEnvironmentVariable); if (!string.IsNullOrEmpty(installDir)) { log.LogMessage(MessageImportance.Low, "Using Visual Studio SDK installation directory from \"" + VsSdkInstallDirEnvironmentVariable + "\" environment variable: \"{0}\"", installDir); } else { using (RegistryKey vsipRegistryKey = Registry.LocalMachine.OpenSubKey(VsSdkVersionsRegistryPath, RegistryKeyPermissionCheck.ReadSubTree)) { if (vsipRegistryKey != null) { string requestedVersionSubKeyName = this.RequestedVersion; using (RegistryKey requestedVersionRegistryKey = vsipRegistryKey.OpenSubKey(requestedVersionSubKeyName, RegistryKeyPermissionCheck.ReadSubTree)) { if (requestedVersionRegistryKey != null) { installDir = requestedVersionRegistryKey.GetValue(VsSdkInstallDirRegistryValue, null) as string; log.LogMessage(MessageImportance.Low, "Using Visual Studio SDK installation directory from registry for version \"{0}\": \"{1}\"", requestedVersionSubKeyName, installDir); } else if (requestedVersionSubKeyName == "8.0") { // Fallback on the 9.0 SDK, enabling a VS2005 build with a 2008SDK install // and minimal additional files. requestedVersionSubKeyName = "9.0"; using (RegistryKey requestedVersionRegistryKeyFallback = vsipRegistryKey.OpenSubKey(requestedVersionSubKeyName, RegistryKeyPermissionCheck.ReadSubTree)) { if (requestedVersionRegistryKeyFallback != null) { installDir = requestedVersionRegistryKeyFallback.GetValue(VsSdkInstallDirRegistryValue, null) as string; log.LogMessage(MessageImportance.Low, "Using Visual Studio SDK installation directory from registry for version \"{0}\": \"{1}\"", requestedVersionSubKeyName, installDir); } } } } } } if (string.IsNullOrEmpty(installDir)) { // if the install has not been found try vswhere // according to https://github.com/Microsoft/vswhere/wiki the install path will be maintained string vsWherePath = Environment.ExpandEnvironmentVariables(@"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe"); if (!File.Exists(vsWherePath)) { vsWherePath = Environment.ExpandEnvironmentVariables(@"%ProgramFiles%\Microsoft Visual Studio\Installer\vswhere.exe"); if (!File.Exists(vsWherePath)) { vsWherePath = null; } } if (string.IsNullOrEmpty(vsWherePath)) { log.LogError("Unable to find vswhere."); } else { #if VISUALSTUDIO_16_0 string versionParameter = "-version [16.0,17.0)"; #elif VISUALSTUDIO_15_0 string versionParameter = "-version [15.0,16.0)"; #else string versionParameter = "-latest"; #endif System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(vsWherePath, versionParameter + " -property installationPath"); startInfo.RedirectStandardOutput = true; startInfo.UseShellExecute = false; startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; using (System.Diagnostics.Process p = System.Diagnostics.Process.Start(startInfo)) { string paths = p.StandardOutput.ReadToEnd(); p.WaitForExit(); string[] pathArray = paths.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); if (pathArray.Length > 0) { installDir = Path.Combine(pathArray[pathArray.Length - 1], "VSSDK"); } } } } } if (string.IsNullOrEmpty(installDir)) { log.LogError("Unable to find Visual Studio SDK installation directory."); return(false); } DirectoryInfo installDirInfo = new DirectoryInfo(installDir); if (!installDirInfo.Exists) { log.LogError("Visual Studio SDK installation directory \"{0}\" does not exist.", installDir); return(false); } installDir = this._installationDirectory = installDirInfo.FullName; // Get the include files directory DirectoryInfo includesDirInfo = new DirectoryInfo(Path.Combine(installDir, VsSdkIncludeFilesSubdirectory)); if (includesDirInfo.Exists) { string includesDir = this._includesDirectory = includesDirInfo.FullName; log.LogMessage(MessageImportance.Low, "Visual Studio SDK include files directory found at \"{0}\".", includesDir); } else { log.LogWarning("Visual Studio SDK include files directory \"{0}\" does not exist.", includesDirInfo.FullName); } // Get the tools directory DirectoryInfo toolsDirInfo = new DirectoryInfo(Path.Combine(installDir, VsSdkToolsSubdirectory)); if (toolsDirInfo.Exists) { string toolsDir = this._toolsDirectory = toolsDirInfo.FullName; log.LogMessage(MessageImportance.Low, "Visual Studio SDK tools directory found at \"{0}\".", toolsDir); } else { log.LogWarning("Visual Studio SDK tools directory \"{0}\" does not exist.", toolsDirInfo.FullName); } // Get the redistributables directory DirectoryInfo redistributablesDirInfo = new DirectoryInfo(Path.Combine(installDir, VsSdkRedistributablesSubdirectory)); if (redistributablesDirInfo.Exists) { string redistributablesDir = this._redistributablesDirectory = redistributablesDirInfo.FullName; log.LogMessage(MessageImportance.Low, "Visual Studio SDK redistributables directory found at \"{0}\".", redistributablesDir); } else { log.LogWarning("Visual Studio SDK redistributables directory \"{0}\" does not exist.", redistributablesDirInfo.FullName); } return(true); }
public void LogMessage(string message) { string messageWithNameTag = GetMessageWithNameTag(message); _taskLoggingHelper.LogMessage(messageWithNameTag); }
/// <summary> /// Logs an informational message. /// </summary> /// <param name="message">The non-empty message that should be logged.</param> /// <param name="arguments">The arguments that should be used to format <paramref name="message" />.</param> public override void Info(string message, params object[] arguments) { _logger.LogMessage(String.Format(message, arguments)); }
public bool IsUpToDate(string assemblyPath, out bool containsFrameworkResources, out List <ResWInfo> reswInfoList) { reswInfoList = null; containsFrameworkResources = false; if (PortableLibraryStatesLookup == null) { PortableLibraryStatesLookup = new Dictionary <string, PortableLibraryResourceStateInfo>(); return(false); } if (PortableLibraryStatesLookup.Count == 0) { return(false); } try { if (assemblyPath == null || !File.Exists(assemblyPath)) { return(false); } PortableLibraryResourceStateInfo info; if (!PortableLibraryStatesLookup.TryGetValue(assemblyPath, out info)) { return(false); } FileInfo fiPlib = new FileInfo(assemblyPath); if (!fiPlib.LastWriteTimeUtc.Equals(info.PLibTimeUtc)) { _logger.LogMessage(MessageImportance.Low, Resources.Message_CachedReswNotUpToDateAssemblyNewer, assemblyPath); return(false); } if (info.ResWInfoList == null) { return(false); } else { foreach (ResWInfo reswInfo in info.ResWInfoList) { if (reswInfo.ResWPath == null || !File.Exists(reswInfo.ResWPath)) { _logger.LogMessage(MessageImportance.Low, Resources.Message_CachedReswNotExists, assemblyPath, reswInfo.ResWPath); return(false); } FileInfo fiResW = new FileInfo(reswInfo.ResWPath); if (!fiResW.LastWriteTimeUtc.Equals(reswInfo.ResWTimeUtc)) { _logger.LogMessage(MessageImportance.Low, Resources.Message_CachedReswNotUpToDate, reswInfo.ResWPath); return(false); } } } foreach (ResWInfo reswInfo in info.ResWInfoList) { _logger.LogMessage(MessageImportance.Low, Resources.Message_UsingCachedResw, reswInfo.ResWPath, assemblyPath); } reswInfoList = info.ResWInfoList; containsFrameworkResources = info.ContainsFrameworkResources; return(true); } catch (Exception e) { _logger.LogMessage(MessageImportance.Low, Resources.Error_UnspecifiedCheckUpToDate, assemblyPath, e.Message); return(false); } }
public void Log(string fmt, params object[] args) { Logger.LogMessage(fmt, args); }
/// <summary> /// Outputs messages based on whether the task is initiated within visual studio IDE or not /// </summary> internal void LogMessage(string message, params object[] args) { m_logHelper.LogMessage(MessageImportance.High, Prefix + message, args); }
public void WriteLine(string output) { _loggingHelper.LogMessage(output); }
public void LogDebug(string data) { _taskLogging.LogMessage(MessageImportance.Low, data); }
public void Info(string message) { _underlying.LogMessage(message); }
private static RegexCompilationInfo LoadRegexCompilationInfo(TaskLoggingHelper log, string regexFilePath) { log.LogMessage("Loading RegexCompilationInfo from \"{0}\".", regexFilePath); bool isPublic = false; string name = null; string @namespace = null; string pattern = null; RegexOptions regexOptions = RegexOptions.Compiled; FileInfo fileInfo = new FileInfo(regexFilePath); using (FileStream fileStream = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete, (int)fileInfo.Length, FileOptions.SequentialScan)) { using (XmlReader xmlReader = XmlReader.Create(fileStream, XmlReaderSettings)) { while (xmlReader.MoveToNextAttribute() || xmlReader.Read()) { switch (xmlReader.NodeType) { case XmlNodeType.Element: case XmlNodeType.Attribute: switch (xmlReader.LocalName) { case "IsPublic": isPublic = xmlReader.ReadContentAsBoolean(); break; case "Name": name = xmlReader.ReadContentAsString(); break; case "Namespace": @namespace = xmlReader.ReadContentAsString(); break; case "CultureInvariant": regexOptions |= RegexOptions.CultureInvariant; break; case "ECMAScript": regexOptions |= RegexOptions.ECMAScript; break; case "ExplicitCapture": regexOptions |= RegexOptions.ExplicitCapture; break; case "IgnoreCase": regexOptions |= RegexOptions.IgnoreCase; break; case "IgnorePatternWhitespace": regexOptions |= RegexOptions.IgnorePatternWhitespace; break; case "Multiline": regexOptions |= RegexOptions.Multiline; break; case "RightToLeft": regexOptions |= RegexOptions.RightToLeft; break; case "Singleline": regexOptions |= RegexOptions.Singleline; break; case "Pattern": pattern = xmlReader.ReadElementContentAsString(); break; } break; } } } } RegexCompilationInfo regexCompilationInfo = new RegexCompilationInfo(pattern, regexOptions, name, @namespace, isPublic); log.LogMessage("RegexCompilationInfo loaded with settings:", null); log.LogMessage("\tNamespace:\t\t{0}", regexCompilationInfo.Namespace); log.LogMessage("\tName:\t\t\t{0}", regexCompilationInfo.Name); log.LogMessage("\tIsPublic:\t\t{0}", regexCompilationInfo.IsPublic); log.LogMessage("\tRegexOptions:\t{0}", regexCompilationInfo.Options); return(regexCompilationInfo); }
public void LogMessage(string message) { logger.LogMessage(message); }
/// <summary> /// Resolves a single reference item by searcheing for referenced items using the specified SearchPaths. /// This method is made public so the resolution logic can be reused by other tasks. /// </summary> /// <param name="reference">The referenced item.</param> /// <param name="searchPaths">The paths to search.</param> /// <param name="searchFilenameExtensions">Filename extensions to check.</param> /// <param name="log">Logging helper.</param> /// <returns>The resolved reference item, or the original reference if it could not be resolved.</returns> public static ITaskItem ResolveReference(ITaskItem reference, string[] searchPaths, string[] searchFilenameExtensions, TaskLoggingHelper log) { if (reference == null) { throw new ArgumentNullException("reference"); } if (searchPaths == null) { // Nothing to search, so just return the original reference item. return(reference); } if (searchFilenameExtensions == null) { searchFilenameExtensions = new string[] { }; } // Copy all the metadata from the source TaskItem resolvedReference = new TaskItem(reference); log.LogMessage(MessageImportance.Low, "WixReference: {0}", reference.ItemSpec); // Now find the resolved path based on our order of precedence foreach (string searchPath in searchPaths) { log.LogMessage(MessageImportance.Low, "Trying {0}", searchPath); if (searchPath.Equals(HintPathToken, StringComparison.Ordinal)) { string path = reference.GetMetadata("HintPath"); log.LogMessage(MessageImportance.Low, "Trying path {0}", path); if (File.Exists(path)) { resolvedReference.ItemSpec = path; break; } } else if (searchPath.Equals(RawFileNameToken, StringComparison.Ordinal)) { log.LogMessage(MessageImportance.Low, "Trying path {0}", resolvedReference.ItemSpec); if (File.Exists(resolvedReference.ItemSpec)) { break; } if (ResolveWixReferences.ResolveFilenameExtensions(resolvedReference, resolvedReference.ItemSpec, searchFilenameExtensions, log)) { break; } } else { string path = Path.Combine(searchPath, Path.GetFileName(reference.ItemSpec)); log.LogMessage(MessageImportance.Low, "Trying path {0}", path); if (File.Exists(path)) { resolvedReference.ItemSpec = path; break; } if (ResolveWixReferences.ResolveFilenameExtensions(resolvedReference, path, searchFilenameExtensions, log)) { break; } } } // Normalize the item path resolvedReference.ItemSpec = resolvedReference.GetMetadata("FullPath"); return(resolvedReference); }
public void WriteInfo(string message) { _logHelper.LogMessage(message); }