public virtual IProcess StartProcess(ToolSettings toolSettings, ProcessSettings processSettings = null) { var toolPath = toolSettings.ToolPath; var arguments = toolSettings.GetArguments(); var argumentsForExecution = arguments.RenderForExecution(); var argumentsForOutput = arguments.RenderForOutput(); #if NETCORE if (EnvironmentInfo.IsUnix && toolPath.EndsWithOrdinalIgnoreCase("exe")) { argumentsForExecution = $"{toolPath.DoubleQuoteIfNeeded()} {argumentsForExecution}"; argumentsForOutput = $"{toolPath.DoubleQuoteIfNeeded()} {argumentsForOutput}"; toolPath = ToolPathResolver.GetPathExecutable("mono"); } #endif ControlFlow.Assert(toolPath != null, "ToolPath was not set."); ControlFlow.Assert(File.Exists(toolPath), $"ToolPath '{toolPath}' does not exist."); Logger.Info($"> {Path.GetFullPath(toolPath).DoubleQuoteIfNeeded()} {argumentsForOutput}"); processSettings = processSettings ?? new ProcessSettings(); return(StartProcessInternal( toolPath, argumentsForExecution, toolSettings.WorkingDirectory, processSettings.EnvironmentVariables, processSettings.ExecutionTimeout, processSettings.RedirectOutput, arguments.Filter)); }
private static void AssertTaskSettings(KeyVaultTaskSettings settings) { ControlFlow.Assert(settings.VaultBaseUrl != null && settings.SecretName != null, "settings.VaultBaseUrl != null && settings.SecretName != null"); ControlFlow.Assert(settings.ClientSecret != null, "settings.ClientSecret != null"); ControlFlow.Assert(settings.ClientId != null, "settings.ClientId != null"); }
private object ConvertValues(IReadOnlyCollection<string> values, Type destinationType) { ControlFlow.Assert(!destinationType.IsArray || destinationType.GetArrayRank() == 1, "Arrays must have a rank of 1."); var elementType = (destinationType.IsArray ? destinationType.GetElementType() : destinationType).NotNull(); ControlFlow.Assert(values.Count < 2 || elementType != null, "values.Count < 2 || elementType != null"); if (values.Count == 0) { if (destinationType.IsArray) return Array.CreateInstance(elementType, length: 0); if (destinationType == typeof(bool) || destinationType == typeof(bool?)) return true; return null; } var convertedValues = values.Select(x => Convert(x, elementType)).ToList(); if (!destinationType.IsArray) { ControlFlow.Assert(convertedValues.Count == 1, $"Value [ {values.JoinComma()} ] cannot be assigned to '{GetPresentableName(destinationType)}'."); return convertedValues.Single(); } var array = Array.CreateInstance(elementType, convertedValues.Count); convertedValues.ForEach((x, i) => array.SetValue(x, i)); ControlFlow.Assert(destinationType.IsInstanceOfType(array), $"Type '{GetPresentableName(array.GetType())}' is not an instance of '{GetPresentableName(destinationType)}'."); return array; }
// TODO: add HasLocalInstalledPackage() ? // ReSharper disable once CyclomaticComplexity public static IEnumerable <InstalledPackage> GetLocalInstalledPackages( string packagesConfigFile = null, bool includeDependencies = false) { packagesConfigFile = packagesConfigFile ?? DefaultPackagesConfigFile; ControlFlow.Assert(!IncludesDependencies(packagesConfigFile) || includeDependencies, $"!IncludesDependencies({packagesConfigFile}) || includeDependencies"); var packagesDirectory = GetPackagesDirectory(packagesConfigFile); var packageIds = XmlTasks.XmlPeek( packagesConfigFile, IsLegacyFile(packagesConfigFile) ? ".//package/@id" : ".//*[local-name() = 'PackageReference']/@Include"); var installedPackages = new HashSet <InstalledPackage>(InstalledPackage.Comparer.Instance); foreach (var packageId in packageIds) { // TODO: use xml namespaces // TODO: version as tag var version = XmlTasks.XmlPeekSingle( packagesConfigFile, IsLegacyFile(packagesConfigFile) ? $".//package[@id='{packageId}']/@version" : $".//*[local-name() = 'PackageReference'][@Include='{packageId}']/@Version"); var packageData = GetGlobalInstalledPackage(packageId, version, packagesDirectory); if (packageData == null) { continue; } installedPackages.Add(packageData); yield return(packageData); } if (includeDependencies) { var packagesToCheck = new Queue <InstalledPackage>(installedPackages); while (packagesToCheck.Any()) { var packageToCheck = packagesToCheck.Dequeue(); foreach (var dependentPackage in GetDependentPackages(packageToCheck, packagesDirectory)) { if (installedPackages.Contains(dependentPackage)) { continue; } installedPackages.Add(dependentPackage); packagesToCheck.Enqueue(dependentPackage); yield return(dependentPackage); } } } }
public static string Combine([CanBeNull] string path1, string path2, char?separator = null) { // TODO: better something like "SafeHandleRoots"? path1 = Trim(path1); path2 = Trim(path2); ControlFlow.Assert(!HasPathRoot(path2), "Second path must not be rooted."); if (string.IsNullOrWhiteSpace(path1)) { return(path2); } if (string.IsNullOrWhiteSpace(path2)) { return(!IsWinRoot(path1) ? path1 : $@"{path1}\"); } AssertSeparatorChoice(path1, separator); separator = separator ?? GetSeparator(path1); if (IsWinRoot(path1)) { return($@"{path1}\{path2}"); } if (IsUnixRoot(path1)) { return($"{path1}{path2}"); } if (IsUncRoot(path1)) { return($@"{path1}\{path2}"); } return($"{path1}{separator}{path2}"); }
public static string GetDirectoryHash(string directory, params string[] fileGlobPatterns) { ControlFlow.Assert(Directory.Exists(directory), $"Directory.Exists({directory})"); var files = (fileGlobPatterns.Length == 0 ? Directory.GetFiles(directory, "*", SearchOption.AllDirectories) : PathConstruction.GlobFiles(directory, fileGlobPatterns)) .OrderBy(x => x).ToList(); using (var md5 = MD5.Create()) { foreach (var file in files) { var relativePath = PathConstruction.GetRelativePath(directory, file); var unixNormalizedPath = PathConstruction.NormalizePath(relativePath, separator: '/'); var pathBytes = Encoding.UTF8.GetBytes(unixNormalizedPath); md5.TransformBlock(pathBytes, inputOffset: 0, inputCount: pathBytes.Length, outputBuffer: pathBytes, outputOffset: 0); var contentBytes = File.ReadAllBytes(file); md5.TransformBlock(contentBytes, inputOffset: 0, inputCount: contentBytes.Length, outputBuffer: contentBytes, outputOffset: 0); } md5.TransformFinalBlock(new byte[0], inputOffset: 0, inputCount: 0); return(BitConverter.ToString(md5.Hash).Replace("-", "").ToLower()); } }
public static async Task <IEnumerable <(string DownloadUrl, string RelativePath)> > GetGitHubDownloadUrls( this GitRepository repository, string directory = null, string branch = null) { ControlFlow.Assert(repository.IsGitHubRepository(), "repository.IsGitHubRepository()"); ControlFlow.Assert(!HasPathRoot(directory) || repository.LocalDirectory != null, "!HasPathRoot(directory) || repository.LocalDirectory != null"); var relativeDirectory = HasPathRoot(directory) ? GetRelativePath(repository.LocalDirectory, directory) : directory; relativeDirectory = (relativeDirectory + "/").TrimStart("/"); branch ??= await repository.GetDefaultBranch(); var treeResponse = await Client.Git.Tree.GetRecursive( repository.GetGitHubOwner(), repository.GetGitHubName(), branch); return(treeResponse.Tree .Where(x => x.Type == TreeType.Blob) .Where(x => x.Path.StartsWithOrdinalIgnoreCase(relativeDirectory)) .Select(x => (repository.GetGitHubDownloadUrl(x.Path, branch), x.Path.TrimStart(relativeDirectory)))); }
public static (string, string) GetLookupTableKeyValueTypes(this Property property) { ControlFlow.Assert(property.IsLookupTable(), "property.IsLookupTable()"); var generics = GetGenerics(property); return(generics[0], generics[1]); }
/// <summary> /// Parses MSBuild project file. /// </summary> public static MSBuildProject MSBuildParseProject(string projectFile, Configure <MSBuildSettings> configurator = null) { Logger.Trace($"Parsing project file '{projectFile}'..."); var content = TextTasks.ReadAllText(projectFile); var isSdkProject = content.Contains("Sdk=\"Microsoft.NET.Sdk\""); var isLegacyProject = content.Contains("http://schemas.microsoft.com/developer/msbuild/2003"); ControlFlow.Assert((isSdkProject || isLegacyProject) && (!isSdkProject || !isLegacyProject), "Unknown format."); var toolSettings = configurator.InvokeSafe(new MSBuildSettings()) .DisableLogOutput() .SetProjectFile(projectFile) .SetVerbosity(MSBuildVerbosity.Diagnostic) .SetTargets(Guid.NewGuid().ToString()); var process = ProcessTasks.StartProcess(toolSettings); process.AssertWaitForExit(); var lines = process.Output.Select(x => x.Text).ToArray(); var properties = ParseProperties(lines); var itemGroups = ParseItemGroups(lines); return(new MSBuildProject(isSdkProject, properties, itemGroups)); }
public Arguments Add <TKey, TValue>( string argumentFormat, [CanBeNull] IReadOnlyDictionary <TKey, TValue> dictionary, string itemFormat, char?separator = null, char?disallowed = null, bool quoteMultiple = false) { if (dictionary == null || dictionary.Count == 0) { return(this); } argumentFormat = argumentFormat.Replace("{value}", "{0}"); var keyValueSeparator = itemFormat.Replace("{key}", string.Empty).Replace("{value}", string.Empty); ControlFlow.Assert(keyValueSeparator.Length == 1, "keyValueSeparator.Length == 1"); string Format(object value) => value.ToString().DoubleQuoteIfNeeded(separator, keyValueSeparator.Single(), disallowed, Space); string FormatPair(KeyValuePair <TKey, TValue> pair) => itemFormat .Replace("{key}", Format(pair.Key)) .Replace("{value}", Format(pair.Value)); var pairs = dictionary.Where(x => x.Value.NotNullWarn($"Value for '{x.Key}' is 'null', omitting...") != null).ToList(); AddInternal( argumentFormat, separator.HasValue ? new[] { FormatMultiple(pairs, FormatPair, separator.Value, quoteMultiple) } : pairs.Select(FormatPair).ToArray()); return(this); }
public static (string, string) GetDictionaryKeyValueTypes(this Property property) { ControlFlow.Assert(property.IsDictionary(), "property.IsDictionary()"); var generics = GetGenerics(property); return(generics[0], generics[1]); }
public static async Task SendTweetAsync( string message, string consumerKey, string consumerSecret, string accessToken, string accessTokenSecret) { var timestamp = ConvertToUnixTimestamp(DateTime.Now).ToString(CultureInfo.InvariantCulture); var data = new Dictionary <string, string> { { "status", message }, { "trim_user", "1" }, { "oauth_consumer_key", consumerKey }, { "oauth_nonce", Convert.ToBase64String(Encoding.UTF8.GetBytes(timestamp)) }, { "oauth_signature_method", "HMAC-SHA1" }, { "oauth_timestamp", timestamp }, { "oauth_token", accessToken }, { "oauth_version", "1.0" } }; data.AddKeyValue("oauth_signature", GetOAuthSignature(data, c_url, consumerSecret, accessTokenSecret)); var authorization = GetOAuthHeader(data); var formData = new FormUrlEncodedContent(data.Where(kvp => !kvp.Key.StartsWith("oauth_"))); using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", authorization); var response = await client.PostAsync(c_url, formData); var responseBody = await response.Content.ReadAsStringAsync(); ControlFlow.Assert(response.StatusCode == HttpStatusCode.OK, $"StatusCode != 200 - '{GetErrorFromBody(responseBody)}'"); }
bool ShouldUpdateChangelog() { bool TryGetChangelogSectionNotes(string tag, out string[] sectionNotes) { sectionNotes = new string[0]; try { sectionNotes = ExtractChangelogSectionNotes(ChangelogFile, tag).ToArray(); return(sectionNotes.Length > 0); } catch (System.Exception) { return(false); } } var nextSectionAvailable = TryGetChangelogSectionNotes("vNext", out var vNextSection); var semVerSectionAvailable = TryGetChangelogSectionNotes(GitVersion.MajorMinorPatch, out var semVerSection); if (semVerSectionAvailable) { ControlFlow.Assert(!nextSectionAvailable, $"{GitVersion.MajorMinorPatch} is already in changelog."); return(false); } return(nextSectionAvailable); }
public virtual IProcess StartProcess( string toolPath, string arguments = null, string workingDirectory = null, IReadOnlyDictionary <string, string> environmentVariables = null, int?timeout = null, bool redirectOutput = false, Func <string, string> outputFilter = null) { ControlFlow.Assert(toolPath != null, "ToolPath was not set."); if (!Path.IsPathRooted(toolPath) && !toolPath.Contains(Path.DirectorySeparatorChar)) { toolPath = ToolPathResolver.GetPathExecutable(toolPath); } ControlFlow.Assert(File.Exists(toolPath), $"ToolPath '{toolPath}' does not exist."); Logger.Info($"> {Path.GetFullPath(toolPath).DoubleQuoteIfNeeded()} {arguments}"); return(StartProcessInternal(toolPath, arguments, workingDirectory, environmentVariables, timeout, redirectOutput, outputFilter ?? (x => x))); }
/// <summary> /// Finalizes the changelog by moving all entries from `[vNext]` to the version specified by release. /// <p>If <paramref name="repository"/> is specified a summary with all versions and links to list the changes directly on GitHub is appended to the end of the changelog.</p> /// </summary> /// <param name="changelogFile">The path to the changelog file.</param> /// <param name="tag">The <see cref="NuGetVersion"/> to finalize the changelog.</param> /// <param name="repository">The repository to create the version overview for.</param> /// <seealso cref="FinalizeChangelog(ChangeLog,NuGetVersion,GitRepository)"/> public static void FinalizeChangelog(ChangeLog changelogFile, NuGetVersion tag, [CanBeNull] GitRepository repository = null) { Logger.Info($"Finalizing {PathConstruction.GetRelativePath(NukeBuild.RootDirectory, changelogFile.Path)} for '{tag}'..."); var unreleasedNotes = changelogFile.Unreleased; var releaseNotes = changelogFile.ReleaseNotes; var lastReleased = changelogFile.LatestVersion; ControlFlow.Assert(unreleasedNotes != null, "Changelog should have draft section."); ControlFlow.Assert(releaseNotes.Any(x => x.Version != null && x.Version.Equals(tag)), $"Tag '{tag}' already exists."); ControlFlow.Assert(lastReleased != null && tag.CompareTo(lastReleased.Version) > 0, $"Tag '{tag}' is not greater compared to last tag '{lastReleased.NotNull().Version}'."); var path = changelogFile.Path; var content = TextTasks.ReadAllLines(path).ToList(); content.Insert(unreleasedNotes.StartIndex + 1, string.Empty); content.Insert(unreleasedNotes.EndIndex + 2, $"## [{tag}] / {DateTime.Now:yyyy-MM-dd}"); UpdateVersionSummary(tag.ToString(), content, repository); content.Add(string.Empty); TextTasks.WriteAllLines(path, content); }
public static void InjectValues(NukeBuild build) { var injectionMembers = build.GetType() .GetMembers(c_bindingFlags) .Where(x => x.GetCustomAttributes <InjectionAttributeBase>().Any()).ToList(); foreach (var member in injectionMembers) { var attributes = member.GetCustomAttributes().OfType <InjectionAttributeBase>().ToList(); if (attributes.Count == 0) { continue; } ControlFlow.Assert(attributes.Count == 1, $"Member '{member.Name}' has multiple injection attributes applied."); var attribute = attributes.Single(); var memberType = (member as FieldInfo)?.FieldType ?? ((PropertyInfo)member).PropertyType; var value = attribute.GetValue(member.Name, memberType); if (value == null) { continue; } var valueType = value.GetType(); ControlFlow.Assert(memberType.IsAssignableFrom(valueType), $"Field '{member.Name}' must be of type '{valueType.Name}' to get its valued injected from '{attribute.GetType().Name}'."); SetValue(build, member, value); } }
/// <summary> /// Obtains information from a local git repository. Auto-injection can be utilized via <see cref="GitRepositoryAttribute"/>. /// </summary> public static GitRepository FromLocalDirectory(string directory, string branch = null, string remote = "origin") { var rootDirectory = FileSystemTasks.FindParentDirectory(directory, x => x.GetDirectories(".git").Any()); ControlFlow.Assert(rootDirectory != null, $"Could not find root directory for '{directory}'."); var gitDirectory = Path.Combine(rootDirectory, ".git"); var headFile = Path.Combine(gitDirectory, "HEAD"); ControlFlow.Assert(File.Exists(headFile), $"File.Exists({headFile})"); var headFileContent = File.ReadAllLines(headFile); var head = headFileContent.First(); var branchMatch = Regex.Match(head, "^ref: refs/heads/(?<branch>.*)"); var configFile = Path.Combine(gitDirectory, "config"); var configFileContent = File.ReadAllLines(configFile); var url = configFileContent .Select(x => x.Trim()) .SkipWhile(x => x != $"[remote \"{remote}\"]") .Skip(count: 1) .TakeWhile(x => !x.StartsWith("[")) .SingleOrDefault(x => x.StartsWithOrdinalIgnoreCase("url = ")) ?.Split('=')[1]; ControlFlow.Assert(url != null, $"Could not parse remote URL for '{remote}'."); var(endpoint, identifier) = ParseUrl(url); return(new GitRepository( endpoint, identifier, rootDirectory, head, branch ?? (branchMatch.Success ? branchMatch.Groups["branch"].Value : null))); }
/// <summary> /// Runs the Publish command for either Test or Prod. /// </summary> /// <returns></returns> public bool ExecutePublish() { if (SkippedTargets.Count > 0) { ControlFlow.Assert( 1 == 0, "You cannot use the --skip flag with PublishProd. PublishProd Process requires the previous steps to have completed."); } if (!SkipNuget) { GlobFiles(OutputDirectory, "*.nupkg") .NotEmpty() .Where(x => !x.EndsWith("symbols.nupkg")) .ForEach(x => { IReadOnlyCollection <Output> nugetOutput = null; try { nugetOutput = DotNetNuGetPush(s => s.SetTargetPath(x).SetSource(NugetRepoUrl).SetApiKey(NugetApiKey).SetSkipDuplicate(true)); if (nugetOutput.Count > 0) { // Look for skipped message. foreach (Output outputLine in nugetOutput) { if (outputLine.Text.Contains("already exists at feed")) { string msg = @"A nuget package <" + Path.GetFileName(x) + "> with this name and version already exists. " + "Assuming this is due to you re-running the publish after a prior error that occurred after the push to Nuget was successful. " + "Will carry on as though this push was successfull. " + "Otherwise, if this should have been a new update, then you will need to make another commit and re-publish"; Logger.Warn(msg); } else { PublishResults.Add(new PublishResult("", "Nuget", x)); } } } } catch (ProcessException pe) { if (!NugetRepoUrl.Contains("nuget.org")) { Logger.Warn("The nuget Push process threw an error. Since you are using a service other than Nuget this may be a service outage with the site or it might mean the version of the library you are pushing already exists. You will need to perform a manual check to determine which it is."); } else { throw pe; } } }); // Now process Copy Outputs. PublishCopiedFolders(); Logger.Success("Version: " + _gitProcessor.Version + " fully committed and deployed to target location."); } return(true); }
protected override void AssertValid() { base.AssertValid(); ControlFlow.Assert(File.Exists(WebConfigFilename), "File.Exists(WebConfigFilename )"); ControlFlow.Assert(File.Exists(TransformFilename), "File.Exists(TransformFilename)"); ControlFlow.Assert(OutputFilename != null, "OutputFilename != null"); }
private static string GetHead(string gitDirectory) { var headFile = Path.Combine(gitDirectory, "HEAD"); ControlFlow.Assert(File.Exists(headFile), $"File.Exists({headFile})"); return(File.ReadAllText(headFile).TrimStart("ref: ").Trim()); }
public static void ValidateRequirements(NukeBuild build, IReadOnlyCollection <ExecutableTarget> executingTargets) { foreach (var target in executingTargets) { foreach (var requirement in target.Requirements) { if (requirement is Expression <Func <bool> > boolExpression) { ControlFlow.Assert(boolExpression.Compile().Invoke(), $"Target '{target.Name}' requires '{requirement.Body}'."); } else if (IsMemberNull(requirement.GetMemberInfo(), build, target)) { ControlFlow.Fail($"Target '{target.Name}' requires member '{requirement.GetMemberInfo().Name}' to be not null."); } } } var requiredMembers = InjectionUtility.GetParameterMembers(build.GetType(), includeUnlisted: true) .Where(x => x.HasCustomAttribute <RequiredAttribute>()); foreach (var member in requiredMembers) { if (IsMemberNull(member, build)) { ControlFlow.Fail($"Member '{member.Name}' is required to be not null."); } } }
/// <summary> /// Obtains information from a local git repository. Auto-injection can be utilized via <see cref="GitRepositoryAttribute"/>. /// </summary> public static GitRepository FromLocalDirectory(string directory) { var rootDirectory = FileSystemTasks.FindParentDirectory(directory, x => x.GetDirectories(".git").Any()); ControlFlow.Assert(rootDirectory != null, $"Could not find git directory for '{directory}'."); var gitDirectory = Path.Combine(rootDirectory, ".git"); var head = GetHead(gitDirectory); var branch = ((Host.Instance as IBuildServer)?.Branch ?? GetHeadIfAttached(head))?.TrimStart("refs/heads/").TrimStart("origin/"); var commit = (Host.Instance as IBuildServer)?.Commit ?? GetCommitFromHead(gitDirectory, head); var tags = GetTagsFromCommit(gitDirectory, commit); var(remoteName, remoteBranch) = GetRemoteNameAndBranch(gitDirectory, branch); var(protocol, endpoint, identifier) = GetRemoteConnectionFromConfig(gitDirectory, remoteName ?? FallbackRemoteName); return(new GitRepository( protocol, endpoint, identifier, branch, rootDirectory, head, commit, tags, remoteName, remoteBranch)); }
public void ImportData( TeamCityImportType type, string path, TeamCityImportTool?tool = null, bool?verbose = null, bool?parseOutOfDate = null, TeamCityNoDataPublishedAction?action = null) { ControlFlow.Assert( type != TeamCityImportType.dotNetCoverage || tool != null, $"Importing data of type '{type}' requires to specify the tool."); ControlFlow.AssertWarn( tool == TeamCityImportTool.dotcover && ConfigurationProperties["teamcity.dotCover.home"].EndsWithOrdinalIgnoreCase("bundled"), new[] { "Configuration parameter 'teamcity.dotCover.home' is set to the bundled version.", $"Adding the '{nameof(TeamCitySetDotCoverHomePathAttribute)}' will automatically set " + $"it to '{nameof(DotCoverTasks)}.{DotCoverTasks.DotCoverPath}'." }.JoinNewLine()); Write("importData", x => x .AddKeyValue("type", type) .AddKeyValue("path", path) .AddKeyValue("tool", tool) .AddKeyValue("verbose", verbose) .AddKeyValue("parseOutOfDate", parseOutOfDate) .AddKeyValue("whenNoDataPublished", action)); }
public static IProcess AssertWaitForExit( [AssertionCondition(AssertionConditionType.IS_NOT_NULL)][CanBeNull] this IProcess process) { ControlFlow.Assert(process != null && process.WaitForExit(), "process != null && process.WaitForExit()"); return(process); }
/// <summary><p>Load an Azure Key Vault to obtain secrets.</p></summary> public static KeyVault LoadVault(KeyVaultTaskSettings settings) { AssertTaskSettings(settings); ControlFlow.Assert(settings.VaultBaseUrl != null, "settings.VaultBaseUrl != null"); return(CreateVault(settings)); }
public object GetCommandLineArgument(string argumentName, Type destinationType, char?separator = null) { var args = _commandLineArgumentsProvider.Invoke(); var index = Array.FindLastIndex(args, x => x.EqualsOrdinalIgnoreCase($"-{argumentName}")); if (index == -1) { return(GetDefaultValue(destinationType)); } var values = args.Skip(index + 1).TakeWhile(x => !x.StartsWith("-")).ToArray(); ControlFlow.Assert(values.Length == 1 || !separator.HasValue || values.All(x => !x.Contains(separator.Value)), $"Command-line argument '{argumentName}' with value [ {values.JoinComma()} ] cannot be split with separator '{separator}'."); values = separator.HasValue && values.Any(x => x.Contains(separator.Value)) ? values.SingleOrDefault()?.Split(separator.Value) ?? new string[0] : values; try { return(ConvertValues(argumentName, values, destinationType)); } catch (Exception ex) { ControlFlow.Fail( new[] { ex.Message, "Command-line arguments were:" } .Concat(args.Select((x, i) => $" [{i}] = {x}")) .JoinNewLine()); return(null); } }
public object ConvertCommandLineArguments( string argumentName, string[] values, Type destinationType, string[] commandLineArguments, char? separator = null) { ControlFlow.Assert(values.Length == 1 || !separator.HasValue || values.All(x => !x.Contains(separator.Value)), $"Command-line argument '{argumentName}' with value [ {values.JoinComma()} ] cannot be split with separator '{separator}'."); values = separator.HasValue && values.Any(x => x.Contains(separator.Value)) ? values.SingleOrDefault()?.Split(separator.Value) ?? new string[0] : values; try { return ConvertValues(argumentName, values, destinationType); } catch (Exception ex) { ControlFlow.Fail( new[] { ex.Message, "Command-line arguments were:" } .Concat(commandLineArguments.Select((x, i) => $" [{i}] = {x}")) .JoinNewLine()); // ReSharper disable once HeuristicUnreachableCode return null; } }
/// <summary> /// Finalizes the changelog by moving all entries from `[vNext]` to the version specified by release. /// <p>If <paramref name="repository"/> is specified a summary with all versions and links to list the changes directly on GitHub is appended to the end of the changelog.</p> /// </summary> /// <param name="changelogFile">The path to the changelog file.</param> /// <param name="tag">The version to finalize the changelog.</param> /// <param name="repository">The repository to create the version overview for.</param> /// <seealso cref="FinalizeChangelog(ChangeLog,NuGetVersion,GitRepository)"/> public static void FinalizeChangelog(string changelogFile, string tag, [CanBeNull] GitRepository repository = null) { Logger.Info($"Finalizing {PathConstruction.GetRelativePath(NukeBuild.RootDirectory, changelogFile)} for '{tag}'..."); var content = TextTasks.ReadAllLines(changelogFile).ToList(); var sections = GetReleaseSections(content).ToList(); var firstSection = sections.First(); var secondSection = sections.Skip(1).FirstOrDefault(); ControlFlow.Assert(firstSection.Caption.All(char.IsLetter), "Cannot find a draft section."); ControlFlow.Assert(sections.All(x => !x.Caption.EqualsOrdinalIgnoreCase(tag)), $"Tag '{tag}' already exists."); ControlFlow.Assert(firstSection.EndIndex > firstSection.StartIndex, $"Draft section '{firstSection.Caption}' does not contain any information."); ControlFlow.Assert(secondSection == null || NuGetVersion.Parse(tag).CompareTo(NuGetVersion.Parse(secondSection.Caption)) > 0, $"Tag '{tag}' is not greater compared to last tag '{secondSection?.Caption}'."); content.Insert(firstSection.StartIndex + 1, string.Empty); content.Insert(firstSection.StartIndex + 2, $"## [{tag}] / {DateTime.Now:yyyy-MM-dd}"); UpdateVersionSummary(tag, content, repository); content.Add(string.Empty); TextTasks.WriteAllLines(changelogFile, content); }
protected override void AssertValid() { base.AssertValid(); ControlFlow.Assert(File.Exists(ConfigPath) || ConfigPath == null, "File.Exists(ConfigPath) || ConfigPath == null"); ControlFlow.Assert(Directory.Exists(RepositoryRoot) || RepositoryRoot == null, "Directory.Exists(RepositoryRoot) || RepositoryRoot == null"); ControlFlow.Assert(Directory.Exists(Theme) || Theme == null, "Directory.Exists(Theme) || Theme == null"); }
/// <summary> /// Interpret the Refs section into individual elements /// </summary> /// <param name="refArg"></param> private void ProcessRefs(string refArg) { // Convert the last field in output into multiple fields int first = refArg.IndexOf('('); ControlFlow.Assert(first > -1, "Unable to locate the property results starting character - ("); int last = refArg.IndexOf(')'); ControlFlow.Assert(last > -1, "Unable to locate the property results ending character - )"); string props = refArg.Substring(++first, last - first); string[] properties = props.Split(','); // Now loop thru the properties for common elements that we further split out. foreach (string property in properties) { string propStr = property.Trim(); if (propStr.StartsWith("tag:")) { Tags.Add(propStr.Substring(5)); } else { Branches.Add(propStr); } } }