├── src
├── Directory.Build.targets
├── Orc.CommandLine.Tests
│ ├── ModuleInitializer.cs
│ ├── Models
│ │ ├── OptionDefinitionFacts.cs
│ │ └── Extensions
│ │ │ └── OptionDefinitionExtensionsFacts.cs
│ ├── FodyWeavers.xml
│ ├── Context
│ │ ├── BrandingCommandLineContext.cs
│ │ ├── TestContextWithFile.cs
│ │ ├── TestContextWithMandatoryOption.cs
│ │ └── TestContext.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── PublicApiFacts.cs
│ ├── Extensions
│ │ └── StringExtensionsFacts.cs
│ ├── Orc.CommandLine.Tests.csproj
│ └── Parsers
│ │ ├── CommandLineParserFacts.issues.cs
│ │ └── CommandLineParserFacts.cs
├── global.json
├── Orc.CommandLine
│ ├── Services
│ │ ├── Interfaces
│ │ │ ├── ICommandLineService.cs
│ │ │ ├── IOptionDefinitionService.cs
│ │ │ └── IHelpWriterService.cs
│ │ ├── CommandLineService.cs
│ │ ├── OptionDefinitionService.cs
│ │ └── HelpWriterService.cs
│ ├── FodyWeavers.xml
│ ├── Context
│ │ ├── Interfaces
│ │ │ └── IContext.cs
│ │ └── ContextBase.cs
│ ├── Exceptions
│ │ └── CommandLineException.cs
│ ├── Parsers
│ │ ├── Interfaces
│ │ │ └── ICommandLineParser.cs
│ │ └── Extensions
│ │ │ └── ICommandLineParserExtensions.cs
│ ├── Properties
│ │ ├── AssemblyInfo.cs
│ │ ├── Resources.de.resx
│ │ ├── Resources.es.resx
│ │ ├── Resources.fr.resx
│ │ ├── Resources.nl.resx
│ │ ├── Resources.ru.resx
│ │ └── Resources.Designer.cs
│ ├── Attributes
│ │ └── OptionAttribute.cs
│ ├── ModuleInitializer.cs
│ ├── Models
│ │ ├── OptionDefinition.cs
│ │ └── Extensions
│ │ │ └── OptionDefinitionExtensions.cs
│ ├── Orc.CommandLine.csproj
│ ├── Extensions
│ │ └── StringExtensions.cs
│ └── MultilingualResources
│ │ ├── Orc.CommandLine.de.xlf
│ │ ├── Orc.CommandLine.es.xlf
│ │ ├── Orc.CommandLine.fr.xlf
│ │ ├── Orc.CommandLine.nl.xlf
│ │ └── Orc.CommandLine.ru.xlf
├── Directory.Build.nullable.props
├── Directory.Build.implicitusings.props
├── Directory.Build.project.props
├── SolutionAssemblyInfo.cs
├── GlobalSuppressions.cs
├── nuget.config
├── MethodTimeLogger.cs
├── Directory.Build.shared.tests.props
├── Directory.Build.props
├── Directory.Build.shared.tools.props
├── Directory.Build.shared.mat.props
├── Directory.Build.analyzers.props
├── .vsconfig
├── Directory.Build.shared.xamltools.props
├── Orc.CommandLine.sln
└── Directory.Build.shared.implicit.props
├── tools
└── nuget.exe
├── design
└── Package
│ └── Icon.png
├── GitVersion.yml
├── cake.config
├── deployment
└── cake
│ ├── codesigning-tasks.cake
│ ├── templates-variables.cake
│ ├── issuetrackers.cake
│ ├── codesigning-variables.cake
│ ├── tools-variables.cake
│ ├── vsextensions-variables.cake
│ ├── tests-nunit.cake
│ ├── components-variables.cake
│ ├── lib-logging.cake
│ ├── apps-uwp-variables.cake
│ ├── notifications.cake
│ ├── docker-variables.cake
│ ├── tests-variables.cake
│ ├── issuetrackers-jira.cake
│ ├── sourcecontrol-github.cake
│ ├── github-pages-variables.cake
│ ├── sourcecontrol.cake
│ ├── templates-tasks.cake
│ ├── issuetrackers-github.cake
│ ├── notifications-msteams.cake
│ ├── dependencies-variables.cake
│ ├── lib-sourcelink.cake
│ ├── apps-wpf-variables.cake
│ ├── aspire-variables.cake
│ ├── lib-nuget.cake
│ ├── buildserver-continuaci.cake
│ └── aspire-tasks.cake
├── .config
└── dotnet-tools.json
├── .github
├── ISSUE_TEMPLATE
│ ├── --thank-you.md
│ ├── ---support-request.md
│ ├── --bug.md
│ └── --feature-request.md
├── FUNDING.yml
├── dependabot.yml
├── stale.yml
├── support.yml
├── workflows
│ └── build-and-test.yml
├── PULL_REQUEST_TEMPLATE.md
├── lock.yml
└── CONTRIBUTING.md
├── GitReleaseManager.yaml
├── AUTHORS
├── CONTRIBUTORS
├── README.md
├── LICENSE
├── .gitattributes
├── .gitignore
└── CONTRIBUTING.md
/src/Directory.Build.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/tools/nuget.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WildGums/Orc.CommandLine/HEAD/tools/nuget.exe
--------------------------------------------------------------------------------
/design/Package/Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WildGums/Orc.CommandLine/HEAD/design/Package/Icon.png
--------------------------------------------------------------------------------
/src/Orc.CommandLine.Tests/ModuleInitializer.cs:
--------------------------------------------------------------------------------
1 | // Empty by design so it will never be overwritten by an update
--------------------------------------------------------------------------------
/GitVersion.yml:
--------------------------------------------------------------------------------
1 | mode: ContinuousDeployment
2 | assembly-versioning-scheme: MajorMinorPatch
3 | next-version: 5.0.0
4 |
--------------------------------------------------------------------------------
/src/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "10.0.0",
4 | "rollForward": "latestMinor",
5 | "allowPrerelease": false
6 | }
7 | }
--------------------------------------------------------------------------------
/src/Orc.CommandLine/Services/Interfaces/ICommandLineService.cs:
--------------------------------------------------------------------------------
1 | namespace Orc.CommandLine;
2 |
3 | public interface ICommandLineService
4 | {
5 | string GetCommandLine();
6 | }
7 |
--------------------------------------------------------------------------------
/src/Directory.Build.nullable.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | enable
4 |
5 |
--------------------------------------------------------------------------------
/cake.config:
--------------------------------------------------------------------------------
1 | ; The configuration file for Cake.
2 |
3 | [Settings]
4 | SkipVerification=true
5 |
6 | [Settings]
7 | EnableScriptCache=true
8 |
9 | [Paths]
10 | Cache=%temp%/cake-build/cache/
--------------------------------------------------------------------------------
/deployment/cake/codesigning-tasks.cake:
--------------------------------------------------------------------------------
1 | #l "codesigning-variables.cake"
2 |
3 | using System.Xml.Linq;
4 |
5 | //-------------------------------------------------------------
6 |
7 | // Empty by design for now
8 |
--------------------------------------------------------------------------------
/src/Directory.Build.implicitusings.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | enable
4 |
5 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine.Tests/Models/OptionDefinitionFacts.cs:
--------------------------------------------------------------------------------
1 | namespace Orc.CommandLine.Tests.Models;
2 |
3 | using NUnit.Framework;
4 |
5 | [TestFixture]
6 | public class OptionDefinitionFacts
7 | {
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/.config/dotnet-tools.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "isRoot": true,
4 | "tools": {
5 | "cake.tool": {
6 | "version": "6.0.0",
7 | "commands": [
8 | "dotnet-cake"
9 | ]
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/--thank-you.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "❤️Thank You"
3 | about: Just want to say thank you, this is the one to do it in
4 | title: Thank You
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | Leave Your Message Below (don't delete this line though)
--------------------------------------------------------------------------------
/src/Orc.CommandLine.Tests/FodyWeavers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine/Services/Interfaces/IOptionDefinitionService.cs:
--------------------------------------------------------------------------------
1 | namespace Orc.CommandLine;
2 |
3 | using System.Collections.Generic;
4 |
5 | public interface IOptionDefinitionService
6 | {
7 | IEnumerable GetOptionDefinitions(IContext targetContext);
8 | }
9 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine/Services/Interfaces/IHelpWriterService.cs:
--------------------------------------------------------------------------------
1 | namespace Orc.CommandLine;
2 |
3 | using System.Collections.Generic;
4 |
5 | public interface IHelpWriterService
6 | {
7 | IEnumerable GetAppHeader();
8 | IEnumerable GetHelp(IContext targetContext);
9 | }
10 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine/FodyWeavers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/GitReleaseManager.yaml:
--------------------------------------------------------------------------------
1 | issue-labels-include:
2 | - Breaking change
3 | - Feature
4 | - Bug
5 | - Improvement
6 | - Documentation
7 | - Dependencies
8 | issue-labels-exclude:
9 | - Build
10 | - Won't fix
11 | issue-labels-alias:
12 | - name: Documentation
13 | header: Documentation
14 | plural: Documentation
--------------------------------------------------------------------------------
/src/Orc.CommandLine/Context/Interfaces/IContext.cs:
--------------------------------------------------------------------------------
1 | namespace Orc.CommandLine;
2 |
3 | using System.Collections.Generic;
4 |
5 | public interface IContext
6 | {
7 | string OriginalCommandLine { get; set; }
8 |
9 | bool IsHelp { get; set; }
10 |
11 | Dictionary RawValues { get; }
12 |
13 | List QuoteSplitCharacters { get; }
14 |
15 | void Finish();
16 | }
17 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine/Exceptions/CommandLineException.cs:
--------------------------------------------------------------------------------
1 | namespace Orc.CommandLine;
2 |
3 | using System;
4 |
5 | public class CommandLineException : Exception
6 | {
7 | public CommandLineException(string message)
8 | : base(message)
9 | {
10 | }
11 |
12 | public CommandLineException(string message, Exception innerException)
13 | : base(message, innerException)
14 | {
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine.Tests/Context/BrandingCommandLineContext.cs:
--------------------------------------------------------------------------------
1 | namespace Orc.CommandLine.Tests.Context;
2 |
3 | public class BrandingCommandLineContext : ContextBase
4 | {
5 | [Option("ac", "appcolor", HelpText = "The accent color for the application")]
6 | public string AppColor { get; set; }
7 |
8 | [Option("an", "appname", HelpText = "The name for the application")]
9 | public string AppName { get; set; }
10 | }
11 |
--------------------------------------------------------------------------------
/AUTHORS:
--------------------------------------------------------------------------------
1 | # This is the official list of authors for copyright purposes.
2 | # This file is distinct from the CONTRIBUTORS file.
3 | # See the latter for an explanation.
4 |
5 | # Names should be added to this file as
6 | # Name or Organization
7 | # The email address is not required for organizations.
8 |
9 | # Please keep the list sorted.
10 | # Please notify the first person on the list to be added here.
11 |
12 | WildGums
13 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine.Tests/Context/TestContextWithFile.cs:
--------------------------------------------------------------------------------
1 | namespace Orc.CommandLine.Tests.Context;
2 |
3 | public class TestContextWithFile : TestContext
4 | {
5 | public TestContextWithFile()
6 | {
7 | FileName = string.Empty;
8 | }
9 |
10 | [Option("", "", DisplayName = "fileName", HelpText = "The file name to start with", TrimQuotes = true, TrimWhiteSpace = true)]
11 | public string FileName { get; set; }
12 | }
13 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine.Tests/Context/TestContextWithMandatoryOption.cs:
--------------------------------------------------------------------------------
1 | namespace Orc.CommandLine.Tests.Context;
2 |
3 | public class TestContextWithMandatoryOption : TestContext
4 | {
5 | public TestContextWithMandatoryOption()
6 | {
7 | RequiredStringSwitch = string.Empty;
8 | }
9 |
10 | [Option("r", "required", IsMandatory = true, HelpText = "Some required string switch")]
11 | public string RequiredStringSwitch { get; set; }
12 | }
13 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: WildGums-oss # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | custom: # Replace with a single custom sponsorship URL
--------------------------------------------------------------------------------
/CONTRIBUTORS:
--------------------------------------------------------------------------------
1 | # This is the official list of people who have contributed
2 | # to this repository.
3 | # The AUTHORS file lists the copyright holders; this file
4 | # lists people.
5 |
6 | # People submitting code should be listed in this file (by email address).
7 |
8 | # Names should be added to this file like so:
9 | # Name
10 |
11 | # Please keep the list sorted.
12 |
13 | Geert van Horrik
14 | Maksim Khomutov
15 |
--------------------------------------------------------------------------------
/src/Directory.Build.project.props:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 | wildgums
8 | https://github.com/WildGums/Orc.CommandLine
9 | MIT
10 | https://github.com/WildGums/Orc.CommandLine
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine/Parsers/Interfaces/ICommandLineParser.cs:
--------------------------------------------------------------------------------
1 | namespace Orc.CommandLine;
2 |
3 | using System.Collections.Generic;
4 | using Catel.Data;
5 |
6 | public interface ICommandLineParser
7 | {
8 | IValidationContext Parse(IContext targetContext);
9 | IValidationContext Parse(List commandLineArguments, IContext targetContext);
10 | IValidationContext Parse(IEnumerable commandLineArguments, IContext targetContext);
11 | IValidationContext Parse(string commandLine, IContext targetContext);
12 | }
13 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine/Services/CommandLineService.cs:
--------------------------------------------------------------------------------
1 | namespace Orc.CommandLine;
2 |
3 | using System;
4 | using System.Linq;
5 |
6 | public class CommandLineService : ICommandLineService
7 | {
8 | public virtual string GetCommandLine()
9 | {
10 | var commandArguments = Environment.GetCommandLineArgs().Skip(1)
11 | .Select(x => x.Contains(' ') ? $"\'{x}\'" : x)
12 | .ToArray();
13 |
14 | var commandLine = string.Join(" ", commandArguments);
15 |
16 | return commandLine;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | registries:
3 | nuget-feed-default:
4 | type: nuget-feed
5 | url: https://api.nuget.org/v3/index.json
6 |
7 | updates:
8 | - package-ecosystem: github-actions
9 | directory: "/"
10 | schedule:
11 | interval: weekly
12 |
13 | - package-ecosystem: nuget
14 | directories:
15 | - "/src"
16 | schedule:
17 | interval: daily
18 | open-pull-requests-limit: 10
19 | ignore:
20 | - dependency-name: "*Analyzers"
21 | versions:
22 | - ">= 0"
23 | registries:
24 | - nuget-feed-default
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Orc.CommandLine
2 | ===============
3 |
4 | !!! This repository is now archived, use an alternative like System.CommandLine instead !!!
5 |
6 | Name|Badge
7 | ---|---
8 | Downloads|
9 | Stable version|
10 | Unstable version|
11 |
12 | Use command line the easy way.
13 |
14 | For documentation, please visit the [documentation portal](http://opensource.wildgums.com)
15 |
--------------------------------------------------------------------------------
/src/SolutionAssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by Cake.
4 | //
5 | //------------------------------------------------------------------------------
6 | using System.Reflection;
7 |
8 | [assembly: AssemblyCompany("WildGums")]
9 | [assembly: AssemblyVersion("5.0.0")]
10 | [assembly: AssemblyFileVersion("5.0.0")]
11 | [assembly: AssemblyInformationalVersion("5.0.0-alpha.1")]
12 | [assembly: AssemblyCopyright("Copyright © WildGums 2010 - 2018")]
13 |
14 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/---support-request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "\U0001F62C Support Request"
3 | about: Having Trouble - ONLY contributors to other OSS projects OR people who are
4 | funding this project can submit these! If you aren't one of these, expect the ban
5 | hammer to fall
6 | title: ''
7 | labels: ''
8 | assignees: ''
9 |
10 | ---
11 |
12 | ONLY active OSS contributors OR people who buy us a coffee can ask questions here. If you don't do either of these things - DO NOT FILE HERE :)
13 |
14 | Give as much details as humanly possible if you want any sort of answer!
15 |
16 | Enter Question Below (don't delete this line)
--------------------------------------------------------------------------------
/src/Orc.CommandLine.Tests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // All other assembly info is defined in SharedAssembly.cs
5 |
6 | [assembly: AssemblyTitle("Orc.CommandLine.Test")]
7 | [assembly: AssemblyProduct("Orc.CommandLine.Test")]
8 | [assembly: AssemblyDescription("Orc.CommandLine.Test library")]
9 |
10 | // Setting ComVisible to false makes the types in this assembly not visible
11 | // to COM components. If you need to access a type in this assembly from
12 | // COM, set the ComVisible attribute to true on that type.
13 |
14 | [assembly: ComVisible(false)]
15 |
--------------------------------------------------------------------------------
/src/GlobalSuppressions.cs:
--------------------------------------------------------------------------------
1 |
2 | // This file is used by Code Analysis to maintain SuppressMessage
3 | // attributes that are applied to this project.
4 | // Project-level suppressions either have no target or are given
5 | // a specific target and scoped to a namespace, type, member, etc.
6 |
7 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("WpfAnalyzers.DependencyProperties", "WPF1010:Property '[property]' must notify when value changes.", Justification = "Don't enforce this")]
8 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("WpfAnalyzers.DependencyProperties", "WPF1011:Implement INotifyPropertyChanged.", Justification = "Don't enforce this")]
9 |
10 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.InteropServices;
4 |
5 | // All other assembly info is defined in SharedAssembly.cs
6 |
7 | [assembly: AssemblyTitle("Orc.CommandLine")]
8 | [assembly: AssemblyProduct("Orc.CommandLine")]
9 | [assembly: AssemblyDescription("Orc.CommandLine library")]
10 | [assembly: NeutralResourcesLanguage("en-US")]
11 |
12 | // Setting ComVisible to false makes the types in this assembly not visible
13 | // to COM components. If you need to access a type in this assembly from
14 | // COM, set the ComVisible attribute to true on that type.
15 |
16 | [assembly: ComVisible(false)]
17 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine/Context/ContextBase.cs:
--------------------------------------------------------------------------------
1 | namespace Orc.CommandLine;
2 |
3 | using System;
4 | using System.Collections.Generic;
5 |
6 | public abstract class ContextBase : IContext
7 | {
8 | protected ContextBase()
9 | {
10 | OriginalCommandLine = string.Empty;
11 | RawValues = new Dictionary(StringComparer.OrdinalIgnoreCase);
12 | QuoteSplitCharacters = new List(new [] { '\"', '\'' });
13 | }
14 |
15 | public string OriginalCommandLine { get; set; }
16 | public bool IsHelp { get; set; }
17 | public Dictionary RawValues { get; }
18 | public List QuoteSplitCharacters { get; }
19 |
20 | public virtual void Finish()
21 | {
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/--bug.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "\U0001F99FBug"
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: "s/unverified, t/bug \U0001F47E"
6 | assignees: ''
7 |
8 | ---
9 |
10 | # IF YOU DON'T ANSWER THIS TEMPLATE - THE BOT WILL AUTOMATICALLY CLOSE YOUR ISSUE!
11 |
12 | ## Please check all of the platforms you are having the issue on (if platform is not listed, it is not supported)
13 |
14 | - [ ] WPF
15 | - [ ] Blazor WASM
16 | - [ ] .NET Core
17 |
18 | ## Component
19 |
20 | What component is this issue occurring in?
21 |
22 | ## Version of Library
23 |
24 |
25 | ## Version of OS(s) listed above with issue
26 |
27 |
28 | ## Steps to Reproduce
29 | 1.
30 | 2.
31 | 3.
32 |
33 | ## Expected Behavior
34 |
35 |
36 | ## Actual Behavior
--------------------------------------------------------------------------------
/.github/stale.yml:
--------------------------------------------------------------------------------
1 | # Number of days of inactivity before an issue becomes stale
2 | daysUntilStale: 60
3 | # Number of days of inactivity before a stale issue is closed
4 | daysUntilClose: 7
5 | # Issues with these labels will never be considered stale
6 | exemptLabels:
7 | - pinned
8 | - security
9 | - planned
10 | - nostale
11 | # Label to use when marking an issue as stale
12 | staleLabel: wontfix
13 | # Comment to post when marking an issue as stale. Set to `false` to disable
14 | markComment: >
15 | This issue has been automatically marked as stale because it has not had
16 | recent activity. It will be closed if no further activity occurs. Thank you
17 | for your contributions.
18 | # Comment to post when closing a stale issue. Set to `false` to disable
19 | closeComment: false
--------------------------------------------------------------------------------
/src/Orc.CommandLine.Tests/Context/TestContext.cs:
--------------------------------------------------------------------------------
1 | namespace Orc.CommandLine.Tests.Context;
2 |
3 | public class TestContext : ContextBase
4 | {
5 | public TestContext()
6 | {
7 | StringSwitch = string.Empty;
8 | }
9 |
10 | [Option("bs", "bool", AcceptsValue = false, HelpText = "Some boolean switch")]
11 | public bool BooleanSwitch { get; set; }
12 |
13 | [Option("i", "int", HelpText = "Some integer switch")]
14 | public int IntegerSwitch { get; set; }
15 |
16 | [Option("s", "string", HelpText = "Some string switch")]
17 | public string StringSwitch { get; set; }
18 |
19 | [Option("x", "trimquotes", TrimQuotes = true)]
20 | public string TrimQuotes { get; set; }
21 |
22 | [Option("y", "donttrimquotes", TrimQuotes = false)]
23 | public string DontTrimQuotes { get; set; }
24 | }
25 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/--feature-request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "\U0001F354Feature Request"
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: "s/unverified, t/enhancement \U0001F423"
6 | assignees: ''
7 |
8 | ---
9 |
10 | # IF YOU DON'T ANSWER THIS TEMPLATE - THE BOT WILL AUTOMATICALLY CLOSE YOUR ISSUE!
11 |
12 | ## Summary
13 | Please provide a brief summary of your proposal. Two to three sentences is best here.
14 |
15 | ## API Changes
16 | Include a list of all API changes, additions, subtractions as would be required by your proposal. These APIs should be considered placeholders, so the naming is not as important as getting the concepts correct. If possible you should include some "example" code of usage of your new API.
17 |
18 | ## Intended Use Case
19 | Provide a detailed example of where your proposal would be used and for what purpose.
--------------------------------------------------------------------------------
/.github/support.yml:
--------------------------------------------------------------------------------
1 | # Configuration for Support Requests - https://github.com/dessant/support-requests
2 |
3 | # Label used to mark issues as support requests
4 | supportLabel: support
5 |
6 | # Comment to post on issues marked as support requests, `{issue-author}` is an
7 | # optional placeholder. Set to `false` to disable
8 | supportComment: >
9 | :wave: @{issue-author}, we use the issue tracker exclusively for bug reports
10 | and feature requests. However, this issue appears to be a support request.
11 | Please use our support channels to get help with the project.
12 |
13 | # Close issues marked as support requests
14 | close: true
15 |
16 | # Lock issues marked as support requests
17 | lock: false
18 |
19 | # Assign `off-topic` as the reason for locking. Set to `false` to disable
20 | setLockReason: true
21 |
22 | # Repository to extend settings from
23 | # _extends: repo
--------------------------------------------------------------------------------
/src/nuget.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine.Tests/PublicApiFacts.cs:
--------------------------------------------------------------------------------
1 | namespace Orc.CommandLine.Tests;
2 |
3 | using System.Reflection;
4 | using System.Runtime.CompilerServices;
5 | using System.Threading.Tasks;
6 | using NUnit.Framework;
7 | using PublicApiGenerator;
8 | using VerifyNUnit;
9 |
10 | [TestFixture]
11 | public class PublicApiFacts
12 | {
13 | [Test, MethodImpl(MethodImplOptions.NoInlining)]
14 | public async Task Orc_CommandLine_HasNoBreakingChanges_Async()
15 | {
16 | var assembly = typeof(CommandLineParser).Assembly;
17 |
18 | await PublicApiApprover.ApprovePublicApiAsync(assembly);
19 | }
20 |
21 | internal static class PublicApiApprover
22 | {
23 | public static async Task ApprovePublicApiAsync(Assembly assembly)
24 | {
25 | var publicApi = ApiGenerator.GeneratePublicApi(assembly, new ApiGeneratorOptions());
26 | await Verifier.Verify(publicApi);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine/Attributes/OptionAttribute.cs:
--------------------------------------------------------------------------------
1 | namespace Orc.CommandLine;
2 |
3 | using System;
4 |
5 | [AttributeUsage(AttributeTargets.Property)]
6 | public class OptionAttribute : Attribute
7 | {
8 | public OptionAttribute(string shortName, string longName)
9 | {
10 | ShortName = shortName;
11 | LongName = longName;
12 | DisplayName = string.Empty;
13 | HelpText = string.Empty;
14 | AcceptsValue = true;
15 | TrimQuotes = true;
16 | TrimWhiteSpace = false;
17 | IsMandatory = false;
18 | }
19 |
20 | public string ShortName { get; }
21 |
22 | public string LongName { get; }
23 |
24 | public string DisplayName { get; set; }
25 |
26 | public string HelpText { get; set; }
27 |
28 | public bool AcceptsValue { get; set; }
29 |
30 | public bool TrimQuotes { get; set; }
31 |
32 | public bool TrimWhiteSpace { get; set; }
33 |
34 | public bool IsMandatory { get; set; }
35 | }
36 |
--------------------------------------------------------------------------------
/.github/workflows/build-and-test.yml:
--------------------------------------------------------------------------------
1 | name: Build and test
2 |
3 | on:
4 | push:
5 | branches:
6 | - develop
7 | - master
8 | pull_request:
9 |
10 | #permissions:
11 | #pull-requests: write
12 | #contents: write
13 |
14 | jobs:
15 | build-and-test:
16 | runs-on: windows-latest # Required for some (WPF) projects
17 |
18 | steps:
19 | - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
20 | id: checkout
21 | with:
22 | fetch-depth: 0
23 |
24 | - name: Setup .NET Core
25 | id: setup-dotnet
26 | uses: actions/setup-dotnet@d4c94342e560b34958eacfc5d055d21461ed1c5d # v5.0.0
27 | with:
28 | dotnet-version: '10.0.x'
29 |
30 | - name: Cake Action
31 | id: cake-action
32 | uses: cake-build/cake-action@d218f1133bb74a1df0b08c89cfd8fc100c09e1a0 #v3.0.1
33 | with:
34 | target: BuildAndTest
35 | arguments: |
36 | IsCiBuild: true
--------------------------------------------------------------------------------
/src/Orc.CommandLine/ModuleInitializer.cs:
--------------------------------------------------------------------------------
1 | using Catel.IoC;
2 | using Catel.Services;
3 | using Orc.CommandLine;
4 |
5 | ///
6 | /// Used by the ModuleInit. All code inside the Initialize method is ran as soon as the assembly is loaded.
7 | ///
8 | public static class ModuleInitializer
9 | {
10 | ///
11 | /// Initializes the module.
12 | ///
13 | public static void Initialize()
14 | {
15 | var serviceLocator = ServiceLocator.Default;
16 |
17 | serviceLocator.RegisterType();
18 | serviceLocator.RegisterType();
19 | serviceLocator.RegisterType();
20 | serviceLocator.RegisterType();
21 |
22 | var languageService = serviceLocator.ResolveRequiredType();
23 | languageService.RegisterLanguageSource(new LanguageResourceSource("Orc.CommandLine", "Orc.CommandLine.Properties", "Resources"));
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine/Models/OptionDefinition.cs:
--------------------------------------------------------------------------------
1 | namespace Orc.CommandLine;
2 |
3 | public class OptionDefinition
4 | {
5 | public OptionDefinition()
6 | {
7 | ShortName = string.Empty;
8 | LongName = string.Empty;
9 | DisplayName = string.Empty;
10 | HelpText = string.Empty;
11 | PropertyNameOnContext = string.Empty;
12 | AcceptsValue = true;
13 | TrimQuotes = true;
14 | TrimWhiteSpace = false;
15 | }
16 |
17 | public string ShortName { get; set; }
18 |
19 | public string LongName { get; set; }
20 |
21 | public string DisplayName { get; set; }
22 |
23 | public string HelpText { get; set; }
24 |
25 | public string PropertyNameOnContext { get; set; }
26 |
27 | public bool IsMandatory { get; set; }
28 |
29 | public bool AcceptsValue { get; set; }
30 |
31 | public bool TrimQuotes { get; set; }
32 |
33 | public bool TrimWhiteSpace { get; set; }
34 |
35 | public override string ToString()
36 | {
37 | var text = this.GetSwitchDisplay();
38 | return text;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine/Parsers/Extensions/ICommandLineParserExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Orc.CommandLine;
2 |
3 | using System;
4 | using System.Collections.Generic;
5 | using Catel.IoC;
6 |
7 | public static class ICommandLineParserExtensions
8 | {
9 | public static IEnumerable GetAppHeader(this ICommandLineParser commandLineParser)
10 | {
11 | ArgumentNullException.ThrowIfNull(commandLineParser);
12 |
13 | var dependencyResolver = commandLineParser.GetDependencyResolver();
14 |
15 | var helpWriterService = dependencyResolver.ResolveRequired();
16 | return helpWriterService.GetAppHeader();
17 | }
18 |
19 | public static IEnumerable GetHelp(this ICommandLineParser commandLineParser, IContext targetContext)
20 | {
21 | ArgumentNullException.ThrowIfNull(commandLineParser);
22 |
23 | var dependencyResolver = commandLineParser.GetDependencyResolver();
24 |
25 | var helpWriterService = dependencyResolver.ResolveRequired();
26 | return helpWriterService.GetHelp(targetContext);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/MethodTimeLogger.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using Catel.Logging;
3 | using System;
4 | using System.Globalization;
5 |
6 | ///
7 | /// Note: do not rename this class or put it inside a namespace.
8 | ///
9 | internal static class MethodTimeLogger
10 | {
11 | public static void Log(MethodBase methodBase, long milliseconds, string message)
12 | {
13 | Log(methodBase.DeclaringType ?? typeof(object), methodBase.Name, milliseconds, message);
14 | }
15 |
16 | public static void Log(Type type, string methodName, long milliseconds, string message)
17 | {
18 | if (type is null)
19 | {
20 | return;
21 | }
22 |
23 | if (milliseconds == 0)
24 | {
25 | // Don't log superfast methods
26 | return;
27 | }
28 |
29 | var finalMessage = $"[METHODTIMER] {type.Name}.{methodName} took '{milliseconds.ToString(CultureInfo.InvariantCulture)}' ms";
30 |
31 | if (!string.IsNullOrWhiteSpace(message))
32 | {
33 | finalMessage += $" | {message}";
34 | }
35 |
36 | var logger = LogManager.GetLogger(type);
37 | logger.Debug(finalMessage);
38 | }
39 | }
--------------------------------------------------------------------------------
/src/Directory.Build.shared.tests.props:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 | false
10 | true
11 | true
12 |
13 |
14 |
15 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ### Description of Change ###
2 |
3 |
4 |
5 | ### Issues Resolved ###
6 |
7 |
8 |
9 | - fixes #
10 |
11 | ### API Changes ###
12 |
13 |
14 |
15 | None
16 |
17 | ### Behavioral Changes ###
18 |
19 |
20 |
21 | None
22 |
23 | ### Testing Procedure ###
24 |
25 |
26 |
27 | ### PR Checklist ###
28 |
29 | - [ ] I have included examples or tests
30 | - [ ] I have updated the change log or created a GitHub ticket with the change
31 | - [ ] I am listed in the CONTRIBUTORS file (if it exists)
32 | - [ ] Changes adhere to coding standard
33 | - [ ] I checked the licenses of Third Party software and discussed new dependencies with at least 1 other team member
--------------------------------------------------------------------------------
/.github/lock.yml:
--------------------------------------------------------------------------------
1 | # Configuration for Lock Threads - https://github.com/dessant/lock-threads
2 |
3 | # Number of days of inactivity before a closed issue or pull request is locked
4 | daysUntilLock: 4
5 |
6 | # Skip issues and pull requests created before a given timestamp. Timestamp must
7 | # follow ISO 8601 (`YYYY-MM-DD`). Set to `false` to disable
8 | skipCreatedBefore: false
9 |
10 | # Issues and pull requests with these labels will be ignored. Set to `[]` to disable
11 | exemptLabels: ["pinned", "planned"]
12 |
13 | # Label to add before locking, such as `outdated`. Set to `false` to disable
14 | lockLabel: false
15 |
16 | # Comment to post before locking. Set to `false` to disable
17 | lockComment: >
18 | This thread has been automatically locked since there has not been
19 | any recent activity after it was closed. Please open a new issue for
20 | related bugs.
21 |
22 | # Assign `resolved` as the reason for locking. Set to `false` to disable
23 | setLockReason: true
24 |
25 | # Limit to only `issues` or `pulls`
26 | # only: issues
27 |
28 | # Optionally, specify configuration settings just for `issues` or `pulls`
29 | # issues:
30 | # exemptLabels:
31 | # - help-wanted
32 | # lockLabel: outdated
33 |
34 | # pulls:
35 | # daysUntilLock: 30
36 |
37 | # Repository to extend settings from
38 | # _extends: repo
--------------------------------------------------------------------------------
/deployment/cake/templates-variables.cake:
--------------------------------------------------------------------------------
1 | #l "buildserver.cake"
2 |
3 | //-------------------------------------------------------------
4 |
5 | public class TemplatesContext : BuildContextWithItemsBase
6 | {
7 | public TemplatesContext(IBuildContext parentBuildContext)
8 | : base(parentBuildContext)
9 | {
10 | }
11 |
12 | protected override void ValidateContext()
13 | {
14 |
15 | }
16 |
17 | protected override void LogStateInfoForContext()
18 | {
19 | CakeContext.Information($"Found '{Items.Count}' template items");
20 | }
21 | }
22 |
23 | //-------------------------------------------------------------
24 |
25 | private TemplatesContext InitializeTemplatesContext(BuildContext buildContext, IBuildContext parentBuildContext)
26 | {
27 | var data = new TemplatesContext(parentBuildContext)
28 | {
29 | Items = Templates ?? new List(),
30 | };
31 |
32 | return data;
33 | }
34 |
35 | //-------------------------------------------------------------
36 |
37 | List _templates;
38 |
39 | public List Templates
40 | {
41 | get
42 | {
43 | if (_templates is null)
44 | {
45 | _templates = new List();
46 | }
47 |
48 | return _templates;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/deployment/cake/issuetrackers.cake:
--------------------------------------------------------------------------------
1 | // Customize this file when using a different issue tracker
2 | #l "issuetrackers-github.cake"
3 | #l "issuetrackers-jira.cake"
4 |
5 | //-------------------------------------------------------------
6 |
7 | public interface IIssueTracker
8 | {
9 | Task CreateAndReleaseVersionAsync();
10 | }
11 |
12 | //-------------------------------------------------------------
13 |
14 | public class IssueTrackerIntegration : IntegrationBase
15 | {
16 | private readonly List _issueTrackers = new List();
17 |
18 | public IssueTrackerIntegration(BuildContext buildContext)
19 | : base(buildContext)
20 | {
21 | _issueTrackers.Add(new GitHubIssueTracker(buildContext));
22 | _issueTrackers.Add(new JiraIssueTracker(buildContext));
23 | }
24 |
25 | public async Task CreateAndReleaseVersionAsync()
26 | {
27 | BuildContext.CakeContext.LogSeparator("Creating and releasing version");
28 |
29 | foreach (var issueTracker in _issueTrackers)
30 | {
31 | try
32 | {
33 | await issueTracker.CreateAndReleaseVersionAsync();
34 | }
35 | catch (Exception ex)
36 | {
37 | BuildContext.CakeContext.Error(ex.Message);
38 | }
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/deployment/cake/codesigning-variables.cake:
--------------------------------------------------------------------------------
1 | #l "buildserver.cake"
2 |
3 | //-------------------------------------------------------------
4 |
5 | public class CodeSigningContext : BuildContextBase
6 | {
7 | public CodeSigningContext(IBuildContext parentBuildContext)
8 | : base(parentBuildContext)
9 | {
10 | }
11 |
12 | public List ProjectsToSignImmediately { get; set; }
13 |
14 | protected override void ValidateContext()
15 | {
16 |
17 | }
18 |
19 | protected override void LogStateInfoForContext()
20 | {
21 | //CakeContext.Information($"Found '{Items.Count}' component projects");
22 | }
23 | }
24 |
25 | //-------------------------------------------------------------
26 |
27 | private CodeSigningContext InitializeCodeSigningContext(BuildContext buildContext, IBuildContext parentBuildContext)
28 | {
29 | var data = new CodeSigningContext(parentBuildContext)
30 | {
31 | ProjectsToSignImmediately = CodeSignImmediately,
32 | };
33 |
34 | return data;
35 | }
36 |
37 | //-------------------------------------------------------------
38 |
39 | List _codeSignImmediately;
40 |
41 | public List CodeSignImmediately
42 | {
43 | get
44 | {
45 | if (_codeSignImmediately is null)
46 | {
47 | _codeSignImmediately = new List();
48 | }
49 |
50 | return _codeSignImmediately;
51 | }
52 | }
--------------------------------------------------------------------------------
/src/Orc.CommandLine/Services/OptionDefinitionService.cs:
--------------------------------------------------------------------------------
1 | namespace Orc.CommandLine;
2 |
3 | using System;
4 | using System.Collections.Generic;
5 | using Catel.Reflection;
6 |
7 | public class OptionDefinitionService : IOptionDefinitionService
8 | {
9 | public IEnumerable GetOptionDefinitions(IContext targetContext)
10 | {
11 | ArgumentNullException.ThrowIfNull(targetContext);
12 |
13 | var optionDefinitions = new List();
14 |
15 | var properties = targetContext.GetType().GetPropertiesEx();
16 | foreach (var propertyInfo in properties)
17 | {
18 | if (propertyInfo.TryGetAttribute(out var optionAttribute))
19 | {
20 | optionDefinitions.Add(new OptionDefinition
21 | {
22 | ShortName = optionAttribute.ShortName,
23 | LongName = optionAttribute.LongName,
24 | DisplayName = optionAttribute.DisplayName,
25 | HelpText = optionAttribute.HelpText,
26 | AcceptsValue = optionAttribute.AcceptsValue,
27 | TrimQuotes = optionAttribute.TrimQuotes,
28 | TrimWhiteSpace = optionAttribute.TrimWhiteSpace,
29 | IsMandatory = optionAttribute.IsMandatory,
30 | PropertyNameOnContext = propertyInfo.Name
31 | });
32 | }
33 | }
34 |
35 | return optionDefinitions;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine.Tests/Extensions/StringExtensionsFacts.cs:
--------------------------------------------------------------------------------
1 | namespace Orc.CommandLine.Tests;
2 |
3 | using NUnit.Framework;
4 |
5 | [TestFixture]
6 | public class StringExtensionsFacts
7 | {
8 | [TestCase("", "")]
9 | [TestCase("a", "a")]
10 | [TestCase("ab", "ab")]
11 | [TestCase("-a", "a")]
12 | [TestCase("-ab", "ab")]
13 | [TestCase("/a", "a")]
14 | [TestCase("/ab", "ab")]
15 | [TestCase("//ab", "/ab")]
16 | public void TheTrimSwitchPrefixMethod(string input, string expectedValue)
17 | {
18 | Assert.That(input.TrimSwitchPrefix(), Is.EqualTo(expectedValue));
19 | }
20 |
21 | [TestCase("", false)]
22 | [TestCase("a", false)]
23 | [TestCase("ab", false)]
24 | [TestCase("-a", true)]
25 | [TestCase("-ab", true)]
26 | [TestCase("/a", true)]
27 | [TestCase("/ab", true)]
28 | public void TheIsSwitch1Method(string input, bool expectedValue)
29 | {
30 | Assert.That(input.IsSwitch(new[] { '\"', '\'' }), Is.EqualTo(expectedValue));
31 | }
32 |
33 | [TestCase("", "-a", false)]
34 | [TestCase("a", "-aa", false)]
35 | [TestCase("aa", "-a", false)]
36 | [TestCase("a", "-a", true)]
37 | [TestCase("abc", "-abc", true)]
38 | [TestCase("", "/a", false)]
39 | [TestCase("a", "/aa", false)]
40 | [TestCase("aa", "/a", false)]
41 | [TestCase("a", "/a", true)]
42 | [TestCase("abc", "/abc", true)]
43 | public void TheIsSwitch2Method(string input, string switchValue, bool expectedValue)
44 | {
45 | Assert.That(input.IsSwitch(switchValue, new [] { '\"', '\'' }), Is.EqualTo(expectedValue));
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/deployment/cake/tools-variables.cake:
--------------------------------------------------------------------------------
1 | #l "buildserver.cake"
2 |
3 | //-------------------------------------------------------------
4 |
5 | public class ToolsContext : BuildContextWithItemsBase
6 | {
7 | public ToolsContext(IBuildContext parentBuildContext)
8 | : base(parentBuildContext)
9 | {
10 | }
11 |
12 | public string NuGetRepositoryUrls { get; set; }
13 | public string NuGetRepositoryApiKeys { get; set; }
14 |
15 | protected override void ValidateContext()
16 | {
17 |
18 | }
19 |
20 | protected override void LogStateInfoForContext()
21 | {
22 | CakeContext.Information($"Found '{Items.Count}' tool projects");
23 | }
24 | }
25 |
26 | //-------------------------------------------------------------
27 |
28 | private ToolsContext InitializeToolsContext(BuildContext buildContext, IBuildContext parentBuildContext)
29 | {
30 | var data = new ToolsContext(parentBuildContext)
31 | {
32 | Items = Tools ?? new List(),
33 | NuGetRepositoryUrls = buildContext.BuildServer.GetVariable("ToolsNuGetRepositoryUrls", showValue: true),
34 | NuGetRepositoryApiKeys = buildContext.BuildServer.GetVariable("ToolsNuGetRepositoryApiKeys", showValue: false)
35 | };
36 |
37 | return data;
38 | }
39 |
40 | //-------------------------------------------------------------
41 |
42 | List _tools;
43 |
44 | public List Tools
45 | {
46 | get
47 | {
48 | if (_tools is null)
49 | {
50 | _tools = new List();
51 | }
52 |
53 | return _tools;
54 | }
55 | }
--------------------------------------------------------------------------------
/deployment/cake/vsextensions-variables.cake:
--------------------------------------------------------------------------------
1 | #l "buildserver.cake"
2 |
3 | public class VsExtensionsContext : BuildContextWithItemsBase
4 | {
5 | public VsExtensionsContext(IBuildContext parentBuildContext)
6 | : base(parentBuildContext)
7 | {
8 | }
9 |
10 | public string PublisherName { get; set; }
11 | public string PersonalAccessToken { get; set; }
12 |
13 | protected override void ValidateContext()
14 | {
15 |
16 | }
17 |
18 | protected override void LogStateInfoForContext()
19 | {
20 | CakeContext.Information($"Found '{Items.Count}' vs extension projects");
21 | }
22 | }
23 |
24 | //-------------------------------------------------------------
25 |
26 | private VsExtensionsContext InitializeVsExtensionsContext(BuildContext buildContext, IBuildContext parentBuildContext)
27 | {
28 | var data = new VsExtensionsContext(parentBuildContext)
29 | {
30 | Items = VsExtensions ?? new List(),
31 | PublisherName = buildContext.BuildServer.GetVariable("VsExtensionsPublisherName", showValue: true),
32 | PersonalAccessToken = buildContext.BuildServer.GetVariable("VsExtensionsPersonalAccessToken", showValue: false),
33 | };
34 |
35 | return data;
36 | }
37 |
38 | //-------------------------------------------------------------
39 |
40 | List _vsExtensions;
41 |
42 | public List VsExtensions
43 | {
44 | get
45 | {
46 | if (_vsExtensions is null)
47 | {
48 | _vsExtensions = new List();
49 | }
50 |
51 | return _vsExtensions;
52 | }
53 | }
--------------------------------------------------------------------------------
/deployment/cake/tests-nunit.cake:
--------------------------------------------------------------------------------
1 | #tool "nuget:?package=NUnit.ConsoleRunner&version=3.20.2"
2 |
3 | //-------------------------------------------------------------
4 |
5 | private static void RunTestsUsingNUnit(BuildContext buildContext, string projectName, string testTargetFramework, string testResultsDirectory)
6 | {
7 | var testFile = System.IO.Path.Combine(GetProjectOutputDirectory(buildContext, projectName),
8 | testTargetFramework, $"{projectName}.dll");
9 | var resultsFile = System.IO.Path.Combine(testResultsDirectory, "testresults.xml");
10 |
11 | var nunitSettings = new NUnit3Settings
12 | {
13 | Results = new NUnit3Result[]
14 | {
15 | new NUnit3Result
16 | {
17 | FileName = resultsFile,
18 | Format = "nunit3"
19 | }
20 | },
21 | NoHeader = true,
22 | NoColor = true,
23 | NoResults = false,
24 | X86 = string.Equals(buildContext.Tests.ProcessBit, "X86", StringComparison.OrdinalIgnoreCase),
25 | Timeout = 60 * 1000, // 60 seconds
26 | Workers = 1
27 | //Work = testResultsDirectory
28 | };
29 |
30 | // Note: although the docs say you can use without array initialization, you can't
31 | buildContext.CakeContext.NUnit3(new string[] { testFile }, nunitSettings);
32 |
33 | buildContext.CakeContext.Information("Verifying whether results file '{0}' exists", resultsFile);
34 |
35 | if (!buildContext.CakeContext.FileExists(resultsFile))
36 | {
37 | throw new Exception(string.Format("Expected results file '{0}' does not exist", resultsFile));
38 | }
39 | }
--------------------------------------------------------------------------------
/deployment/cake/components-variables.cake:
--------------------------------------------------------------------------------
1 | #l "buildserver.cake"
2 |
3 | //-------------------------------------------------------------
4 |
5 | public class ComponentsContext : BuildContextWithItemsBase
6 | {
7 | public ComponentsContext(IBuildContext parentBuildContext)
8 | : base(parentBuildContext)
9 | {
10 | }
11 |
12 | public string NuGetRepositoryUrl { get; set; }
13 | public string NuGetRepositoryApiKey { get; set; }
14 |
15 | protected override void ValidateContext()
16 | {
17 |
18 | }
19 |
20 | protected override void LogStateInfoForContext()
21 | {
22 | CakeContext.Information($"Found '{Items.Count}' component projects");
23 | }
24 | }
25 |
26 | //-------------------------------------------------------------
27 |
28 | private ComponentsContext InitializeComponentsContext(BuildContext buildContext, IBuildContext parentBuildContext)
29 | {
30 | var data = new ComponentsContext(parentBuildContext)
31 | {
32 | Items = Components ?? new List(),
33 | NuGetRepositoryUrl = buildContext.BuildServer.GetVariable("NuGetRepositoryUrl", showValue: true),
34 | NuGetRepositoryApiKey = buildContext.BuildServer.GetVariable("NuGetRepositoryApiKey", showValue: false)
35 | };
36 |
37 | return data;
38 | }
39 |
40 | //-------------------------------------------------------------
41 |
42 | List _components;
43 |
44 | public List Components
45 | {
46 | get
47 | {
48 | if (_components is null)
49 | {
50 | _components = new List();
51 | }
52 |
53 | return _components;
54 | }
55 | }
--------------------------------------------------------------------------------
/deployment/cake/lib-logging.cake:
--------------------------------------------------------------------------------
1 | // Note: code originally comes from https://stackoverflow.com/questions/50826394/how-to-print-tool-command-line-in-cake
2 |
3 | ///
4 | /// Temporary sets logging verbosity.
5 | ///
6 | ///
7 | ///
8 | /// // Temporary sets logging verbosity to Diagnostic.
9 | /// using(context.UseVerbosity(Verbosity.Diagnostic))
10 | /// {
11 | /// context.DotNetBuild(project, settings);
12 | /// }
13 | ///
14 | ///
15 | public static VerbosityChanger UseVerbosity(this ICakeContext context, Verbosity newVerbosity) =>
16 | new VerbosityChanger(context.Log, newVerbosity);
17 |
18 |
19 | ///
20 | /// Temporary sets logging verbosity to Diagnostic.
21 | ///
22 | ///
23 | ///
24 | /// // Temporary sets logging verbosity to Diagnostic.
25 | /// using(context.UseDiagnosticVerbosity())
26 | /// {
27 | /// context.DotNetBuild(project, settings);
28 | /// }
29 | ///
30 | ///
31 | public static VerbosityChanger UseDiagnosticVerbosity(this ICakeContext context) =>
32 | context.UseVerbosity(Verbosity.Diagnostic);
33 |
34 | ///
35 | /// Cake log verbosity changer.
36 | /// Restores old verbosity on Dispose.
37 | ///
38 | public class VerbosityChanger : IDisposable
39 | {
40 | ICakeLog _log;
41 | Verbosity _oldVerbosity;
42 |
43 | public VerbosityChanger(ICakeLog log, Verbosity newVerbosity)
44 | {
45 | _log = log;
46 | _oldVerbosity = log.Verbosity;
47 | _log.Verbosity = newVerbosity;
48 | }
49 |
50 | public void Dispose() => _log.Verbosity = _oldVerbosity;
51 | }
--------------------------------------------------------------------------------
/src/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
9 |
11 |
13 |
14 |
15 |
16 |
18 |
20 |
22 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014-2016 WildGums
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 | ==============================================================================
24 |
25 | Additional licenses / components
26 | --------------------------------
27 |
28 | Some parts are based on other open-source components. Each component that is based
29 | on another component has a reference to the original component including the original
30 | license the code was delivered upon. Below is a list of other components / licenses.
31 |
32 | Note: if you feel an item is missing in this list, please let us know!
33 |
34 | * Catel
35 | http://github.com/catel/catel
36 | Original license: MIT
37 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine/Orc.CommandLine.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net8.0;net9.0
4 | Orc.CommandLine
5 | Orc.CommandLine
6 | en-US
7 | Orc.CommandLine
8 | 1.0.0-alpha0001
9 | Orc.CommandLine library.
10 | orc;command;line;parameters
11 |
12 |
13 |
14 |
15 | 52E01A33-3A3F-4D04-83AC-100EACD9541E
16 |
17 |
18 |
19 |
20 |
21 |
22 | runtime; build; native; contentfiles; analyzers
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine/Properties/Resources.de.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | text/microsoft-resx
5 |
6 |
7 | 2.0
8 |
9 |
10 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
11 |
12 |
13 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
14 |
15 |
16 | Cannot parse '{0}' because an exception occured: {1}
17 |
18 |
19 | Cannot parse '{0}' since there is no empty switch on the context
20 |
21 |
22 | Cannot parse '{0}' because it is not a switch and it is not the first argument
23 |
24 |
25 | Cannot parse '{0}' because the switch is not recognized
26 |
27 |
28 | Cannot parse '{0}' because the actual value is not found (command line is too short)
29 |
30 |
31 | [no switch]
32 |
33 |
34 | Required switch '{0}' is not specified
35 |
36 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine/Properties/Resources.es.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | text/microsoft-resx
5 |
6 |
7 | 2.0
8 |
9 |
10 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
11 |
12 |
13 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
14 |
15 |
16 | Cannot parse '{0}' because an exception occured: {1}
17 |
18 |
19 | Cannot parse '{0}' since there is no empty switch on the context
20 |
21 |
22 | Cannot parse '{0}' because it is not a switch and it is not the first argument
23 |
24 |
25 | Cannot parse '{0}' because the switch is not recognized
26 |
27 |
28 | Cannot parse '{0}' because the actual value is not found (command line is too short)
29 |
30 |
31 | [no switch]
32 |
33 |
34 | Required switch '{0}' is not specified
35 |
36 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine/Properties/Resources.fr.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | text/microsoft-resx
5 |
6 |
7 | 2.0
8 |
9 |
10 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
11 |
12 |
13 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
14 |
15 |
16 | Cannot parse '{0}' because an exception occured: {1}
17 |
18 |
19 | Cannot parse '{0}' since there is no empty switch on the context
20 |
21 |
22 | Cannot parse '{0}' because it is not a switch and it is not the first argument
23 |
24 |
25 | Cannot parse '{0}' because the switch is not recognized
26 |
27 |
28 | Cannot parse '{0}' because the actual value is not found (command line is too short)
29 |
30 |
31 | [no switch]
32 |
33 |
34 | Required switch '{0}' is not specified
35 |
36 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine/Properties/Resources.nl.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | text/microsoft-resx
5 |
6 |
7 | 2.0
8 |
9 |
10 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
11 |
12 |
13 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
14 |
15 |
16 | Cannot parse '{0}' because an exception occured: {1}
17 |
18 |
19 | Cannot parse '{0}' since there is no empty switch on the context
20 |
21 |
22 | Cannot parse '{0}' because it is not a switch and it is not the first argument
23 |
24 |
25 | Cannot parse '{0}' because the switch is not recognized
26 |
27 |
28 | Cannot parse '{0}' because the actual value is not found (command line is too short)
29 |
30 |
31 | [no switch]
32 |
33 |
34 | Required switch '{0}' is not specified
35 |
36 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine/Properties/Resources.ru.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | text/microsoft-resx
5 |
6 |
7 | 2.0
8 |
9 |
10 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
11 |
12 |
13 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
14 |
15 |
16 | Cannot parse '{0}' because an exception occured: {1}
17 |
18 |
19 | Cannot parse '{0}' since there is no empty switch on the context
20 |
21 |
22 | Cannot parse '{0}' because it is not a switch and it is not the first argument
23 |
24 |
25 | Cannot parse '{0}' because the switch is not recognized
26 |
27 |
28 | Cannot parse '{0}' because the actual value is not found (command line is too short)
29 |
30 |
31 | [no switch]
32 |
33 |
34 | Required switch '{0}' is not specified
35 |
36 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine.Tests/Orc.CommandLine.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net8.0
4 | Orc.CommandLine.Tests
5 | Orc.CommandLine.Tests
6 | en-US
7 | Orc.CommandLine.Tests
8 | 1.0.0-alpha0001
9 |
10 |
11 | true
12 | annotations
13 |
14 |
15 |
16 |
17 |
18 | runtime; build; native; contentfiles; analyzers
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/src/Directory.Build.shared.tools.props:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 | $(Description)
10 | $(PackageProjectUrl)
11 | IncludeDefaultProjectBuildOutputInPack
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | $([MSBuild]::MakeRelative('$(OutputPath)\$(TargetFrameworks)\', %(ToolDllFiles.FullPath)))
31 | tools
32 |
33 |
34 |
35 | $([MSBuild]::MakeRelative('$(OutputPath)\$(TargetFrameworks)\', %(ToolExeFiles.FullPath)))
36 | tools
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/deployment/cake/apps-uwp-variables.cake:
--------------------------------------------------------------------------------
1 | #l "./buildserver.cake"
2 |
3 | //-------------------------------------------------------------
4 |
5 | public class UwpContext : BuildContextWithItemsBase
6 | {
7 | public UwpContext(IBuildContext parentBuildContext)
8 | : base(parentBuildContext)
9 | {
10 | }
11 |
12 | public string WindowsStoreAppId { get; set; }
13 | public string WindowsStoreClientId { get; set; }
14 | public string WindowsStoreClientSecret { get; set; }
15 | public string WindowsStoreTenantId { get; set; }
16 |
17 | protected override void ValidateContext()
18 | {
19 | }
20 |
21 | protected override void LogStateInfoForContext()
22 | {
23 | CakeContext.Information($"Found '{Items.Count}' uwp projects");
24 | }
25 | }
26 |
27 | //-------------------------------------------------------------
28 |
29 | private UwpContext InitializeUwpContext(BuildContext buildContext, IBuildContext parentBuildContext)
30 | {
31 | var data = new UwpContext(parentBuildContext)
32 | {
33 | Items = UwpApps ?? new List(),
34 | WindowsStoreAppId = buildContext.BuildServer.GetVariable("WindowsStoreAppId", showValue: true),
35 | WindowsStoreClientId = buildContext.BuildServer.GetVariable("WindowsStoreClientId", showValue: false),
36 | WindowsStoreClientSecret = buildContext.BuildServer.GetVariable("WindowsStoreClientSecret", showValue: false),
37 | WindowsStoreTenantId = buildContext.BuildServer.GetVariable("WindowsStoreTenantId", showValue: false)
38 | };
39 |
40 | return data;
41 | }
42 |
43 | //-------------------------------------------------------------
44 |
45 | List _uwpApps;
46 |
47 | public List UwpApps
48 | {
49 | get
50 | {
51 | if (_uwpApps is null)
52 | {
53 | _uwpApps = new List();
54 | }
55 |
56 | return _uwpApps;
57 | }
58 | }
--------------------------------------------------------------------------------
/src/Orc.CommandLine.Tests/Models/Extensions/OptionDefinitionExtensionsFacts.cs:
--------------------------------------------------------------------------------
1 | namespace Orc.CommandLine.Tests.Models;
2 |
3 | using NUnit.Framework;
4 |
5 | [TestFixture]
6 | public class OptionDefinitionExtensionsFacts
7 | {
8 | [TestCase(" ", "", false)]
9 | [TestCase("b", "bool", true)]
10 | public void TheHasSwitchMethod(string shortName, string longName, bool expectedValue)
11 | {
12 | var optionDefinition = new OptionDefinition
13 | {
14 | ShortName = shortName,
15 | LongName = longName
16 | };
17 |
18 | Assert.That(optionDefinition.HasSwitch(), Is.EqualTo(expectedValue));
19 | }
20 |
21 | [TestCase("b", "bool", "-b", true)]
22 | [TestCase("b", "bool", "-bool", true)]
23 | [TestCase("b", "bool", "/b", true)]
24 | [TestCase("b", "bool", "/bool", true)]
25 | [TestCase("b", "bool", "b", false)]
26 | [TestCase("b", "bool", "bool", false)]
27 | public void TheIsSwitchMethod(string shortName, string longName, string actualSwitch, bool expectedValue)
28 | {
29 | var optionDefinition = new OptionDefinition
30 | {
31 | ShortName = shortName,
32 | LongName = longName
33 | };
34 |
35 | Assert.That(optionDefinition.IsSwitch(actualSwitch, new[] { '\"', '\'' }), Is.EqualTo(expectedValue));
36 | }
37 |
38 | [TestCase("", "", "", "[no switch]")]
39 | [TestCase("", "", "fileName", "fileName")]
40 | [TestCase("b", "bool", "", "b / bool")]
41 | public void TheGetSwitchDisplayMethod(string shortName, string longName, string displayName, string expectedString)
42 | {
43 | var optionDefinition = new OptionDefinition
44 | {
45 | ShortName = shortName,
46 | LongName = longName,
47 | DisplayName = displayName
48 | };
49 |
50 | var actual = optionDefinition.GetSwitchDisplay();
51 |
52 | Assert.That(actual, Is.EqualTo(expectedString));
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/Directory.Build.shared.mat.props:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 | 4.0
10 | en-US
11 | true
12 | true
13 | true
14 |
15 |
16 |
17 | <_ResxFiles Remove="Properties\*.resx" />
18 |
19 |
20 |
21 |
22 |
23 |
24 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/deployment/cake/notifications.cake:
--------------------------------------------------------------------------------
1 | #l "notifications-msteams.cake"
2 | //#l "notifications-slack.cake"
3 |
4 | //-------------------------------------------------------------
5 |
6 | public enum NotificationType
7 | {
8 | Info,
9 |
10 | Error
11 | }
12 |
13 | //-------------------------------------------------------------
14 |
15 | public interface INotifier
16 | {
17 | Task NotifyAsync(string project, string message, TargetType targetType = TargetType.Unknown, NotificationType notificationType = NotificationType.Info);
18 | }
19 |
20 | //-------------------------------------------------------------
21 |
22 | public class NotificationsIntegration : IntegrationBase
23 | {
24 | private readonly List _notifiers = new List();
25 |
26 | public NotificationsIntegration(BuildContext buildContext)
27 | : base(buildContext)
28 | {
29 | _notifiers.Add(new MsTeamsNotifier(buildContext));
30 | }
31 |
32 | public async Task NotifyDefaultAsync(string project, string message, TargetType targetType = TargetType.Unknown)
33 | {
34 | await NotifyAsync(project, message, targetType, NotificationType.Info);
35 | }
36 |
37 | //-------------------------------------------------------------
38 |
39 | public async Task NotifyErrorAsync(string project, string message, TargetType targetType = TargetType.Unknown)
40 | {
41 | await NotifyAsync(project, string.Format("ERROR: {0}", message), targetType, NotificationType.Error);
42 | }
43 |
44 | //-------------------------------------------------------------
45 |
46 | public async Task NotifyAsync(string project, string message, TargetType targetType = TargetType.Unknown, NotificationType notificationType = NotificationType.Info)
47 | {
48 | foreach (var notifier in _notifiers)
49 | {
50 | await notifier.NotifyAsync(project, message, targetType, notificationType);
51 | }
52 | }
53 | }
--------------------------------------------------------------------------------
/src/Orc.CommandLine/Services/HelpWriterService.cs:
--------------------------------------------------------------------------------
1 | namespace Orc.CommandLine;
2 |
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Text;
7 | using Catel.Reflection;
8 |
9 | public class HelpWriterService : IHelpWriterService
10 | {
11 | private readonly IOptionDefinitionService _optionDefinitionService;
12 |
13 | public HelpWriterService(IOptionDefinitionService optionDefinitionService)
14 | {
15 | ArgumentNullException.ThrowIfNull(optionDefinitionService);
16 |
17 | _optionDefinitionService = optionDefinitionService;
18 | }
19 |
20 | public IEnumerable GetAppHeader()
21 | {
22 | var assembly = AssemblyHelper.GetRequiredEntryAssembly();
23 |
24 | var lines = new List
25 | {
26 | $"{assembly.Title()} v{assembly.Version()}",
27 | "================",
28 | string.Empty
29 | };
30 |
31 | return lines;
32 | }
33 |
34 | public IEnumerable GetHelp(IContext targetContext)
35 | {
36 | var optionDefinitions = _optionDefinitionService.GetOptionDefinitions(targetContext).ToList();
37 | if (optionDefinitions.Count == 0)
38 | {
39 | return Array.Empty();
40 | }
41 |
42 | var lines = new List();
43 |
44 | var prefixLength = optionDefinitions.Select(x => x.ToString().Length).Max();
45 |
46 | foreach (var optionDefinition in optionDefinitions)
47 | {
48 | var prefix = optionDefinition.ToString();
49 |
50 | var stringBuilder = new StringBuilder();
51 | stringBuilder.Append(prefix);
52 |
53 | for (var i = prefix.Length; i < prefixLength; i++)
54 | {
55 | stringBuilder.Append(" ");
56 | }
57 |
58 | stringBuilder.Append($" {optionDefinition.HelpText}");
59 | lines.Add(stringBuilder.ToString());
60 | }
61 |
62 | return lines;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/deployment/cake/docker-variables.cake:
--------------------------------------------------------------------------------
1 | #l "buildserver.cake"
2 |
3 | //-------------------------------------------------------------
4 |
5 | public class DockerImagesContext : BuildContextWithItemsBase
6 | {
7 | public DockerImagesContext(IBuildContext parentBuildContext)
8 | : base(parentBuildContext)
9 | {
10 | }
11 |
12 | public string DockerEngineUrl { get; set; }
13 | public string DockerRegistryUrl { get; set; }
14 | public string DockerRegistryUserName { get; set; }
15 | public string DockerRegistryPassword { get; set; }
16 |
17 | protected override void ValidateContext()
18 | {
19 | }
20 |
21 | protected override void LogStateInfoForContext()
22 | {
23 | CakeContext.Information($"Found '{Items.Count}' docker image projects");
24 | }
25 | }
26 |
27 | //-------------------------------------------------------------
28 |
29 | private DockerImagesContext InitializeDockerImagesContext(BuildContext buildContext, IBuildContext parentBuildContext)
30 | {
31 | var data = new DockerImagesContext(parentBuildContext)
32 | {
33 | Items = DockerImages ?? new List(),
34 | DockerEngineUrl = buildContext.BuildServer.GetVariable("DockerEngineUrl", showValue: true),
35 | DockerRegistryUrl = buildContext.BuildServer.GetVariable("DockerRegistryUrl", showValue: true),
36 | DockerRegistryUserName = buildContext.BuildServer.GetVariable("DockerRegistryUserName", showValue: false),
37 | DockerRegistryPassword = buildContext.BuildServer.GetVariable("DockerRegistryPassword", showValue: false)
38 | };
39 |
40 | return data;
41 | }
42 |
43 | //-------------------------------------------------------------
44 |
45 | List _dockerImages;
46 |
47 | public List DockerImages
48 | {
49 | get
50 | {
51 | if (_dockerImages is null)
52 | {
53 | _dockerImages = new List();
54 | }
55 |
56 | return _dockerImages;
57 | }
58 | }
--------------------------------------------------------------------------------
/src/Orc.CommandLine/Extensions/StringExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Orc.CommandLine;
2 |
3 | using System.Linq;
4 |
5 | public static class StringExtensions
6 | {
7 | internal static readonly string[] AcceptedSwitchPrefixes = { "-", "/" };
8 |
9 | public static bool IsSwitch(this string value, char[] quoteSplitCharacters)
10 | {
11 | if (string.IsNullOrWhiteSpace(value))
12 | {
13 | return false;
14 | }
15 |
16 | value = value.Trim(quoteSplitCharacters);
17 |
18 | return AcceptedSwitchPrefixes.Any(acceptedSwitchPrefix => value.StartsWith(acceptedSwitchPrefix));
19 | }
20 |
21 | public static string TrimSwitchPrefix(this string value)
22 | {
23 | if (string.IsNullOrWhiteSpace(value))
24 | {
25 | return value;
26 | }
27 |
28 | foreach (var acceptedSwitchPrefix in AcceptedSwitchPrefixes)
29 | {
30 | if (value.StartsWith(acceptedSwitchPrefix))
31 | {
32 | value = value[acceptedSwitchPrefix.Length..];
33 |
34 | // Just trim 1
35 | break;
36 | }
37 | }
38 |
39 | return value;
40 | }
41 |
42 | public static bool IsSwitch(this string switchName, string value, char[] quoteSplitCharacters)
43 | {
44 | value = value.Trim(quoteSplitCharacters);
45 |
46 | foreach (var acceptedSwitchPrefix in AcceptedSwitchPrefixes)
47 | {
48 | if (value.StartsWith(acceptedSwitchPrefix))
49 | {
50 | value = value.Remove(0, acceptedSwitchPrefix.Length);
51 | }
52 | }
53 |
54 | return string.Equals(switchName, value);
55 | }
56 |
57 | public static bool IsHelp(this string singleArgument, char[] quoteSplitCharacters)
58 | {
59 | return IsSwitch("h", singleArgument, quoteSplitCharacters) ||
60 | IsSwitch("help", singleArgument, quoteSplitCharacters) ||
61 | IsSwitch("?", singleArgument, quoteSplitCharacters);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine/Models/Extensions/OptionDefinitionExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Orc.CommandLine;
2 |
3 | using System;
4 | using Catel.IoC;
5 | using Catel.Services;
6 |
7 | public static class OptionDefinitionExtensions
8 | {
9 | private static readonly ILanguageService LanguageService;
10 |
11 | static OptionDefinitionExtensions()
12 | {
13 | var serviceLocator = ServiceLocator.Default;
14 |
15 | LanguageService = serviceLocator.ResolveRequiredType();
16 | }
17 |
18 | public static bool HasSwitch(this OptionDefinition optionDefinition)
19 | {
20 | ArgumentNullException.ThrowIfNull(optionDefinition);
21 |
22 | return !string.IsNullOrWhiteSpace(optionDefinition.ShortName);
23 | }
24 |
25 | public static bool IsSwitch(this OptionDefinition optionDefinition, string actualSwitch, char[] quoteSplitCharacters)
26 | {
27 | ArgumentNullException.ThrowIfNull(optionDefinition);
28 |
29 | if (!actualSwitch.IsSwitch(quoteSplitCharacters))
30 | {
31 | return false;
32 | }
33 |
34 | return optionDefinition.ShortName.IsSwitch(actualSwitch, quoteSplitCharacters)
35 | || optionDefinition.LongName.IsSwitch(actualSwitch, quoteSplitCharacters);
36 | }
37 |
38 | public static string GetSwitchDisplay(this OptionDefinition optionDefinition)
39 | {
40 | ArgumentNullException.ThrowIfNull(optionDefinition);
41 |
42 | var text = optionDefinition.DisplayName;
43 | if (!string.IsNullOrWhiteSpace(text))
44 | {
45 | return text;
46 | }
47 |
48 | var shortName = optionDefinition.ShortName.Trim();
49 | var longName = optionDefinition.LongName.Trim();
50 |
51 | var areEqual = string.Equals(shortName, longName);
52 | if (areEqual && string.IsNullOrWhiteSpace(longName))
53 | {
54 | text = LanguageService.GetRequiredString("CommandLine_NoSwitch");
55 | }
56 | else
57 | {
58 | text = $"{optionDefinition.ShortName} / {optionDefinition.LongName}";
59 | }
60 |
61 | return text;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine.Tests/Parsers/CommandLineParserFacts.issues.cs:
--------------------------------------------------------------------------------
1 | namespace Orc.CommandLine.Tests;
2 |
3 | using NUnit.Framework;
4 |
5 | public partial class CommandLineParserFacts
6 | {
7 | private class SingleQuotesContext : ContextBase
8 | {
9 | [Option("", "project", DisplayName = "project", HelpText = "", TrimQuotes = true, TrimWhiteSpace = true)]
10 | public string Project { get; set; }
11 |
12 | [Option("", "extension", DisplayName = "extension", HelpText = "", TrimQuotes = true, TrimWhiteSpace = true)]
13 | public string Extension { get; set; }
14 | }
15 |
16 | [TestCase("-something 'some argument' -appcolor \"#FF483FFC\" -appname \"New name\" -extension 'MyProjects.Plugins.MyPlugin' -project 'D:\\Data\\Testing\\My Project Path'", @"D:\Data\Testing\My Project Path", "MyProjects.Plugins.MyPlugin")]
17 | [TestCase(@"-project 'D:\Data\Testing\My Project Path' -extension 'MyProjects.Plugins.MyPlugin'", @"D:\Data\Testing\My Project Path", "MyProjects.Plugins.MyPlugin")]
18 | public void SupportsSingleQuotes(string input, string expectedProject, string expectedExtension)
19 | {
20 | var commandLineParser = CreateCommandLineParser();
21 |
22 | var context = new SingleQuotesContext();
23 | var validationContext = commandLineParser.Parse(input, context);
24 |
25 | Assert.That(validationContext.HasErrors, Is.False);
26 |
27 | Assert.That(context.Project, Is.EqualTo(expectedProject));
28 | Assert.That(context.Extension, Is.EqualTo(expectedExtension));
29 | }
30 |
31 | [TestCase(@"-project 'D:\Data\Testing\My Project Path!@#$%' -extension 'MyProjects.Plugins.MyPlugin'", @"D:\Data\Testing\My Project Path!@#$%", "MyProjects.Plugins.MyPlugin")]
32 | public void SupportsSpecialCharacters(string input, string expectedProject, string expectedExtension)
33 | {
34 | var commandLineParser = CreateCommandLineParser();
35 |
36 | var context = new SingleQuotesContext();
37 | var validationContext = commandLineParser.Parse(input, context);
38 |
39 | Assert.That(validationContext.HasErrors, Is.False);
40 |
41 | Assert.That(context.Project, Is.EqualTo(expectedProject));
42 | Assert.That(context.Extension, Is.EqualTo(expectedExtension));
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/deployment/cake/tests-variables.cake:
--------------------------------------------------------------------------------
1 | #l "buildserver.cake"
2 |
3 | //-------------------------------------------------------------
4 |
5 | public class TestsContext : BuildContextWithItemsBase
6 | {
7 | public TestsContext(IBuildContext parentBuildContext)
8 | : base(parentBuildContext)
9 | {
10 | }
11 |
12 | public string Framework { get; set; }
13 | public string TargetFramework { get; set; }
14 | public string OperatingSystem { get; set; }
15 | public string ProcessBit { get; set; }
16 |
17 | protected override void ValidateContext()
18 | {
19 | if (Items.Count == 0)
20 | {
21 | return;
22 | }
23 |
24 | if (string.IsNullOrWhiteSpace(Framework))
25 | {
26 | throw new Exception("Framework is required, specify via 'TestFramework'");
27 | }
28 |
29 | if (string.IsNullOrWhiteSpace(ProcessBit))
30 | {
31 | throw new Exception("ProcessBit is required, specify via 'TestProcessBit'");
32 | }
33 | }
34 |
35 | protected override void LogStateInfoForContext()
36 | {
37 | CakeContext.Information($"Found '{Items.Count}' test projects");
38 | }
39 | }
40 |
41 | //-------------------------------------------------------------
42 |
43 | private TestsContext InitializeTestsContext(BuildContext buildContext, IBuildContext parentBuildContext)
44 | {
45 | var data = new TestsContext(parentBuildContext)
46 | {
47 | Items = TestProjects,
48 |
49 | Framework = buildContext.BuildServer.GetVariable("TestFramework", "nunit", showValue: true),
50 | TargetFramework = buildContext.BuildServer.GetVariable("TestTargetFramework", "", showValue: true),
51 | OperatingSystem = buildContext.BuildServer.GetVariable("TestOperatingSystem", "win", showValue: true),
52 | ProcessBit = buildContext.BuildServer.GetVariable("TestProcessBit", "X64", showValue: true)
53 | };
54 |
55 | return data;
56 | }
57 |
58 | //-------------------------------------------------------------
59 |
60 | List _testProjects;
61 |
62 | public List TestProjects
63 | {
64 | get
65 | {
66 | if (_testProjects is null)
67 | {
68 | _testProjects = new List();
69 | }
70 |
71 | return _testProjects;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/Directory.Build.analyzers.props:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 | all
9 | runtime; build; native; contentfiles; analyzers; buildtransitive
10 |
11 |
12 | all
13 | runtime; build; native; contentfiles; analyzers; buildtransitive
14 |
15 |
16 | all
17 | runtime; build; native; contentfiles; analyzers; buildtransitive
18 |
19 |
20 | all
21 | runtime; build; native; contentfiles; analyzers; buildtransitive
22 |
23 |
24 | all
25 | runtime; build; native; contentfiles; analyzers; buildtransitive
26 |
27 |
28 |
29 |
30 |
32 | latest
33 |
34 |
35 |
46 |
47 | $(NoWarn);CA1030;CA1031;CA1054;CA1062;CA1724;CA1810;CA2007;CA2237
48 | $(NoError);CA1030;CA1031;CA1054;CA1062;CA1724;CA810;CA2007;CA2237
49 |
50 |
--------------------------------------------------------------------------------
/deployment/cake/issuetrackers-jira.cake:
--------------------------------------------------------------------------------
1 | #tool "nuget:?package=JiraCli&version=1.3.0-alpha0338&prerelease"
2 |
3 | //-------------------------------------------------------------
4 |
5 | public class JiraIssueTracker : IIssueTracker
6 | {
7 | public JiraIssueTracker(BuildContext buildContext)
8 | {
9 | BuildContext = buildContext;
10 |
11 | Url = buildContext.BuildServer.GetVariable("JiraUrl", showValue: true);
12 | Username = buildContext.BuildServer.GetVariable("JiraUsername", showValue: true);
13 | Password = buildContext.BuildServer.GetVariable("JiraPassword", showValue: false);
14 | ProjectName = buildContext.BuildServer.GetVariable("JiraProjectName", showValue: true);
15 |
16 | if (!string.IsNullOrWhiteSpace(Url) &&
17 | !string.IsNullOrWhiteSpace(ProjectName))
18 | {
19 | IsAvailable = true;
20 | }
21 | }
22 |
23 | public BuildContext BuildContext { get; private set; }
24 |
25 | public string Url { get; set; }
26 | public string Username { get; set; }
27 | public string Password { get; set; }
28 | public string ProjectName { get; set; }
29 | public bool IsAvailable { get; private set; }
30 |
31 | public async Task CreateAndReleaseVersionAsync()
32 | {
33 | if (!IsAvailable)
34 | {
35 | BuildContext.CakeContext.Information("JIRA is not available, skipping JIRA integration");
36 | return;
37 | }
38 |
39 | var version = BuildContext.General.Version.FullSemVer;
40 |
41 | BuildContext.CakeContext.Information("Releasing version '{0}' in JIRA", version);
42 |
43 | // Example call:
44 | // JiraCli.exe -url %JiraUrl% -user %JiraUsername% -pw %JiraPassword% -action createandreleaseversion
45 | // -project %JiraProjectName% -version %GitVersion_FullSemVer% -merge %IsOfficialBuild%
46 |
47 | var nugetPath = BuildContext.CakeContext.Tools.Resolve("JiraCli.exe");
48 | BuildContext.CakeContext.StartProcess(nugetPath, new ProcessSettings
49 | {
50 | Arguments = new ProcessArgumentBuilder()
51 | .AppendSwitch("-url", Url)
52 | .AppendSwitch("-user", Username)
53 | .AppendSwitchSecret("-pw", Password)
54 | .AppendSwitch("-action", "createandreleaseversion")
55 | .AppendSwitch("-project", ProjectName)
56 | .AppendSwitch("-version", version)
57 | .AppendSwitch("-merge", BuildContext.General.IsOfficialBuild.ToString())
58 | });
59 |
60 | BuildContext.CakeContext.Information("Released version in JIRA");
61 | }
62 | }
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/src/.vsconfig:
--------------------------------------------------------------------------------
1 | {
2 | "version": "1.0",
3 | "components": [
4 | "Microsoft.VisualStudio.Component.CoreEditor",
5 | "Microsoft.VisualStudio.Workload.CoreEditor",
6 | "Microsoft.Net.Component.4.8.SDK",
7 | "Microsoft.Net.Component.4.7.2.TargetingPack",
8 | "Microsoft.Net.ComponentGroup.DevelopmentPrerequisites",
9 | "Microsoft.VisualStudio.Component.TypeScript.TSServer",
10 | "Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions",
11 | "Microsoft.VisualStudio.Component.JavaScript.TypeScript",
12 | "Microsoft.VisualStudio.Component.JavaScript.Diagnostics",
13 | "Microsoft.VisualStudio.Component.Roslyn.Compiler",
14 | "Microsoft.Component.MSBuild",
15 | "Microsoft.VisualStudio.Component.Roslyn.LanguageServices",
16 | "Microsoft.VisualStudio.Component.TextTemplating",
17 | "Component.Microsoft.VisualStudio.RazorExtension",
18 | "Microsoft.VisualStudio.Component.IISExpress",
19 | "Microsoft.VisualStudio.Component.NuGet",
20 | "Microsoft.VisualStudio.Component.MSODBC.SQL",
21 | "Microsoft.VisualStudio.Component.SQL.LocalDB.Runtime",
22 | "Microsoft.VisualStudio.Component.Common.Azure.Tools",
23 | "Microsoft.VisualStudio.Component.SQL.CLR",
24 | "Microsoft.VisualStudio.Component.MSSQL.CMDLnUtils",
25 | "Microsoft.VisualStudio.Component.ManagedDesktop.Core",
26 | "Microsoft.VisualStudio.Component.SQL.SSDT",
27 | "Microsoft.VisualStudio.Component.SQL.DataSources",
28 | "Component.Microsoft.Web.LibraryManager",
29 | "Component.Microsoft.WebTools.BrowserLink.WebLivePreview",
30 | "Microsoft.VisualStudio.ComponentGroup.Web",
31 | "Microsoft.NetCore.Component.Runtime.8.0",
32 | "Microsoft.NetCore.Component.SDK",
33 | "Microsoft.VisualStudio.Component.FSharp",
34 | "Microsoft.NetCore.Component.DevelopmentTools",
35 | "Microsoft.VisualStudio.Component.FSharp.WebTemplates",
36 | "Microsoft.VisualStudio.Component.DockerTools",
37 | "Microsoft.NetCore.Component.Web",
38 | "Microsoft.VisualStudio.Component.WebDeploy",
39 | "Microsoft.VisualStudio.Component.AppInsights.Tools",
40 | "Microsoft.VisualStudio.Component.Web",
41 | "Microsoft.VisualStudio.Component.AspNet45",
42 | "Microsoft.VisualStudio.Component.AspNet",
43 | "Component.Microsoft.VisualStudio.Web.AzureFunctions",
44 | "Microsoft.VisualStudio.ComponentGroup.AzureFunctions",
45 | "Microsoft.VisualStudio.ComponentGroup.Web.CloudTools",
46 | "Microsoft.VisualStudio.Component.DiagnosticTools",
47 | "Microsoft.VisualStudio.Component.Debugger.JustInTime",
48 | "Microsoft.VisualStudio.Component.WslDebugging",
49 | "Microsoft.VisualStudio.Workload.NetWeb",
50 | "Microsoft.VisualStudio.Component.ManagedDesktop.Prerequisites",
51 | "Microsoft.VisualStudio.Workload.ManagedDesktop"
52 | ],
53 | "extensions": []
54 | }
--------------------------------------------------------------------------------
/deployment/cake/sourcecontrol-github.cake:
--------------------------------------------------------------------------------
1 | #addin "nuget:?package=Cake.GitHub&version=1.0.0"
2 | #addin "nuget:?package=Octokit&version=14.0.0"
3 |
4 | //-------------------------------------------------------------
5 |
6 | public class GitHubSourceControl : ISourceControl
7 | {
8 | public GitHubSourceControl(BuildContext buildContext)
9 | {
10 | BuildContext = buildContext;
11 |
12 | ApiKey = buildContext.BuildServer.GetVariable("GitHubApiKey", buildContext.General.Repository.Password, showValue: false);
13 | OwnerName = buildContext.BuildServer.GetVariable("GitHubOwnerName", buildContext.General.Copyright.Company, showValue: true);
14 | ProjectName = buildContext.BuildServer.GetVariable("GitHubProjectName", buildContext.General.Solution.Name, showValue: true);
15 |
16 | if (!string.IsNullOrWhiteSpace(ApiKey) &&
17 | !string.IsNullOrWhiteSpace(OwnerName) &&
18 | !string.IsNullOrWhiteSpace(ProjectName))
19 | {
20 | IsAvailable = true;
21 | }
22 | }
23 |
24 | public BuildContext BuildContext { get; private set; }
25 |
26 | public string ApiKey { get; set; }
27 | public string OwnerName { get; set; }
28 | public string ProjectName { get; set; }
29 |
30 | public string OwnerAndProjectName
31 | {
32 | get { return $"{OwnerName}/{ProjectName}"; }
33 | }
34 |
35 | public bool IsAvailable { get; private set; }
36 |
37 | public async Task MarkBuildAsPendingAsync(string context, string description)
38 | {
39 | UpdateStatus(GitHubStatusState.Pending, context, description);
40 | }
41 |
42 | public async Task MarkBuildAsFailedAsync(string context, string description)
43 | {
44 | UpdateStatus(GitHubStatusState.Failure, context, description);
45 | }
46 |
47 | public async Task MarkBuildAsSucceededAsync(string context, string description)
48 | {
49 | UpdateStatus(GitHubStatusState.Success, context, description);
50 | }
51 |
52 | private void UpdateStatus(GitHubStatusState state, string context, string description)
53 | {
54 | // Disabled for now
55 | return;
56 |
57 | if (!IsAvailable)
58 | {
59 | return;
60 | }
61 |
62 | BuildContext.CakeContext.Information("Updating GitHub status to '{0}' | '{1}'", state, description);
63 |
64 | var commitSha = BuildContext.General.Repository.CommitId;
65 |
66 | // Note: UserName is not really required, use string.Empty, then only api key is needed
67 | BuildContext.CakeContext.GitHubStatus(string.Empty, ApiKey, OwnerName, ProjectName, commitSha, new GitHubStatusSettings
68 | {
69 | State = state,
70 | TargetUrl = null,// "url-to-build-server",
71 | Description = description,
72 | Context = $"Cake - {context}"
73 | });
74 | }
75 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 |
9 | .nuget/
10 | tools/FAKE/
11 | build-log.xml
12 | Nuget.key
13 | TestResult.xml
14 |
15 | # Build results
16 | [Bb]in/
17 | [Cc]lientbin/
18 | [Dd]ebug/
19 | [Rr]elease/
20 | [Oo]utput*/
21 | [Pp]ackages*/
22 | [Tt]emp/
23 | bin
24 | obj
25 | [Ll]ib/*
26 | ![Ll]ib/repositories.config
27 | *.ide/
28 | *_i.c
29 | *_p.c
30 | *.ilk
31 | *.meta
32 | *.obj
33 | *.orig
34 | *.pch
35 | *.pdb
36 | *.pgc
37 | *.pgd
38 | *.rsp
39 | *.sbr
40 | *.tlb
41 | *.tli
42 | *.tlh
43 | *.tmp
44 | *.vspscc
45 | *.xap
46 | .builds
47 | *.log
48 |
49 | # Visual C++ cache files
50 | ipch/
51 | *.aps
52 | *.ncb
53 | *.opensdf
54 | *.sdf
55 |
56 | # Visual Studio profiler
57 | *.psess
58 | *.vsp
59 |
60 | # ReSharper is a .NET coding add-in
61 | _ReSharper*
62 | *.resharper.user
63 |
64 | # Catel
65 | CatelLogging.txt
66 |
67 | # Dotcover
68 | *.dotCover
69 | *.dotsettings.user
70 |
71 | # Finalbuilder
72 | *.fbl7
73 | *.fb7lck
74 | *.fbpInf
75 |
76 | # Ghostdoc
77 | *.GhostDoc.xml
78 |
79 | # Deployments
80 | deployment/FinalBuilder/backup
81 | deployment/InnoSetup/template/templates
82 | deployment/InnoSetup/template/snippets
83 | deployment/InnoSetup/template/libraries
84 | deployment/InnoSetup/template/doc
85 |
86 | # Installshield output folder
87 | [Ee]xpress
88 |
89 | # DocProject is a documentation generator add-in
90 | DocProject/buildhelp/
91 | DocProject/Help/*.HxT
92 | DocProject/Help/*.HxC
93 | DocProject/Help/*.hhc
94 | DocProject/Help/*.hhk
95 | DocProject/Help/*.hhp
96 | DocProject/Help/Html2
97 | DocProject/Help/html
98 |
99 | # Click-Once directory
100 | publish
101 |
102 | # Others
103 | [Bb]in
104 | [Oo]bj
105 | sql
106 | TestResults
107 | *.Cache
108 | ClientBin
109 | stylecop.*
110 | ~$*
111 | *.dbmdl
112 | Generated_Code #added for RIA/Silverlight projects
113 |
114 | # Backup & report files from converting an old project file to a newer
115 | # Visual Studio version. Backup files are not needed, because we have git ;-)
116 | _UpgradeReport_Files/
117 | Backup*/
118 | UpgradeLog*.XML
119 |
120 | # Windows image file caches
121 | Thumbs.db
122 |
123 | # Folder config file
124 | Desktop.ini
125 |
126 | # Cake - Uncomment if you are using it
127 | tools/**
128 | !tools/packages.config
129 | build.cakeoverrides
130 |
131 | # mstest test results
132 | TestResults
133 | .vs/
134 | .sonarqube/
135 | BundleArtifacts/
136 |
137 | # docker / tye
138 | .tye
139 |
140 | # editors
141 | .idea
142 | .vscode
143 |
144 | # Binaries
145 | *.dll
146 | *.exe
147 |
148 | # fody
149 | FodyWeavers.xsd
150 |
151 | # Approval tests
152 | *.received.*
153 |
154 | # ANTLR
155 | data/dsl/*.class
156 | data/dsl/*.java
157 |
158 | # Nodejs / NPM
159 | node_modules
160 | package-lock.json
161 |
162 | # Azure / .NET Aspire
163 | .azure
164 | infra/
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | Thanks you for your interest in contributing - Please see our our [Code of Conduct](CODE_OF_CONDUCT.md).
4 |
5 |
6 | ### Bug Fixes
7 |
8 | If you're looking for something to fix, please browse the open issues.
9 |
10 | Follow the style used by the [.NET Foundation](https://github.com/dotnet/corefx/blob/master/Documentation/coding-guidelines/coding-style.md), with a few exceptions:
11 |
12 | - Apply readonly on class level private variables that are assigned in the constructor
13 | - 4 SPACES - tabs do not exist :)
14 |
15 | Read and follow our [Pull Request template](PULL_REQUEST_TEMPLATE.md) if you are submitting fixes.
16 |
17 | ### Feature Requests
18 |
19 | To propose a change or new feature, please make use the feature request area in issues.
20 |
21 | #### Non-Starter Topics
22 | The following topics should generally not be proposed for discussion as they are non-starters:
23 |
24 | * Large renames of APIs
25 | * Large non-backward-compatible breaking changes
26 | * Avoid clutter posts like "+1" which do not serve to further the conversation
27 |
28 | #### Proposal States
29 | ##### Open
30 | Open proposals are still under discussion. Please leave your concrete, constructive feedback on this proposal. +1s and other clutter posts which do not add to the discussion will be removed.
31 |
32 | ##### Accepted
33 | Accepted proposals are proposals that both the community and core team agree should be a part of projects. These proposals are ready for implementation. These proposals are available for anyone to work on unless it is already assigned to someone.
34 |
35 | If you wish to start working on an accepted proposal, please reply to the thread so we can mark you as the implementor and change the title to In Progress. This helps to avoid multiple people working on the same thing. If you decide to work on this proposal publicly, feel free to post a link to the branch as well for folks to follow along.
36 |
37 | ###### What "Accepted" does mean
38 | * Any community member is welcome to work on the idea.
39 | * The maintainers _may_ consider working on this idea on their own, but has not done so until it is marked "In Progress" with a team member assigned as the implementor.
40 | * Any pull request implementing the proposal will be welcomed with an API and code review.
41 |
42 | ###### What "Accepted" does not mean
43 | * The proposal will ever be implemented, either by a community member or maintainers.
44 | * The maintainers are committing to implementing a proposal, even if nobody else does.
45 |
46 | ##### In Progress
47 | Once a developer has begun work on a proposal, either from the team or a community member, the proposal is marked as in progress with the implementors name and (possibly) a link to a development branch to follow along with progress.
48 |
49 | #### Rejected
50 | Rejected proposals will not be implemented or merged into the code base. Once a proposal is rejected, the thread will be closed and the conversation is considered completed, pending considerable new information or changes..
--------------------------------------------------------------------------------
/deployment/cake/github-pages-variables.cake:
--------------------------------------------------------------------------------
1 | #l "buildserver.cake"
2 |
3 | //-------------------------------------------------------------
4 |
5 | public class GitHubPagesContext : BuildContextWithItemsBase
6 | {
7 | public GitHubPagesContext(IBuildContext parentBuildContext)
8 | : base(parentBuildContext)
9 | {
10 | }
11 |
12 | public string RepositoryUrl { get; set; }
13 | public string BranchName { get; set; }
14 | public string Email { get; set; }
15 | public string UserName { get; set; }
16 | public string ApiToken { get; set; }
17 |
18 | protected override void ValidateContext()
19 | {
20 | if (Items.Count == 0)
21 | {
22 | return;
23 | }
24 |
25 | if (string.IsNullOrWhiteSpace(RepositoryUrl))
26 | {
27 | throw new Exception("GitHubPagesRepositoryUrl must be defined");
28 | }
29 |
30 | if (string.IsNullOrWhiteSpace(BranchName))
31 | {
32 | throw new Exception("GitHubPagesBranchName must be defined");
33 | }
34 |
35 | if (string.IsNullOrWhiteSpace(Email))
36 | {
37 | throw new Exception("GitHubPagesEmail must be defined");
38 | }
39 |
40 | if (string.IsNullOrWhiteSpace(UserName))
41 | {
42 | throw new Exception("GitHubPagesUserName must be defined");
43 | }
44 |
45 | if (string.IsNullOrWhiteSpace(ApiToken))
46 | {
47 | throw new Exception("GitHubPagesApiToken must be defined");
48 | }
49 | }
50 |
51 | protected override void LogStateInfoForContext()
52 | {
53 | CakeContext.Information($"Found '{Items.Count}' GitHub pages projects");
54 | }
55 | }
56 |
57 | //-------------------------------------------------------------
58 |
59 | private GitHubPagesContext InitializeGitHubPagesContext(BuildContext buildContext, IBuildContext parentBuildContext)
60 | {
61 | var data = new GitHubPagesContext(parentBuildContext)
62 | {
63 | Items = GitHubPages ?? new List(),
64 | RepositoryUrl = buildContext.BuildServer.GetVariable("GitHubPagesRepositoryUrl", ((BuildContext)parentBuildContext).General.Repository.Url, showValue: true),
65 | BranchName = buildContext.BuildServer.GetVariable("GitHubPagesRepositoryUrl", "gh-pages", showValue: true),
66 | Email = buildContext.BuildServer.GetVariable("GitHubPagesEmail", showValue: true),
67 | UserName = buildContext.BuildServer.GetVariable("GitHubPagesUserName", showValue: true),
68 | ApiToken = buildContext.BuildServer.GetVariable("GitHubPagesApiToken", showValue: false),
69 | };
70 |
71 | return data;
72 | }
73 |
74 | //-------------------------------------------------------------
75 |
76 | List _gitHubPages;
77 |
78 | public List GitHubPages
79 | {
80 | get
81 | {
82 | if (_gitHubPages is null)
83 | {
84 | _gitHubPages = new List();
85 | }
86 |
87 | return _gitHubPages;
88 | }
89 | }
--------------------------------------------------------------------------------
/deployment/cake/sourcecontrol.cake:
--------------------------------------------------------------------------------
1 | // Customize this file when using a different source controls
2 | #l "sourcecontrol-github.cake"
3 |
4 | //-------------------------------------------------------------
5 |
6 | public interface ISourceControl
7 | {
8 | Task MarkBuildAsPendingAsync(string context, string description);
9 | Task MarkBuildAsFailedAsync(string context, string description);
10 | Task MarkBuildAsSucceededAsync(string context, string description);
11 | }
12 |
13 | //-------------------------------------------------------------
14 |
15 | public class SourceControlIntegration : IntegrationBase
16 | {
17 | private readonly List _sourceControls = new List();
18 |
19 | public SourceControlIntegration(BuildContext buildContext)
20 | : base(buildContext)
21 | {
22 | _sourceControls.Add(new GitHubSourceControl(buildContext));
23 | }
24 |
25 | public async Task MarkBuildAsPendingAsync(string context, string description = null)
26 | {
27 | BuildContext.CakeContext.LogSeparator($"Marking build as pending: '{description ?? string.Empty}'");
28 |
29 | context = context ?? "default";
30 | description = description ?? "Build pending";
31 |
32 | foreach (var sourceControl in _sourceControls)
33 | {
34 | try
35 | {
36 | await sourceControl.MarkBuildAsPendingAsync(context, description);
37 | }
38 | catch (Exception ex)
39 | {
40 | BuildContext.CakeContext.Warning($"Failed to update status: {ex.Message}");
41 | }
42 | }
43 | }
44 |
45 | public async Task MarkBuildAsFailedAsync(string context, string description = null)
46 | {
47 | BuildContext.CakeContext.LogSeparator($"Marking build as failed: '{description ?? string.Empty}'");
48 |
49 | context = context ?? "default";
50 | description = description ?? "Build failed";
51 |
52 | foreach (var sourceControl in _sourceControls)
53 | {
54 | try
55 | {
56 | await sourceControl.MarkBuildAsFailedAsync(context, description);
57 | }
58 | catch (Exception ex)
59 | {
60 | BuildContext.CakeContext.Warning($"Failed to update status: {ex.Message}");
61 | }
62 | }
63 | }
64 |
65 | public async Task MarkBuildAsSucceededAsync(string context, string description = null)
66 | {
67 | BuildContext.CakeContext.LogSeparator($"Marking build as succeeded: '{description ?? string.Empty}'");
68 |
69 | context = context ?? "default";
70 | description = description ?? "Build succeeded";
71 |
72 | foreach (var sourceControl in _sourceControls)
73 | {
74 | try
75 | {
76 | await sourceControl.MarkBuildAsSucceededAsync(context, description);
77 | }
78 | catch (Exception ex)
79 | {
80 | BuildContext.CakeContext.Warning($"Failed to update status: {ex.Message}");
81 | }
82 | }
83 | }
84 | }
--------------------------------------------------------------------------------
/src/Directory.Build.shared.xamltools.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | false
35 |
36 |
37 |
38 | true
39 |
40 |
41 |
42 |
43 | False
44 | False
45 | False
46 |
47 |
48 |
49 |
50 | True
51 |
52 |
53 |
54 |
55 | False
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
66 |
67 |
68 |
69 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.5.33424.131
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A8A1A4EE-E04A-43AB-90C9-41E7B82EE1E5}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "misc", "misc", "{1FE0D431-A761-4239-B2D6-D32C70723FD2}"
9 | ProjectSection(SolutionItems) = preProject
10 | Directory.build.project.props = Directory.build.project.props
11 | Directory.build.props = Directory.build.props
12 | Directory.build.shared.explicit.props = Directory.build.shared.explicit.props
13 | Directory.build.shared.implicit.props = Directory.build.shared.implicit.props
14 | Directory.build.shared.mat.props = Directory.build.shared.mat.props
15 | Directory.build.targets = Directory.build.targets
16 | GlobalSuppressions.cs = GlobalSuppressions.cs
17 | nuget.config = nuget.config
18 | Orc.CommandLine.sln.DotSettings = Orc.CommandLine.sln.DotSettings
19 | SolutionAssemblyInfo.cs = SolutionAssemblyInfo.cs
20 | EndProjectSection
21 | EndProject
22 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{0787DFC6-AB24-4D00-A8A4-FF203DC7D080}"
23 | EndProject
24 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{D3EA1078-BF3D-4709-871C-AAFF70B95045}"
25 | EndProject
26 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Orc.CommandLine", "Orc.CommandLine\Orc.CommandLine.csproj", "{52E01A33-3A3F-4D04-83AC-100EACD9541E}"
27 | EndProject
28 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Orc.CommandLine.Tests", "Orc.CommandLine.Tests\Orc.CommandLine.Tests.csproj", "{7EF7D9A5-22AA-46C9-AD78-55488068FA88}"
29 | EndProject
30 | Global
31 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
32 | Debug|Any CPU = Debug|Any CPU
33 | Release|Any CPU = Release|Any CPU
34 | EndGlobalSection
35 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
36 | {52E01A33-3A3F-4D04-83AC-100EACD9541E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
37 | {52E01A33-3A3F-4D04-83AC-100EACD9541E}.Debug|Any CPU.Build.0 = Debug|Any CPU
38 | {52E01A33-3A3F-4D04-83AC-100EACD9541E}.Release|Any CPU.ActiveCfg = Release|Any CPU
39 | {52E01A33-3A3F-4D04-83AC-100EACD9541E}.Release|Any CPU.Build.0 = Release|Any CPU
40 | {7EF7D9A5-22AA-46C9-AD78-55488068FA88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
41 | {7EF7D9A5-22AA-46C9-AD78-55488068FA88}.Debug|Any CPU.Build.0 = Debug|Any CPU
42 | {7EF7D9A5-22AA-46C9-AD78-55488068FA88}.Release|Any CPU.ActiveCfg = Release|Any CPU
43 | {7EF7D9A5-22AA-46C9-AD78-55488068FA88}.Release|Any CPU.Build.0 = Release|Any CPU
44 | EndGlobalSection
45 | GlobalSection(SolutionProperties) = preSolution
46 | HideSolutionNode = FALSE
47 | EndGlobalSection
48 | GlobalSection(NestedProjects) = preSolution
49 | {0787DFC6-AB24-4D00-A8A4-FF203DC7D080} = {A8A1A4EE-E04A-43AB-90C9-41E7B82EE1E5}
50 | {D3EA1078-BF3D-4709-871C-AAFF70B95045} = {A8A1A4EE-E04A-43AB-90C9-41E7B82EE1E5}
51 | {52E01A33-3A3F-4D04-83AC-100EACD9541E} = {0787DFC6-AB24-4D00-A8A4-FF203DC7D080}
52 | {7EF7D9A5-22AA-46C9-AD78-55488068FA88} = {D3EA1078-BF3D-4709-871C-AAFF70B95045}
53 | EndGlobalSection
54 | GlobalSection(ExtensibilityGlobals) = postSolution
55 | SolutionGuid = {CEF72B02-2F3A-421B-9465-F83DC4E29304}
56 | EndGlobalSection
57 | EndGlobal
58 |
--------------------------------------------------------------------------------
/deployment/cake/templates-tasks.cake:
--------------------------------------------------------------------------------
1 | #l "templates-variables.cake"
2 |
3 | using System.Linq;
4 | using System.Text.RegularExpressions;
5 | using System.Xml.Linq;
6 | using System.IO;
7 |
8 | //-------------------------------------------------------------
9 |
10 | public class TemplatesProcessor : ProcessorBase
11 | {
12 | public TemplatesProcessor(BuildContext buildContext)
13 | : base(buildContext)
14 | {
15 | var templatesRelativePath = "./deployment/templates";
16 |
17 | if (CakeContext.DirectoryExists(templatesRelativePath))
18 | {
19 | var currentDirectoryPath = System.IO.Directory.GetCurrentDirectory();
20 | var templateAbsolutePath = System.IO.Path.Combine(currentDirectoryPath, templatesRelativePath);
21 | var files = System.IO.Directory.GetFiles(templateAbsolutePath, "*.*", System.IO.SearchOption.AllDirectories);
22 |
23 | CakeContext.Information($"Found '{files.Count()}' template files");
24 |
25 | foreach (var file in files)
26 | {
27 | BuildContext.Templates.Items.Add(file.Substring(templateAbsolutePath.Length + 1));
28 | }
29 | }
30 | }
31 |
32 | public override bool HasItems()
33 | {
34 | return BuildContext.Templates.Items.Count > 0;
35 | }
36 |
37 | public override async Task PrepareAsync()
38 | {
39 |
40 | }
41 |
42 | public override async Task UpdateInfoAsync()
43 | {
44 | if (!HasItems())
45 | {
46 | return;
47 | }
48 |
49 | var variableRegex = new Regex(@"\$\{([^}]+)\}", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Compiled);
50 |
51 | foreach (var template in BuildContext.Templates.Items)
52 | {
53 | CakeContext.Information($"Updating template file '{template}'");
54 |
55 | var templateSourceFile = $"./deployment/templates/{template}";
56 | var content = CakeContext.FileReadText(templateSourceFile);
57 |
58 | var matches = variableRegex.Matches(content);
59 |
60 | foreach (var match in matches.Cast())
61 | {
62 | var variableName = match.Groups[1].Value;
63 |
64 | CakeContext.Information($"Found usage of variable '{variableName}'");
65 |
66 | if (!BuildContext.Variables.TryGetValue(variableName, out var replacement))
67 | {
68 | CakeContext.Error($"Could not find value for variable '{variableName}'");
69 | continue;
70 | }
71 |
72 | content = content.Replace($"${{{variableName}}}", replacement);
73 | }
74 |
75 | CakeContext.FileWriteText($"{template}", content);
76 | }
77 | }
78 |
79 | public override async Task BuildAsync()
80 | {
81 | // Run templates every time
82 | await UpdateInfoAsync();
83 | }
84 |
85 | public override async Task PackageAsync()
86 | {
87 | // Run templates every time
88 | await UpdateInfoAsync();
89 | }
90 |
91 | public override async Task DeployAsync()
92 | {
93 | if (!HasItems())
94 | {
95 | return;
96 | }
97 | }
98 |
99 | public override async Task FinalizeAsync()
100 | {
101 |
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/deployment/cake/issuetrackers-github.cake:
--------------------------------------------------------------------------------
1 | #tool "nuget:?package=gitreleasemanager&version=0.20.0"
2 |
3 | //-------------------------------------------------------------
4 |
5 | public class GitHubIssueTracker : IIssueTracker
6 | {
7 | public GitHubIssueTracker(BuildContext buildContext)
8 | {
9 | BuildContext = buildContext;
10 |
11 | ApiKey = buildContext.BuildServer.GetVariable("GitHubApiKey", showValue: false);
12 | OwnerName = buildContext.BuildServer.GetVariable("GitHubOwnerName", buildContext.General.Copyright.Company, showValue: true);
13 | ProjectName = buildContext.BuildServer.GetVariable("GitHubProjectName", buildContext.General.Solution.Name, showValue: true);
14 |
15 | if (!string.IsNullOrWhiteSpace(ApiKey) &&
16 | !string.IsNullOrWhiteSpace(OwnerName) &&
17 | !string.IsNullOrWhiteSpace(ProjectName))
18 | {
19 | IsAvailable = true;
20 | }
21 | }
22 |
23 | public BuildContext BuildContext { get; private set; }
24 |
25 | public string ApiKey { get; set; }
26 | public string OwnerName { get; set; }
27 | public string ProjectName { get; set; }
28 |
29 | public string OwnerAndProjectName
30 | {
31 | get { return $"{OwnerName}/{ProjectName}"; }
32 | }
33 |
34 | public bool IsAvailable { get; private set; }
35 |
36 | public async Task CreateAndReleaseVersionAsync()
37 | {
38 | if (!IsAvailable)
39 | {
40 | BuildContext.CakeContext.Information("GitHub is not available, skipping GitHub integration");
41 | return;
42 | }
43 |
44 | var version = BuildContext.General.Version.FullSemVer;
45 |
46 | BuildContext.CakeContext.Information("Releasing version '{0}' in GitHub", version);
47 |
48 | // For docs, see https://cakebuild.net/dsl/gitreleasemanager/
49 |
50 | BuildContext.CakeContext.Information("Step 1 / 4: Creating release");
51 |
52 | BuildContext.CakeContext.GitReleaseManagerCreate(ApiKey, OwnerName, ProjectName, new GitReleaseManagerCreateSettings
53 | {
54 | TargetDirectory = BuildContext.General.RootDirectory,
55 | Milestone = BuildContext.General.Version.MajorMinorPatch,
56 | Name = version,
57 | Prerelease = !BuildContext.General.IsOfficialBuild,
58 | TargetCommitish = BuildContext.General.Repository.CommitId
59 | });
60 |
61 | BuildContext.CakeContext.Information("Step 2 / 4: Adding assets to the release (not supported yet)");
62 |
63 | // Not yet supported
64 |
65 | if (!BuildContext.General.IsOfficialBuild)
66 | {
67 | BuildContext.CakeContext.Information("GitHub release publishing only runs against non-prerelease builds");
68 | }
69 | else
70 | {
71 | BuildContext.CakeContext.Information("Step 3 / 4: Publishing release");
72 |
73 | BuildContext.CakeContext.GitReleaseManagerPublish(ApiKey, OwnerName, ProjectName, BuildContext.General.Version.MajorMinorPatch, new GitReleaseManagerPublishSettings
74 | {
75 | TargetDirectory = BuildContext.General.RootDirectory
76 | });
77 |
78 | BuildContext.CakeContext.Information("Step 4 / 4: Closing the milestone");
79 |
80 | BuildContext.CakeContext.GitReleaseManagerClose(ApiKey, OwnerName, ProjectName, BuildContext.General.Version.MajorMinorPatch, new GitReleaseManagerCloseMilestoneSettings
81 | {
82 | TargetDirectory = BuildContext.General.RootDirectory
83 | });
84 | }
85 |
86 | BuildContext.CakeContext.Information("Released version in GitHub");
87 | }
88 | }
--------------------------------------------------------------------------------
/src/Directory.Build.shared.implicit.props:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 | $(NoWarn);CA1416;CS1591;CS1998;NU1603;NU1605;NU1608;NU1701;AD0001;HAA0301;HAA0302;HAA0303;HAA0401;HAA0603
8 | $(NoError);CS1591;CS1998;NU1603;NU1605;NU1608;NU1701;AD0001;HAA0301;HAA0302;HAA0303;HAA0401;HAA0603
9 | true
10 | false
11 | true
12 | false
13 | false
14 | Release
15 | $(ProjectDir)..\..\output\$(Configuration)\
16 | $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb;.xml
17 | False
18 | true
19 |
20 |
21 |
22 |
26 |
27 |
28 | true
29 |
30 |
31 |
32 |
33 |
34 | latest
35 |
36 |
37 |
38 |
40 | portable
41 |
42 | true
43 |
44 |
45 |
46 |
48 | portable
49 | true
50 |
51 |
52 |
53 |
55 | portable
56 | true
57 |
58 |
59 |
60 |
61 |
62 | direct
63 |
64 | low
65 |
66 |
67 |
68 |
69 | true
70 |
71 |
72 |
--------------------------------------------------------------------------------
/deployment/cake/notifications-msteams.cake:
--------------------------------------------------------------------------------
1 | #addin "nuget:?package=Cake.MicrosoftTeams&version=2.0.0"
2 |
3 | //-------------------------------------------------------------
4 |
5 | public class MsTeamsNotifier : INotifier
6 | {
7 | public MsTeamsNotifier(BuildContext buildContext)
8 | {
9 | BuildContext = buildContext;
10 |
11 | WebhookUrl = buildContext.BuildServer.GetVariable("MsTeamsWebhookUrl", showValue: false);
12 | WebhookUrlForErrors = buildContext.BuildServer.GetVariable("MsTeamsWebhookUrlForErrors", WebhookUrl, showValue: false);
13 | }
14 |
15 | public BuildContext BuildContext { get; private set; }
16 |
17 | public string WebhookUrl { get; private set; }
18 | public string WebhookUrlForErrors { get; private set; }
19 |
20 | public string GetMsTeamsWebhookUrl(string project, TargetType targetType)
21 | {
22 | // Allow per target overrides via "MsTeamsWebhookUrlFor[TargetType]"
23 | var targetTypeUrl = GetTargetSpecificConfigurationValue(BuildContext, targetType, "MsTeamsWebhookUrlFor", string.Empty);
24 | if (!string.IsNullOrEmpty(targetTypeUrl))
25 | {
26 | return targetTypeUrl;
27 | }
28 |
29 | // Allow per project overrides via "MsTeamsWebhookUrlFor[ProjectName]"
30 | var projectTypeUrl = GetProjectSpecificConfigurationValue(BuildContext, project, "MsTeamsWebhookUrlFor", string.Empty);
31 | if (!string.IsNullOrEmpty(projectTypeUrl))
32 | {
33 | return projectTypeUrl;
34 | }
35 |
36 | // Return default fallback
37 | return WebhookUrl;
38 | }
39 |
40 | //-------------------------------------------------------------
41 |
42 | private string GetMsTeamsTarget(string project, TargetType targetType, NotificationType notificationType)
43 | {
44 | if (notificationType == NotificationType.Error)
45 | {
46 | return WebhookUrlForErrors;
47 | }
48 |
49 | return GetMsTeamsWebhookUrl(project, targetType);
50 | }
51 |
52 | //-------------------------------------------------------------
53 |
54 | public async Task NotifyAsync(string project, string message, TargetType targetType, NotificationType notificationType)
55 | {
56 | var targetWebhookUrl = GetMsTeamsTarget(project, targetType, notificationType);
57 | if (string.IsNullOrWhiteSpace(targetWebhookUrl))
58 | {
59 | return;
60 | }
61 |
62 | var messageCard = new MicrosoftTeamsMessageCard
63 | {
64 | title = project,
65 | summary = notificationType.ToString(),
66 | sections = new []
67 | {
68 | new MicrosoftTeamsMessageSection
69 | {
70 | activityTitle = notificationType.ToString(),
71 | activitySubtitle = message,
72 | activityText = " ",
73 | activityImage = "https://raw.githubusercontent.com/cake-build/graphics/master/png/cake-small.png",
74 | facts = new []
75 | {
76 | new MicrosoftTeamsMessageFacts { name ="Project", value = project },
77 | new MicrosoftTeamsMessageFacts { name ="Version", value = BuildContext.General.Version.FullSemVer },
78 | new MicrosoftTeamsMessageFacts { name ="CakeVersion", value = BuildContext.CakeContext.Environment.Runtime.CakeVersion.ToString() },
79 | //new MicrosoftTeamsMessageFacts { name ="TargetFramework", value = Context.Environment.Runtime .TargetFramework.ToString() },
80 | },
81 | }
82 | }
83 | };
84 |
85 | var result = BuildContext.CakeContext.MicrosoftTeamsPostMessage(messageCard, new MicrosoftTeamsSettings
86 | {
87 | IncomingWebhookUrl = targetWebhookUrl
88 | });
89 |
90 | if (result != System.Net.HttpStatusCode.OK)
91 | {
92 | BuildContext.CakeContext.Warning(string.Format("MsTeams result: {0}", result));
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/deployment/cake/dependencies-variables.cake:
--------------------------------------------------------------------------------
1 | #l "buildserver.cake"
2 |
3 | //-------------------------------------------------------------
4 |
5 | public class DependenciesContext : BuildContextWithItemsBase
6 | {
7 | public DependenciesContext(IBuildContext parentBuildContext, Dictionary> dependencies)
8 | : base(parentBuildContext)
9 | {
10 | Dependencies = dependencies ?? new Dictionary>();
11 | Items = Dependencies.Keys.ToList();
12 | }
13 |
14 | public Dictionary> Dependencies { get; private set; }
15 |
16 | protected override void ValidateContext()
17 | {
18 |
19 | }
20 |
21 | protected override void LogStateInfoForContext()
22 | {
23 | CakeContext.Information($"Found '{Items.Count}' dependency projects");
24 | }
25 |
26 | public bool ShouldBuildDependency(string dependencyProject)
27 | {
28 | return ShouldBuildDependency(dependencyProject, Array.Empty());
29 | }
30 |
31 | public bool ShouldBuildDependency(string dependencyProject, IEnumerable knownDependenciesToBeBuilt)
32 | {
33 | if (!Dependencies.TryGetValue(dependencyProject, out var dependencyInfo))
34 | {
35 | return false;
36 | }
37 |
38 | if (dependencyInfo.Count == 0)
39 | {
40 | // No explicit projects defined, always build dependency
41 | return true;
42 | }
43 |
44 | foreach (var projectRequiringDependency in dependencyInfo)
45 | {
46 | CakeContext.Information($"Checking whether '{projectRequiringDependency}' is in the list to be processed");
47 |
48 | // Check dependencies of dependencies
49 | if (knownDependenciesToBeBuilt.Any(x => string.Equals(x, projectRequiringDependency, StringComparison.OrdinalIgnoreCase)))
50 | {
51 | CakeContext.Information($"Dependency '{dependencyProject}' is a dependency of dependency project '{projectRequiringDependency}', including this in the build");
52 | return true;
53 | }
54 |
55 | // Special case: *if* this is the 2nd round we check, and the project requiring this dependency is a test project,
56 | // we should check whether the test project is not already excluded. If so, the Deploy[SomeProject]Tests will return true
57 | // and this logic will still include it, so we need to exclude it explicitly
58 | if (IsTestProject((BuildContext)ParentContext, projectRequiringDependency) &&
59 | !knownDependenciesToBeBuilt.Contains(projectRequiringDependency))
60 | {
61 | CakeContext.Information($"Dependency '{dependencyProject}' is a dependency of '{projectRequiringDependency}', but that is an already excluded test project, not yet including in the build");
62 |
63 | // Important: don't return, there might be other projects
64 | continue;
65 | }
66 |
67 | // Check if we should build this project
68 | if (ShouldProcessProject((BuildContext)ParentContext, projectRequiringDependency))
69 | {
70 | CakeContext.Information($"Dependency '{dependencyProject}' is a dependency of '{projectRequiringDependency}', including this in the build");
71 | return true;
72 | }
73 | }
74 |
75 | return false;
76 | }
77 | }
78 |
79 | //-------------------------------------------------------------
80 |
81 | private DependenciesContext InitializeDependenciesContext(BuildContext buildContext, IBuildContext parentBuildContext)
82 | {
83 | var data = new DependenciesContext(parentBuildContext, Dependencies);
84 |
85 | return data;
86 | }
87 |
88 | //-------------------------------------------------------------
89 |
90 | Dictionary> _dependencies;
91 |
92 | public Dictionary> Dependencies
93 | {
94 | get
95 | {
96 | if (_dependencies is null)
97 | {
98 | _dependencies = new Dictionary>();
99 | }
100 |
101 | return _dependencies;
102 | }
103 | }
--------------------------------------------------------------------------------
/deployment/cake/lib-sourcelink.cake:
--------------------------------------------------------------------------------
1 | public static bool IsSourceLinkSupported(BuildContext buildContext, string projectName, string projectFileName)
2 | {
3 | if (buildContext.General.SourceLink.IsDisabled)
4 | {
5 | return false;
6 | }
7 |
8 | if (buildContext.General.IsLocalBuild)
9 | {
10 | return false;
11 | }
12 |
13 | if (string.IsNullOrWhiteSpace(buildContext.General.Repository.Url))
14 | {
15 | return false;
16 | }
17 |
18 | // Only support C# projects
19 | if (!projectFileName.EndsWith(".csproj"))
20 | {
21 | return false;
22 | }
23 |
24 | // Is this a test project?
25 | if (buildContext.Tests.Items.Contains(projectName))
26 | {
27 | return false;
28 | }
29 |
30 | // Only support when running a real build, e.g. ot for 'Package' only
31 | if (!buildContext.General.Target.ToLower().Contains("build"))
32 | {
33 | return false;
34 | }
35 |
36 | return true;
37 | }
38 |
39 | //-------------------------------------------------------------
40 |
41 | public static void InjectSourceLinkInProjectFile(BuildContext buildContext, string projectName, string projectFileName)
42 | {
43 | try
44 | {
45 | // Only support C# projects
46 | if (!IsSourceLinkSupported(buildContext, projectName, projectFileName))
47 | {
48 | return;
49 | }
50 |
51 | // For SourceLink to work, the .csproj should contain something like this:
52 | //
53 | var projectFileContents = System.IO.File.ReadAllText(projectFileName);
54 | if (projectFileContents.Contains("Microsoft.SourceLink.GitHub"))
55 | {
56 | return;
57 | }
58 |
59 | buildContext.CakeContext.Warning("No SourceLink reference found, automatically injecting SourceLink package reference now");
60 |
61 | //const string MSBuildNS = (XNamespace) "http://schemas.microsoft.com/developer/msbuild/2003";
62 |
63 | var xmlDocument = XDocument.Parse(projectFileContents);
64 | var projectElement = xmlDocument.Root;
65 |
66 | // Item group with package reference
67 | var referencesItemGroup = new XElement("ItemGroup");
68 | var sourceLinkPackageReference = new XElement("PackageReference");
69 | sourceLinkPackageReference.Add(new XAttribute("Include", "Microsoft.SourceLink.GitHub"));
70 | sourceLinkPackageReference.Add(new XAttribute("Version", "1.1.1"));
71 | sourceLinkPackageReference.Add(new XAttribute("PrivateAssets", "all"));
72 |
73 | referencesItemGroup.Add(sourceLinkPackageReference);
74 | projectElement.Add(referencesItemGroup);
75 |
76 | // Item group with source root
77 | //
78 | var sourceRootItemGroup = new XElement("ItemGroup");
79 | var sourceRoot = new XElement("SourceRoot");
80 |
81 | // Required to end with a \
82 | var sourceRootValue = buildContext.General.RootDirectory;
83 | var directorySeparator = System.IO.Path.DirectorySeparatorChar.ToString();
84 | if (!sourceRootValue.EndsWith(directorySeparator))
85 | {
86 | sourceRootValue += directorySeparator;
87 | };
88 |
89 | sourceRoot.Add(new XAttribute("Include", sourceRootValue));
90 | sourceRoot.Add(new XAttribute("RepositoryUrl", buildContext.General.Repository.Url));
91 |
92 | // Note: since we are not allowing source control manager queries (we don't want to require a .git directory),
93 | // we must specify the additional information below
94 | sourceRoot.Add(new XAttribute("SourceControl", "git"));
95 | sourceRoot.Add(new XAttribute("RevisionId", buildContext.General.Repository.CommitId));
96 |
97 | sourceRootItemGroup.Add(sourceRoot);
98 | projectElement.Add(sourceRootItemGroup);
99 |
100 | xmlDocument.Save(projectFileName);
101 | }
102 | catch (Exception ex)
103 | {
104 | buildContext.CakeContext.Error($"Failed to process source link for project '{projectFileName}': {ex.Message}");
105 | }
106 | }
--------------------------------------------------------------------------------
/deployment/cake/apps-wpf-variables.cake:
--------------------------------------------------------------------------------
1 | #l "buildserver.cake"
2 |
3 | //-------------------------------------------------------------
4 |
5 | public class WpfContext : BuildContextWithItemsBase
6 | {
7 | public WpfContext(IBuildContext parentBuildContext)
8 | : base(parentBuildContext)
9 | {
10 | }
11 |
12 |
13 | public string DeploymentsShare { get; set; }
14 | public string Channel { get; set; }
15 | public bool AppendDeploymentChannelSuffix { get; set; }
16 | public bool UpdateDeploymentsShare { get; set; }
17 | public string AzureDeploymentsStorageConnectionString { get; set; }
18 |
19 | public bool GenerateDeploymentCatalog { get; set; }
20 | public bool GroupUpdatesByMajorVersion { get; set; }
21 | public bool DeployUpdatesToAlphaChannel { get; set; }
22 | public bool DeployUpdatesToBetaChannel { get; set; }
23 | public bool DeployUpdatesToStableChannel { get; set; }
24 | public bool DeployInstallers { get; set; }
25 |
26 | protected override void ValidateContext()
27 | {
28 |
29 | }
30 |
31 | protected override void LogStateInfoForContext()
32 | {
33 | CakeContext.Information($"Found '{Items.Count}' wpf projects");
34 |
35 | CakeContext.Information($"Generate Deployment Catalog: '{GenerateDeploymentCatalog}'");
36 | CakeContext.Information($"Group updates by major version: '{GroupUpdatesByMajorVersion}'");
37 | CakeContext.Information($"Deploy updates to alpha channel: '{DeployUpdatesToAlphaChannel}'");
38 | CakeContext.Information($"Deploy updates to beta channel: '{DeployUpdatesToBetaChannel}'");
39 | CakeContext.Information($"Deploy updates to stable channel: '{DeployUpdatesToStableChannel}'");
40 | CakeContext.Information($"Deploy installers: '{DeployInstallers}'");
41 | }
42 |
43 | public string GetDeploymentShareForProject(string projectName)
44 | {
45 | var projectSlug = GetProjectSlug(projectName, "-");
46 | var deploymentShare = System.IO.Path.Combine(DeploymentsShare, projectSlug);
47 |
48 | return deploymentShare;
49 | }
50 | }
51 |
52 | //-------------------------------------------------------------
53 |
54 | private WpfContext InitializeWpfContext(BuildContext buildContext, IBuildContext parentBuildContext)
55 | {
56 | var data = new WpfContext(parentBuildContext)
57 | {
58 | Items = WpfApps ?? new List(),
59 | DeploymentsShare = buildContext.BuildServer.GetVariable("DeploymentsShare", showValue: true),
60 | Channel = buildContext.BuildServer.GetVariable("Channel", showValue: true),
61 | AppendDeploymentChannelSuffix = buildContext.BuildServer.GetVariableAsBool("AppendDeploymentChannelSuffix", false, showValue: true),
62 | UpdateDeploymentsShare = buildContext.BuildServer.GetVariableAsBool("UpdateDeploymentsShare", true, showValue: true),
63 | AzureDeploymentsStorageConnectionString = buildContext.BuildServer.GetVariable("AzureDeploymentsStorageConnectionString"),
64 | GenerateDeploymentCatalog = buildContext.BuildServer.GetVariableAsBool("WpfGenerateDeploymentCatalog", true, showValue: true),
65 | GroupUpdatesByMajorVersion = buildContext.BuildServer.GetVariableAsBool("WpfGroupUpdatesByMajorVersion", false, showValue: true),
66 | DeployUpdatesToAlphaChannel = buildContext.BuildServer.GetVariableAsBool("WpfDeployUpdatesToAlphaChannel", true, showValue: true),
67 | DeployUpdatesToBetaChannel = buildContext.BuildServer.GetVariableAsBool("WpfDeployUpdatesToBetaChannel", true, showValue: true),
68 | DeployUpdatesToStableChannel = buildContext.BuildServer.GetVariableAsBool("WpfDeployUpdatesToStableChannel", true, showValue: true),
69 | DeployInstallers = buildContext.BuildServer.GetVariableAsBool("WpfDeployInstallers", true, showValue: true),
70 | };
71 |
72 | if (string.IsNullOrWhiteSpace(data.Channel))
73 | {
74 | data.Channel = DetermineChannel(buildContext.General);
75 |
76 | data.CakeContext.Information($"Determined channel '{data.Channel}' for wpf projects");
77 | }
78 |
79 | return data;
80 | }
81 |
82 | //-------------------------------------------------------------
83 |
84 | List _wpfApps;
85 |
86 | public List WpfApps
87 | {
88 | get
89 | {
90 | if (_wpfApps is null)
91 | {
92 | _wpfApps = new List();
93 | }
94 |
95 | return _wpfApps;
96 | }
97 | }
--------------------------------------------------------------------------------
/deployment/cake/aspire-variables.cake:
--------------------------------------------------------------------------------
1 | #l "buildserver.cake"
2 |
3 | //-------------------------------------------------------------
4 |
5 | public class AspireContext : BuildContextWithItemsBase
6 | {
7 | public AspireContext(IBuildContext parentBuildContext)
8 | : base(parentBuildContext)
9 | {
10 | }
11 |
12 | public string EnvironmentName { get; set; }
13 |
14 | public string AzurePrincipalId { get; set; }
15 |
16 | public string AzurePrincipalType { get; set; }
17 |
18 | public string AzureLocation { get; set; }
19 |
20 | public string AzureResourceGroup { get; set; }
21 |
22 | public string AzureSubscriptionId { get; set; }
23 |
24 | public string AzureTenantId { get; set; }
25 |
26 | public string AzureClientId { get; set; }
27 |
28 | public string AzureClientSecret { get; set; }
29 |
30 | protected override void ValidateContext()
31 | {
32 | if (Items.Count == 0)
33 | {
34 | return;
35 | }
36 |
37 | if (Items.Count > 1)
38 | {
39 | throw new InvalidOperationException("Multiple Aspire projects found. Please ensure only one Aspire project is defined in the solution.");
40 | }
41 |
42 | if (string.IsNullOrWhiteSpace(EnvironmentName))
43 | {
44 | throw new InvalidOperationException("Environment name is not set. Please set the 'AspireEnvironment' variable.");
45 | }
46 |
47 | if (string.IsNullOrWhiteSpace(AzurePrincipalId))
48 | {
49 | throw new InvalidOperationException("Azure principal ID is not set. Please set the 'AzurePrincipalId' variable.");
50 | }
51 |
52 | if (string.IsNullOrWhiteSpace(AzureLocation))
53 | {
54 | throw new InvalidOperationException("Azure location is not set. Please set the 'AzureLocation' variable.");
55 | }
56 |
57 | if (string.IsNullOrWhiteSpace(AzureResourceGroup))
58 | {
59 | throw new InvalidOperationException("Azure resource group is not set. Please set the 'AzureResourceGroup' variable.");
60 | }
61 |
62 | if (string.IsNullOrWhiteSpace(AzureSubscriptionId))
63 | {
64 | throw new InvalidOperationException("Azure subscription ID is not set. Please set the 'AzureSubscriptionId' variable.");
65 | }
66 |
67 | if (string.IsNullOrWhiteSpace(AzureTenantId))
68 | {
69 | throw new InvalidOperationException("Azure tenant ID is not set. Please set the 'AzureTenantId' variable.");
70 | }
71 |
72 | if (string.IsNullOrWhiteSpace(AzureClientId))
73 | {
74 | throw new InvalidOperationException("Azure client ID is not set. Please set the 'AzureClientId' variable.");
75 | }
76 |
77 | if (string.IsNullOrWhiteSpace(AzureClientSecret))
78 | {
79 | throw new InvalidOperationException("Azure client secret is not set. Please set the 'AzureClientSecret' variable.");
80 | }
81 | }
82 |
83 | protected override void LogStateInfoForContext()
84 | {
85 | CakeContext.Information($"Found '{Items.Count}' Aspire projects");
86 | }
87 | }
88 |
89 | //-------------------------------------------------------------
90 |
91 | private AspireContext InitializeAspireContext(BuildContext buildContext, IBuildContext parentBuildContext)
92 | {
93 | var data = new AspireContext(parentBuildContext)
94 | {
95 | Items = AspireProjects ?? new List(),
96 | EnvironmentName = buildContext.BuildServer.GetVariable("AspireEnvironment", "prod", showValue: true),
97 | AzurePrincipalId = buildContext.BuildServer.GetVariable("AspireAzurePrincipalId", showValue: true),
98 | AzurePrincipalType = buildContext.BuildServer.GetVariable("AspireAzurePrincipalType", "ManagedIdentity", showValue: true),
99 | AzureLocation = buildContext.BuildServer.GetVariable("AspireAzureLocation", showValue: true),
100 | AzureResourceGroup = buildContext.BuildServer.GetVariable("AspireAzureResourceGroup", showValue: true),
101 | AzureSubscriptionId = buildContext.BuildServer.GetVariable("AspireAzureSubscriptionId", showValue: true),
102 | AzureTenantId = buildContext.BuildServer.GetVariable("AspireAzureTenantId", showValue: true),
103 | AzureClientId = buildContext.BuildServer.GetVariable("AspireAzureClientId", showValue: true),
104 | AzureClientSecret = buildContext.BuildServer.GetVariable("AspireAzureClientSecret", showValue: false)
105 | };
106 |
107 | return data;
108 | }
109 |
110 | //-------------------------------------------------------------
111 |
112 | List _aspireProjects;
113 |
114 | public List AspireProjects
115 | {
116 | get
117 | {
118 | if (_aspireProjects is null)
119 | {
120 | _aspireProjects = new List();
121 | }
122 |
123 | return _aspireProjects;
124 | }
125 | }
--------------------------------------------------------------------------------
/src/Orc.CommandLine/MultilingualResources/Orc.CommandLine.de.xlf:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
10 | Cannot parse '{0}' because an exception occured: {1}
11 | Cannot parse '{0}' because an exception occured: {1}
12 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
13 |
14 |
15 | Cannot parse '{0}' since there is no empty switch on the context
16 | Cannot parse '{0}' since there is no empty switch on the context
17 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
18 |
19 |
20 | Cannot parse '{0}' because it is not a switch and it is not the first argument
21 | Cannot parse '{0}' because it is not a switch and it is not the first argument
22 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
23 |
24 |
25 | Cannot parse '{0}' because the switch is not recognized
26 | Cannot parse '{0}' because the switch is not recognized
27 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
28 |
29 |
30 | Cannot parse '{0}' because the actual value is not found (command line is too short)
31 | Cannot parse '{0}' because the actual value is not found (command line is too short)
32 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
33 |
34 |
35 | [no switch]
36 | [no switch]
37 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
38 |
39 |
40 | Required switch '{0}' is not specified
41 | Required switch '{0}' is not specified
42 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine/MultilingualResources/Orc.CommandLine.es.xlf:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
10 | Cannot parse '{0}' because an exception occured: {1}
11 | Cannot parse '{0}' because an exception occured: {1}
12 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
13 |
14 |
15 | Cannot parse '{0}' since there is no empty switch on the context
16 | Cannot parse '{0}' since there is no empty switch on the context
17 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
18 |
19 |
20 | Cannot parse '{0}' because it is not a switch and it is not the first argument
21 | Cannot parse '{0}' because it is not a switch and it is not the first argument
22 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
23 |
24 |
25 | Cannot parse '{0}' because the switch is not recognized
26 | Cannot parse '{0}' because the switch is not recognized
27 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
28 |
29 |
30 | Cannot parse '{0}' because the actual value is not found (command line is too short)
31 | Cannot parse '{0}' because the actual value is not found (command line is too short)
32 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
33 |
34 |
35 | [no switch]
36 | [no switch]
37 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
38 |
39 |
40 | Required switch '{0}' is not specified
41 | Required switch '{0}' is not specified
42 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine/MultilingualResources/Orc.CommandLine.fr.xlf:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
10 | Cannot parse '{0}' because an exception occured: {1}
11 | Cannot parse '{0}' because an exception occured: {1}
12 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
13 |
14 |
15 | Cannot parse '{0}' since there is no empty switch on the context
16 | Cannot parse '{0}' since there is no empty switch on the context
17 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
18 |
19 |
20 | Cannot parse '{0}' because it is not a switch and it is not the first argument
21 | Cannot parse '{0}' because it is not a switch and it is not the first argument
22 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
23 |
24 |
25 | Cannot parse '{0}' because the switch is not recognized
26 | Cannot parse '{0}' because the switch is not recognized
27 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
28 |
29 |
30 | Cannot parse '{0}' because the actual value is not found (command line is too short)
31 | Cannot parse '{0}' because the actual value is not found (command line is too short)
32 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
33 |
34 |
35 | [no switch]
36 | [no switch]
37 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
38 |
39 |
40 | Required switch '{0}' is not specified
41 | Required switch '{0}' is not specified
42 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine/MultilingualResources/Orc.CommandLine.nl.xlf:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
10 | Cannot parse '{0}' because an exception occured: {1}
11 | Cannot parse '{0}' because an exception occured: {1}
12 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
13 |
14 |
15 | Cannot parse '{0}' since there is no empty switch on the context
16 | Cannot parse '{0}' since there is no empty switch on the context
17 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
18 |
19 |
20 | Cannot parse '{0}' because it is not a switch and it is not the first argument
21 | Cannot parse '{0}' because it is not a switch and it is not the first argument
22 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
23 |
24 |
25 | Cannot parse '{0}' because the switch is not recognized
26 | Cannot parse '{0}' because the switch is not recognized
27 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
28 |
29 |
30 | Cannot parse '{0}' because the actual value is not found (command line is too short)
31 | Cannot parse '{0}' because the actual value is not found (command line is too short)
32 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
33 |
34 |
35 | [no switch]
36 | [no switch]
37 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
38 |
39 |
40 | Required switch '{0}' is not specified
41 | Required switch '{0}' is not specified
42 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine/MultilingualResources/Orc.CommandLine.ru.xlf:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
10 | Cannot parse '{0}' because an exception occured: {1}
11 | Cannot parse '{0}' because an exception occured: {1}
12 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
13 |
14 |
15 | Cannot parse '{0}' since there is no empty switch on the context
16 | Cannot parse '{0}' since there is no empty switch on the context
17 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
18 |
19 |
20 | Cannot parse '{0}' because it is not a switch and it is not the first argument
21 | Cannot parse '{0}' because it is not a switch and it is not the first argument
22 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
23 |
24 |
25 | Cannot parse '{0}' because the switch is not recognized
26 | Cannot parse '{0}' because the switch is not recognized
27 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
28 |
29 |
30 | Cannot parse '{0}' because the actual value is not found (command line is too short)
31 | Cannot parse '{0}' because the actual value is not found (command line is too short)
32 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
33 |
34 |
35 | [no switch]
36 | [no switch]
37 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
38 |
39 |
40 | Required switch '{0}' is not specified
41 | Required switch '{0}' is not specified
42 | When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed.
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/deployment/cake/lib-nuget.cake:
--------------------------------------------------------------------------------
1 | public class NuGetServer
2 | {
3 | public string Url { get;set; }
4 |
5 | public string ApiKey { get;set; }
6 |
7 | public override string ToString()
8 | {
9 | var result = Url;
10 |
11 | result += string.Format(" (ApiKey present: '{0}')", !string.IsNullOrWhiteSpace(ApiKey));
12 |
13 | return result;
14 | }
15 | }
16 |
17 | //-------------------------------------------------------------
18 |
19 | public static List GetNuGetServers(string urls, string apiKeys)
20 | {
21 | var splittedUrls = urls.Split(new [] { ";" }, StringSplitOptions.None);
22 | var splittedApiKeys = apiKeys.Split(new [] { ";" }, StringSplitOptions.None);
23 |
24 | if (splittedUrls.Length != splittedApiKeys.Length)
25 | {
26 | throw new Exception("Number of api keys does not match number of urls. Even if an API key is not required, add an empty one");
27 | }
28 |
29 | var servers = new List();
30 |
31 | for (int i = 0; i < splittedUrls.Length; i++)
32 | {
33 | var url = splittedUrls[i];
34 | if (string.IsNullOrWhiteSpace(url))
35 | {
36 | throw new Exception("Url for NuGet server cannot be empty");
37 | }
38 |
39 | servers.Add(new NuGetServer
40 | {
41 | Url = url,
42 | ApiKey = splittedApiKeys[i]
43 | });
44 | }
45 |
46 | return servers;
47 | }
48 |
49 | //-------------------------------------------------------------
50 |
51 | private static void RestoreNuGetPackages(BuildContext buildContext, Cake.Core.IO.FilePath solutionOrProjectFileName)
52 | {
53 | buildContext.CakeContext.LogSeparator("Restoring packages for '{0}'", solutionOrProjectFileName);
54 |
55 | var sources = SplitSeparatedList(buildContext.General.NuGet.PackageSources, ';');
56 |
57 | var runtimeIdentifiers = new []
58 | {
59 | "win-x86",
60 | "win-x64",
61 | "win-arm64",
62 | "browser-wasm"
63 | };
64 |
65 | var supportedRuntimeIdentifiers = GetProjectRuntimesIdentifiers(buildContext, solutionOrProjectFileName, runtimeIdentifiers);
66 |
67 | RestoreNuGetPackagesUsingNuGet(buildContext, solutionOrProjectFileName, sources, supportedRuntimeIdentifiers);
68 | RestoreNuGetPackagesUsingDotnetRestore(buildContext, solutionOrProjectFileName, sources, supportedRuntimeIdentifiers);
69 | }
70 |
71 | //-------------------------------------------------------------
72 |
73 | private static void RestoreNuGetPackagesUsingNuGet(BuildContext buildContext, Cake.Core.IO.FilePath solutionOrProjectFileName, IReadOnlyList sources, IReadOnlyList runtimeIdentifiers)
74 | {
75 | if (!buildContext.General.NuGet.RestoreUsingNuGet)
76 | {
77 | return;
78 | }
79 |
80 | buildContext.CakeContext.LogSeparator("Restoring packages for '{0}' using 'NuGet'", solutionOrProjectFileName);
81 |
82 | // No need to deal with runtime identifiers
83 |
84 | try
85 | {
86 | var nuGetRestoreSettings = new NuGetRestoreSettings
87 | {
88 | DisableParallelProcessing = false,
89 | NoCache = false,
90 | NonInteractive = true,
91 | RequireConsent = false
92 | };
93 |
94 | if (sources.Count > 0)
95 | {
96 | nuGetRestoreSettings.Source = sources.ToList();
97 | }
98 |
99 | buildContext.CakeContext.NuGetRestore(solutionOrProjectFileName, nuGetRestoreSettings);
100 | }
101 | catch (Exception)
102 | {
103 | // Ignore
104 | }
105 | }
106 |
107 | //-------------------------------------------------------------
108 |
109 | private static void RestoreNuGetPackagesUsingDotnetRestore(BuildContext buildContext, Cake.Core.IO.FilePath solutionOrProjectFileName, IReadOnlyList sources, IReadOnlyList runtimeIdentifiers)
110 | {
111 | if (!buildContext.General.NuGet.RestoreUsingDotNetRestore)
112 | {
113 | return;
114 | }
115 |
116 | buildContext.CakeContext.LogSeparator("Restoring packages for '{0}' using 'dotnet restore'", solutionOrProjectFileName);
117 |
118 | foreach (var runtimeIdentifier in runtimeIdentifiers)
119 | {
120 | try
121 | {
122 | buildContext.CakeContext.LogSeparator("Restoring packages for '{0}' using 'dotnet restore' using runtime identifier '{1}'", solutionOrProjectFileName, runtimeIdentifier);
123 |
124 | var restoreSettings = new DotNetRestoreSettings
125 | {
126 | DisableParallel = false,
127 | Force = false,
128 | ForceEvaluate = false,
129 | IgnoreFailedSources = true,
130 | NoCache = false,
131 | NoDependencies = buildContext.General.NuGet.NoDependencies, // use true to speed up things
132 | Verbosity = DotNetVerbosity.Normal
133 | };
134 |
135 | if (!string.IsNullOrWhiteSpace(runtimeIdentifier))
136 | {
137 | buildContext.CakeContext.Information("Project restore uses explicit runtime identifier, forcing re-evaluation");
138 |
139 | restoreSettings.Force = true;
140 | restoreSettings.ForceEvaluate = true;
141 | restoreSettings.Runtime = runtimeIdentifier;
142 | }
143 |
144 | if (sources.Count > 0)
145 | {
146 | restoreSettings.Sources = sources.ToList();
147 | }
148 |
149 | using (buildContext.CakeContext.UseDiagnosticVerbosity())
150 | {
151 | buildContext.CakeContext.DotNetRestore(solutionOrProjectFileName.FullPath, restoreSettings);
152 | }
153 | }
154 | catch (Exception)
155 | {
156 | // Ignore
157 | }
158 | }
159 | }
--------------------------------------------------------------------------------
/src/Orc.CommandLine/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace Orc.CommandLine.Properties {
12 | using System;
13 | using Catel.Reflection;
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Orc.CommandLine.Properties.Resources", typeof(Resources).GetAssemblyEx());
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Looks up a localized string similar to Cannot parse '{0}' because an exception occured: {1}.
65 | ///
66 | internal static string CommandLine_CannotParseExceptionOccurred {
67 | get {
68 | return ResourceManager.GetString("CommandLine_CannotParseExceptionOccurred", resourceCulture);
69 | }
70 | }
71 |
72 | ///
73 | /// Looks up a localized string similar to Cannot parse '{0}' since there is no empty switch on the context.
74 | ///
75 | internal static string CommandLine_CannotParseNoEmptySwitch {
76 | get {
77 | return ResourceManager.GetString("CommandLine_CannotParseNoEmptySwitch", resourceCulture);
78 | }
79 | }
80 |
81 | ///
82 | /// Looks up a localized string similar to Cannot parse '{0}' because it is not a switch and it is not the first argument.
83 | ///
84 | internal static string CommandLine_CannotParseNoSwitch {
85 | get {
86 | return ResourceManager.GetString("CommandLine_CannotParseNoSwitch", resourceCulture);
87 | }
88 | }
89 |
90 | ///
91 | /// Looks up a localized string similar to Cannot parse '{0}' because the switch is not recognized.
92 | ///
93 | internal static string CommandLine_CannotParseSwitchNotRecognized {
94 | get {
95 | return ResourceManager.GetString("CommandLine_CannotParseSwitchNotRecognized", resourceCulture);
96 | }
97 | }
98 |
99 | ///
100 | /// Looks up a localized string similar to Cannot parse '{0}' because the actual value is not found (command line is too short).
101 | ///
102 | internal static string CommandLine_CannotParseValueMissing {
103 | get {
104 | return ResourceManager.GetString("CommandLine_CannotParseValueMissing", resourceCulture);
105 | }
106 | }
107 |
108 | ///
109 | /// Looks up a localized string similar to [no switch].
110 | ///
111 | internal static string CommandLine_NoSwitch {
112 | get {
113 | return ResourceManager.GetString("CommandLine_NoSwitch", resourceCulture);
114 | }
115 | }
116 |
117 | ///
118 | /// Looks up a localized string similar to Required switch '{0}' is not specified.
119 | ///
120 | internal static string CommandLine_RequiredSwitchNotSpecified {
121 | get {
122 | return ResourceManager.GetString("CommandLine_RequiredSwitchNotSpecified", resourceCulture);
123 | }
124 | }
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/src/Orc.CommandLine.Tests/Parsers/CommandLineParserFacts.cs:
--------------------------------------------------------------------------------
1 | namespace Orc.CommandLine.Tests;
2 |
3 | using System;
4 | using Catel.IoC;
5 | using Context;
6 | using NUnit.Framework;
7 |
8 | [TestFixture]
9 | public partial class CommandLineParserFacts
10 | {
11 | #region Methods
12 | private ICommandLineParser CreateCommandLineParser()
13 | {
14 | var serviceLocator = ServiceLocator.Default;
15 | #pragma warning disable IDISP001 // Dispose created
16 | var typeFactory = serviceLocator.ResolveType();
17 | #pragma warning restore IDISP001 // Dispose created
18 |
19 | return typeFactory.CreateInstanceWithParametersAndAutoCompletion(new OptionDefinitionService());
20 | }
21 |
22 | [TestCase("", "false", "0", "", "")]
23 | [TestCase("somefile", "false", "0", "", "somefile")]
24 | [TestCase("somefile /bs /s somestring /i 42", "true", "42", "somestring", "somefile")]
25 | [TestCase("C:\\folder\\file.txt /bs /s somestring /i 42", "true", "42", "somestring", "C:\\folder\\file.txt")]
26 | [TestCase("\"C:\\some folder\\file.txt\" /bs /s somestring /i 42", "true", "42", "somestring", "C:\\some folder\\file.txt")]
27 | [TestCase("\"C:\\some folder\\file.txt\" \"/bs\" \"/s\" somestring \"/i\" 42", "true", "42", "somestring", "C:\\some folder\\file.txt")]
28 | [TestCase("\" C:\\some folder\\file.txt \" \"/bs\" \"/s\" somestring \"/i\" 42", "true", "42", "somestring", "C:\\some folder\\file.txt")]
29 | [TestCase("'C:\\some folder\\file.txt' '/bs' '/s' somestring '/i' 42", "true", "42", "somestring", "C:\\some folder\\file.txt")]
30 | [TestCase("\"C:\\some folder\\file.txt\" \"-bs\" \"-s\" somestring \"-i\" 42", "true", "42", "somestring", "C:\\some folder\\file.txt")]
31 | [TestCase("\"C:\\some - folder\\file.txt\" \"-bs\" \"-s\" somestring \"-i\" 42", "true", "42", "somestring", "C:\\some - folder\\file.txt")]
32 | [TestCase("\"some file\" /bs /s somestring /i 42", "true", "42", "somestring", "some file")]
33 | [TestCase("/bs /s somestring /i 42", "true", "42", "somestring", "")]
34 | [TestCase("/bs /s \" some string \" /i 42", "true", "42", " some string ", "")]
35 | public void CorrectlyParsesCommandLinesWithFile(string input, string expectedBooleanSwitch, string expectedIntegerSwitch,
36 | string expectedStringSwitch, string expectedFileName)
37 | {
38 | var commandLineParser = CreateCommandLineParser();
39 |
40 | var context = new TestContextWithFile();
41 | var validationContext = commandLineParser.Parse(input, context);
42 |
43 | Assert.That(validationContext.HasErrors, Is.False);
44 | Assert.That(validationContext.HasWarnings, Is.False);
45 |
46 | Assert.That(string.Equals(expectedBooleanSwitch, context.BooleanSwitch.ToString(), StringComparison.OrdinalIgnoreCase), Is.True);
47 | Assert.That(string.Equals(expectedIntegerSwitch, context.IntegerSwitch.ToString(), StringComparison.OrdinalIgnoreCase), Is.True);
48 | Assert.That(string.Equals(expectedStringSwitch, context.StringSwitch), Is.True);
49 | Assert.That(string.Equals(expectedFileName, context.FileName), Is.True);
50 | }
51 |
52 | [TestCase("-trimquotes \"bla\"", "bla", null)]
53 | [TestCase("-trimquotes \"bla bla\"", "bla bla", null)]
54 | [TestCase("-donttrimquotes \"bla\"", null, "\"bla\"")]
55 | public void CorrectlyHandlesQuoteTrimming(string input, string? expectedTrimQuotesValue, string? expectedDontTrimQuotesValue)
56 | {
57 | var commandLineParser = CreateCommandLineParser();
58 |
59 | var context = new Tests.Context.TestContext();
60 | var validationContext = commandLineParser.Parse(input, context);
61 |
62 | Assert.That(context.TrimQuotes, Is.EqualTo(expectedTrimQuotesValue));
63 | Assert.That(context.DontTrimQuotes, Is.EqualTo(expectedDontTrimQuotesValue));
64 | }
65 |
66 | [TestCase("-h")]
67 | [TestCase("/h")]
68 | [TestCase("-help")]
69 | [TestCase("/help")]
70 | [TestCase("-?")]
71 | [TestCase("/?")]
72 | [TestCase("somefile -h")]
73 | [TestCase("somefile /bs /s somestring /i 42 /help")]
74 | [TestCase("somefile /bs /s somestring /i 42 -?")]
75 | public void CorrectlyParsesCommandLineWithHelp(string input)
76 | {
77 | var commandLineParser = CreateCommandLineParser();
78 |
79 | var context = new TestContextWithFile();
80 | var validationContext = commandLineParser.Parse(input, context);
81 |
82 | Assert.That(validationContext.HasErrors, Is.False);
83 | Assert.That(validationContext.HasWarnings, Is.False);
84 |
85 | Assert.That(context.IsHelp, Is.True);
86 | }
87 |
88 | [TestCase]
89 | public void ReturnsRawValuesForNonSpecifiedOptions()
90 | {
91 | var commandLineParser = CreateCommandLineParser();
92 |
93 | var context = new TestContextWithFile();
94 | var validationContext = commandLineParser.Parse("somefile /nonspecified /nonspecified2 somevalue /bs /s somestring /i 42", context);
95 |
96 | Assert.That(context.RawValues["NonSpecified"], Is.EqualTo(string.Empty));
97 | Assert.That(context.RawValues["NonSpecified2"], Is.EqualTo("somevalue"));
98 | }
99 |
100 | [TestCase]
101 | public void ReturnsValidationContextWithErrorsForMissingMandatoryOptions()
102 | {
103 | var commandLineParser = CreateCommandLineParser();
104 |
105 | var context = new TestContextWithMandatoryOption();
106 | var validationContext = commandLineParser.Parse(string.Empty, context);
107 |
108 | Assert.That(validationContext.HasErrors, Is.True);
109 | }
110 |
111 | [TestCase("-something 'some argument' -appcolor \"#FF483FFC\" -appname \"New name\" -headless")]
112 | public void ParsesBrandingContextWithAdditionalNonDefinedOptions(string commandLine)
113 | {
114 | var commandLineParser = CreateCommandLineParser();
115 |
116 | var context = new BrandingCommandLineContext();
117 | var validationContext = commandLineParser.Parse(commandLine, context);
118 |
119 | Assert.That(validationContext.HasErrors, Is.False);
120 | }
121 | #endregion
122 | }
123 |
--------------------------------------------------------------------------------
/deployment/cake/buildserver-continuaci.cake:
--------------------------------------------------------------------------------
1 | public class ContinuaCIBuildServer : BuildServerBase
2 | {
3 | public ContinuaCIBuildServer(ICakeContext cakeContext)
4 | : base(cakeContext)
5 | {
6 | }
7 |
8 | //-------------------------------------------------------------
9 |
10 | public override async Task OnTestFailedAsync()
11 | {
12 | await ImportUnitTestsAsync();
13 | }
14 |
15 | //-------------------------------------------------------------
16 |
17 | public override async Task AfterTestAsync()
18 | {
19 | await ImportUnitTestsAsync();
20 | }
21 |
22 | //-------------------------------------------------------------
23 |
24 | private async Task ImportUnitTestsAsync()
25 | {
26 | foreach (var project in BuildContext.Tests.Items)
27 | {
28 | await ImportTestFilesAsync(project);
29 | }
30 | }
31 |
32 | //-------------------------------------------------------------
33 |
34 | private async Task ImportTestFilesAsync(string projectName)
35 | {
36 | var continuaCIContext = GetContinuaCIContext();
37 | if (!continuaCIContext.IsRunningOnContinuaCI)
38 | {
39 | return;
40 | }
41 |
42 | CakeContext.Warning($"Importing test results for '{projectName}'");
43 |
44 | var testResultsDirectory = System.IO.Path.Combine(BuildContext.General.OutputRootDirectory, "testresults");
45 |
46 | if (!CakeContext.DirectoryExists(testResultsDirectory))
47 | {
48 | CakeContext.Warning("No test results directory");
49 | return;
50 | }
51 |
52 | var type = string.Empty;
53 | var importType = string.Empty;
54 |
55 | if (IsNUnitTestProject(BuildContext, projectName))
56 | {
57 | type = "nunit";
58 | importType = "nunit";
59 | }
60 |
61 | if (IsXUnitTestProject(BuildContext, projectName))
62 | {
63 | type = "xunit";
64 | importType = "mstest"; // Xml type is different
65 | }
66 |
67 | if (string.IsNullOrWhiteSpace(type))
68 | {
69 | CakeContext.Warning("Could not find test project type");
70 | return;
71 | }
72 |
73 | CakeContext.Warning($"Determined project type '{type}'");
74 |
75 | var cakeFilePattern = System.IO.Path.Combine(testResultsDirectory, projectName, "*.xml");
76 |
77 | CakeContext.Warning($"Using pattern '{cakeFilePattern}'");
78 |
79 | var testResultsFiles = CakeContext.GetFiles(cakeFilePattern);
80 | if (!testResultsFiles.Any())
81 | {
82 | CakeContext.Warning($"No test result file found using '{cakeFilePattern}'");
83 | return;
84 | }
85 |
86 | var continuaCiFilePattern = System.IO.Path.Combine(testResultsDirectory, "**.xml");
87 |
88 | CakeContext.Information($"Importing test results from using '{continuaCiFilePattern}' using import type '{importType}'");
89 |
90 | var message = $"@@continua[importUnitTestResults type='{importType}' filePatterns='{cakeFilePattern}']";
91 | WriteIntegration(message);
92 | }
93 |
94 | //-------------------------------------------------------------
95 |
96 | public override async Task PinBuildAsync(string comment)
97 | {
98 | var continuaCIContext = GetContinuaCIContext();
99 | if (!continuaCIContext.IsRunningOnContinuaCI)
100 | {
101 | return;
102 | }
103 |
104 | CakeContext.Information("Pinning build in Continua CI");
105 |
106 | var message = string.Format("@@continua[pinBuild comment='{0}' appendComment='{1}']",
107 | comment, !string.IsNullOrWhiteSpace(comment));
108 | WriteIntegration(message);
109 | }
110 |
111 | //-------------------------------------------------------------
112 |
113 | public override async Task SetVersionAsync(string version)
114 | {
115 | var continuaCIContext = GetContinuaCIContext();
116 | if (!continuaCIContext.IsRunningOnContinuaCI)
117 | {
118 | return;
119 | }
120 |
121 | CakeContext.Information("Setting version '{0}' in Continua CI", version);
122 |
123 | var message = string.Format("@@continua[setBuildVersion value='{0}']", version);
124 | WriteIntegration(message);
125 | }
126 |
127 | //-------------------------------------------------------------
128 |
129 | public override async Task SetVariableAsync(string variableName, string value)
130 | {
131 | var continuaCIContext = GetContinuaCIContext();
132 | if (!continuaCIContext.IsRunningOnContinuaCI)
133 | {
134 | return;
135 | }
136 |
137 | CakeContext.Information("Setting variable '{0}' to '{1}' in Continua CI", variableName, value);
138 |
139 | var message = string.Format("@@continua[setVariable name='{0}' value='{1}' skipIfNotDefined='true']", variableName, value);
140 | WriteIntegration(message);
141 | }
142 |
143 | //-------------------------------------------------------------
144 |
145 | public override Tuple GetVariable(string variableName, string defaultValue)
146 | {
147 | var continuaCIContext = GetContinuaCIContext();
148 | if (!continuaCIContext.IsRunningOnContinuaCI)
149 | {
150 | return new Tuple(false, string.Empty);
151 | }
152 |
153 | var exists = false;
154 | var value = string.Empty;
155 |
156 | var buildServerVariables = continuaCIContext.Environment.Variable;
157 | if (buildServerVariables.ContainsKey(variableName))
158 | {
159 | CakeContext.Information("Variable '{0}' is specified via Continua CI", variableName);
160 |
161 | exists = true;
162 | value = buildServerVariables[variableName];
163 | }
164 |
165 | return new Tuple(exists, value);
166 | }
167 |
168 | //-------------------------------------------------------------
169 |
170 | private IContinuaCIProvider GetContinuaCIContext()
171 | {
172 | return CakeContext.ContinuaCI();
173 | }
174 |
175 | //-------------------------------------------------------------
176 |
177 | private void WriteIntegration(string message)
178 | {
179 | // Must be Console.WriteLine
180 | CakeContext.Information(message);
181 | }
182 | }
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | Contributors
2 | ============
3 |
4 | ## Contributing Process
5 |
6 | ### Get Buyoff Or Find Open Community Issues/Features
7 |
8 | * Through [GitHub](https://github.com/WildGums/Orc.CommandLine/issues), or through the [Chat Room](https://gitter.im/WildGums/Orc.CommandLine) (preferred), you talk about a feature you would like to see (or a bug), and why it should be included.
9 | * If approved through the Chat Room, ensure the accompanying issue is created with information and a link back to the Chat Room discussion.
10 | * Once you get a nod you can start on the feature.
11 |
12 | ### Set Up Your Environment
13 |
14 | * You create, or update, a fork of https://github.com/WildGums/Orc.CommandLine under your GitHub account.
15 | * From there you create a branch named specific to the feature.
16 | * In the branch you do work specific to the feature.
17 | * Please also observe the following:
18 | * No reformatting
19 | * No changing files that are not specific to the feature
20 | * More covered below in the **Prepare commits** section.
21 | * Test your changes and please help us out by updating and implementing some automated tests. It is recommended that all contributors spend some time looking over the tests in the source code. You can't go wrong emulating one of the existing tests and then changing it specific to the behavior you are testing.
22 | * Please do not update your branch from the master unless we ask you to. See the responding to feedback section below.
23 |
24 | ### Prepare Commits
25 |
26 | This section serves to help you understand what makes a good commit.
27 |
28 | A commit should observe the following:
29 |
30 | * A commit is a small logical unit that represents a change.
31 | * Should include new or changed tests relevant to the changes you are making.
32 | * No unnecessary whitespace. Check for whitespace with `git diff --check` and `git diff --cached --check` before commit.
33 | * You can stage parts of a file for commit.
34 |
35 | A commit message should observe the following:
36 |
37 | * The first line of the commit message should be a short description around 50 characters in length and be prefixed with the issue it refers to with parentheses surrounding that. If the issue is #25, you should have `#25` prefixed to the message.
38 | * If the commit is about documentation, the message should be prefixed with `(doc)`.
39 | * If it is a trivial commit or one of formatting/spaces fixes, it should be prefixed with `(maint)`.
40 | * After the subject, skip one line and fill out a body if the subject line is not informative enough.
41 | * The body:
42 | * Should indent at `72` characters.
43 | * Explains more fully the reason(s) for the change and contrasts with previous behavior.
44 | * Uses present tense. "Fix" versus "Fixed".
45 |
46 | A good example of a commit message is as follows:
47 |
48 | ```
49 | #7 Improve initialization performance
50 |
51 | Previously the initialization took 400 ms and had a severe impact
52 | on the startup of an application. This commit brings the initialization
53 | time back to 35 ms.
54 | ```
55 |
56 | ### Submit Pull Request (PR)
57 |
58 | Prerequisites:
59 |
60 | * You are making commits in a feature branch.
61 | * All specs should be passing.
62 |
63 | Submitting PR:
64 |
65 | * Once you feel it is ready, submit the pull request to the `WildGums/Orc.CommandLine` repository against the ````develop```` branch ([more information on this can be found here](https://help.github.com/articles/creating-a-pull-request)).
66 | * In the pull request, outline what you did and point to specific conversations (as in URLs) and issues that you are are resolving. This is a tremendous help for us in evaluation and acceptance.
67 | * Once the pull request is in, please do not delete the branch or close the pull request (unless something is wrong with it).
68 | * One of the Team members, or one of the committers, will evaluate it within a reasonable time period (which is to say usually within 0-2 weeks). Some things get evaluated faster or fast tracked. We are human and we have active lives outside of open source so don't fret if you haven't seen any activity on your pull request within a month or two. We don't have a Service Level Agreement (SLA) for pull requests. Just know that we will evaluate your pull request.
69 |
70 | ### Respond to Feedback on Pull Request
71 |
72 | We may have feedback for you to fix or change some things. We generally like to see that pushed against the same topic branch (it will automatically update the Pull Request). You can also fix/squash/rebase commits and push the same topic branch with `--force` (it's generally acceptable to do this on topic branches not in the main repository, it is generally unacceptable and should be avoided at all costs against the main repository).
73 |
74 | If we have comments or questions when we do evaluate it and receive no response, it will probably lessen the chance of getting accepted. Eventually this means it will be closed if it is not accepted. Please know this doesn't mean we don't value your contribution, just that things go stale. If in the future you want to pick it back up, feel free to address our concerns/questions/feedback and reopen the issue/open a new PR (referencing old one).
75 |
76 | Sometimes we may need you to rebase your commit against the latest code before we can review it further. If this happens, you can do the following:
77 |
78 | * `git fetch upstream` (upstream would be the mainstream repo or `WildGums/Orc.CommandLine` in this case)
79 | * `git checkout develop`
80 | * `git rebase upstream/develop`
81 | * `git checkout your-branch`
82 | * `git rebase develop`
83 | * Fix any merge conflicts
84 | * `git push origin your-branch` (origin would be your GitHub repo or `your-github-username/Orc.CommandLine` in this case). You may need to `git push origin your-branch --force` to get the commits pushed. This is generally acceptable with topic branches not in the mainstream repository.
85 |
86 | The only reasons a pull request should be closed and resubmitted are as follows:
87 |
88 | * When the pull request is targeting the wrong branch (this doesn't happen as often).
89 | * When there are updates made to the original by someone other than the original contributor. Then the old branch is closed with a note on the newer branch this supersedes the issue.
90 |
91 | ## Other General Information
92 |
93 | If you reformat code or hit core functionality without an approval from a person on the Team, it's likely that no matter how awesome it looks afterwards, it will probably not get accepted. Reformatting code makes it harder for us to evaluate exactly what was changed.
94 |
95 | If you do these things, it will be make evaluation and acceptance easy. Now if you stray outside of the guidelines we have above, it doesn't mean we are going to ignore your pull request. It will just make things harder for us. Harder for us roughly translates to a longer SLA for your pull request.
--------------------------------------------------------------------------------
/deployment/cake/aspire-tasks.cake:
--------------------------------------------------------------------------------
1 | #l "aspire-variables.cake"
2 |
3 | using System.Xml.Linq;
4 |
5 | //-------------------------------------------------------------
6 |
7 | public class AspireProcessor : ProcessorBase
8 | {
9 | public AspireProcessor(BuildContext buildContext)
10 | : base(buildContext)
11 | {
12 |
13 | }
14 |
15 | public override bool HasItems()
16 | {
17 | return BuildContext.Aspire.Items.Count > 0;
18 | }
19 |
20 | public override async Task PrepareAsync()
21 | {
22 | if (!HasItems())
23 | {
24 | return;
25 | }
26 |
27 | // Nothing needed
28 | }
29 |
30 | public override async Task UpdateInfoAsync()
31 | {
32 | if (!HasItems())
33 | {
34 | return;
35 | }
36 |
37 | // Nothing needed
38 | }
39 |
40 | public override async Task BuildAsync()
41 | {
42 | if (!HasItems())
43 | {
44 | return;
45 | }
46 |
47 | // Nothing needed
48 | }
49 |
50 | public override async Task PackageAsync()
51 | {
52 | if (!HasItems())
53 | {
54 | return;
55 | }
56 |
57 | var aspireContext = BuildContext.Aspire;
58 |
59 | if (aspireContext.Items.Count > 1)
60 | {
61 | throw new InvalidOperationException("Multiple Aspire projects found. Please ensure only one Aspire project is defined in the solution.");
62 | }
63 |
64 | var environmentName = GetEnvironmentName(aspireContext);
65 |
66 | foreach (var aspireProject in aspireContext.Items)
67 | {
68 | if (BuildContext.General.SkipComponentsThatAreNotDeployable &&
69 | !ShouldPackageProject(BuildContext, aspireProject))
70 | {
71 | CakeContext.Information("Aspire project '{0}' should not be packaged", aspireProject);
72 | continue;
73 | }
74 |
75 | BuildContext.CakeContext.LogSeparator("Packaging Aspire project '{0}'", aspireProject);
76 |
77 | BuildContext.CakeContext.Information("Setting environment variables");
78 |
79 | var environmentVariables = new Dictionary
80 | {
81 | { "AZURE_PRINCIPAL_ID", aspireContext.AzurePrincipalId },
82 | { "AZURE_PRINCIPAL_TYPE", aspireContext.AzurePrincipalType },
83 | { "AZURE_LOCATION", aspireContext.AzureLocation },
84 | { "AZURE_RESOURCE_GROUP", $"rg-{aspireContext.AzureResourceGroup}-{aspireContext.EnvironmentName}" },
85 | { "AZURE_SUBSCRIPTION_ID", aspireContext.AzureSubscriptionId },
86 | { "AZURE_ENV_NAME", aspireContext.EnvironmentName },
87 | };
88 |
89 | foreach (var environmentVariable in environmentVariables)
90 | {
91 | RunAzd($"env set {environmentVariable.Key}=\"{environmentVariable.Value}\" -e {environmentName} --no-prompt");
92 | }
93 |
94 | BuildContext.CakeContext.Information("Generating infrastructure context");
95 |
96 | RunAzd($"infra gen -e {environmentName} --force");
97 |
98 | BuildContext.CakeContext.LogSeparator();
99 | }
100 | }
101 |
102 | public override async Task DeployAsync()
103 | {
104 | if (!HasItems())
105 | {
106 | return;
107 | }
108 |
109 | var aspireContext = BuildContext.Aspire;
110 |
111 | if (aspireContext.Items.Count > 1)
112 | {
113 | throw new InvalidOperationException("Multiple Aspire projects found. Please ensure only one Aspire project is defined in the solution.");
114 | }
115 |
116 | var environmentName = GetEnvironmentName(aspireContext);
117 |
118 | foreach (var aspireProject in aspireContext.Items)
119 | {
120 | if (!ShouldDeployProject(BuildContext, aspireProject))
121 | {
122 | CakeContext.Information("Aspire project '{0}' should not be deployed", aspireProject);
123 | continue;
124 | }
125 |
126 | BuildContext.CakeContext.LogSeparator("Deploying Aspire project '{0}'", aspireProject);
127 |
128 | try
129 | {
130 | BuildContext.CakeContext.Information("Logging in to Azure");
131 |
132 | RunAzd($"auth login --tenant-id {aspireContext.AzureTenantId} --client-id {aspireContext.AzureClientId} --client-secret {aspireContext.AzureClientSecret}");
133 |
134 | // Note: got weird errors when running provision and deploy manually, so using up instead
135 |
136 | BuildContext.CakeContext.Information("Deploying to Azure");
137 |
138 | RunAzd($"up -e {environmentName}");
139 |
140 | //BuildContext.CakeContext.Information("Provisioning infrastructure for Aspire project '{0}'", aspireProject);
141 |
142 | //RunAzd($"provision -e {environmentName}");
143 |
144 | //BuildContext.CakeContext.Information("Deploying Aspire project '{0}'", aspireProject);
145 |
146 | // Note: this could technically be improved in the future by using
147 | // azd deploy 'componentname'
148 |
149 | //RunAzd($"deploy --all -e {environmentName}");
150 |
151 | await BuildContext.Notifications.NotifyAsync(aspireProject, string.Format("Deployed to Azure"), TargetType.AspireProject);
152 | }
153 | finally
154 | {
155 | BuildContext.CakeContext.Information("Logging out of Azure");
156 |
157 | RunAzd($"auth logout");
158 | }
159 |
160 | BuildContext.CakeContext.LogSeparator();
161 | }
162 | }
163 |
164 | public override async Task FinalizeAsync()
165 | {
166 | // Nothing needed
167 | }
168 |
169 | private string GetEnvironmentName(AspireContext aspireContext)
170 | {
171 | // Because resource group names are set: "rg-{environmentName}" by Aspire, we automatically add
172 | // an extra name to the environment
173 |
174 | var environmentName = $"{aspireContext.AzureResourceGroup}-{aspireContext.EnvironmentName}";
175 |
176 | return environmentName;
177 | }
178 |
179 | private void RunAzd(string arguments)
180 | {
181 | if (BuildContext.CakeContext.StartProcess("azd", new ProcessSettings
182 | {
183 | Arguments = arguments
184 | }) != 0)
185 | {
186 | throw new CakeException("Azd failed failed. Please check the logs for more details.");
187 | }
188 | }
189 | }
--------------------------------------------------------------------------------