quino fix
Examples
The following commmand updates the version number to 8.0.1.0 wherever a version is set in the current folder or any contained folders.
quino fix -v 8.0.1.0
The following commmand enables documentation for all projects in the current folder or any contained folders.
quino fix -d true
The following commmand updates nuspec dependencies for all projects in the current folder or any contained folders.
quino fix -s true
There are more examples in the documentation below.
Purpose
.NET projects and sources contain many options and values that should stay in-sync. As a project grows, so too does the effort to maintain these options.
For example,
- .NET projects will target certain frameworks
- Some of those projects will have documentation-generation enabled (e.g. for Swagger)
- Some will be output to a common folder (e.g.
../out
) while web applications should be in their own folder (e.g.bin
). - Each project should include the copyright, product name, company name, etc.
- Source files have a header that should reflect the current year.
Also, build servers and local developers have different requirements. For example,
- Framework packages should include documentation while documentation compiler warnings can be distracting for developers
- Framework packages have very specific versions whereas the version of in-progress code is immaterial
- Dependencies in
.nuspec
files for .NET Framework projects are not automatically updated bynuget
. This doesn't affect local developers, but these dependencies should match those in the project files before packaging.
There are tools to help maintain some of these features. For example, ReSharper helps with file headers and there is a NuGet package and MSBuild support that kind-of updates dependencies in nuspec
files for .NET Framework projects.
However, it's not uncommon for even medium-sized projects to have many options that are out-of-sync. Sometimes these inconsistencies lead to a frustrating loss of time (e.g. when a new project targets an incompatible .NET version or when a NuGet package includes out-of-date dependencies).
Function
Products define rules in a configuration file. These rules include values for options to be applied by fixers (project and source) to one or more filesets . A fileset includes and excludes files and additional options. It may either be processed by default or only when triggered by a condition.
Developers run this tool to "fix" projects and sources to match these rules. The tool works with both .NET Core/Standard and .NET Framework projects.
Configuration
Configuration Files
The tool will load and combine configuration from the following files, in the given order:
{tool}/fix-command.xml
{tool}/fix-command-common.xml
(searches parent folders){tool}/fix-command-common.local.xml
(searches parent folders){current}/fix-command.xml
{current}/fix-command.local.xml
Where {tool}
is the installation folder and {current}
is the folder from which the tool was launched.
Each file may include the following sections:
- Options: key/value pairs
- Projects: One or more filesets to be processed by project fixers
- Sources: One or more filesets to be processed by source fixers
- Filesets: includes, excludes, options and a trigger
Options
A text option with no value is not applied. Set an option to empty (e.g. <header></header
) to prevent fixers from applying that option.
Name | Default Value | Used in | Description |
---|---|---|---|
header |
See below | Sources | Included at the top of source files |
filename |
Current filename | Sources | The name of the file being processed |
year |
Current Year | All Projects, AssemblyInfo files & Sources | |
copyright |
See below | All Projects, AssemblyInfo files & Sources | Copyright notice |
companyName |
Empty | All Projects, AssemblyInfo files & Sources | Company/author of the assembly |
productName |
Empty | All Projects & AssemblyInfo files | Name of the product to which the assembly belongs |
version |
Empty | All Projects & AssemblyInfo files | Semantic version of the product (e.g. d.d.d.d or d.d.d-beta345 ) |
fileVersion |
Empty | All Projects & AssemblyInfo files | File version of the product (e.g. d.d.d.d ) |
description |
Empty | All Projects & AssemblyInfo files | Description of the assembly |
outputFolder |
Empty | All Projects | relative path to the output folder |
targetFramework |
Empty | All Projects | The target framework to use |
languageVersion |
Empty | All Projects | The maximum C# language version to use |
documentationEnabled |
false |
All Projects | If true , the documentation file is set up to be generated |
titleEnabled |
true |
All Projects & AssemblyInfo files | If true , the name of the assembly is updated to match the name of the project |
packageProjectUrl |
Empty | .NET Core/Standard Projects | URL to the project home page |
packageIconUrl |
Empty | .NET Core/Standard Projects | URL to the icon to use in NuGet |
repositoryType |
Empty | .NET Core/Standard Projects | The type of repository (e.g. "git") |
repositoryUrl |
Empty | .NET Core/Standard Projects | URL to the repository |
packageLicenseUrl |
Empty | .NET Core/Standard Projects | URL to the license file |
clsCompliant |
Empty | AssemblyInfo files | Controls the value of the assembly attribute |
toolsVersion |
Empty | .NET Framework Projects | The tools version to use (e.g. "15.0") |
nuspecDependenciesEnabled |
false |
.NET Framework Projects | If true , the dependencies in nuspec files are updated from the project |
Default Values
Copyright
Copyright (c) {year} {companyName}. All rights reserved.
Header
// <copyright file="{filename}" company="{companyName}">
// Copyright (c) {year} {companyName}. All rights reserved.
// </copyright>
// <license>
// This file is subject to the terms and conditions defined in the 'LICENSE' file.
// </license>
Template Variables
Any of the configuration options can be referenced in any of the others using, e.g. {Option}
.
The default value for the Copyright
shown above references the Year
and CompanyName
.
Cycles are disallowed for obvious reasons.
Year-handling
Wherever the fixer uses the year
, it incorporates an existing year (e.g. in a copyright notice in a header or project).
For example, assume that year
is set to 2018. The fixer converts the year as follows.
Current value | New value |
---|---|
2018 |
2018 |
2015 |
2015-2018 |
2015-2017 |
2015-2018 |
2015-2018 |
2015-2018 |
Filesets
A fileset can include and exclude one or more patterns. It can also override _options and set up a trigger.
include
: includes the files matching the glob pattern in the filesetexclude
: excludes the files matching the glob pattern from the filesetoptions
: defines additional options to apply only with this filesettrigger
: indicates that this fileset should only be applied when the given trigger is activated
Glob patterns
See Microsoft's glob-syntax documentation for a description of all options. The examples below should provide a good overview.
Pattern | Description | Example |
---|---|---|
**/*.csproj |
Any project in any sub-folder of the current folder | libs/A/A.csproj |
tests/**/Expectations/** |
Any file in any sub-folder of a folder named Expectations found in one or more sub-folders of tests |
tests/A/B/Expectations/C/D/readme.txt |
libs/**/*.csproj |
Any project in any sub-folder of libs |
libs/A/A.csproj |
**/*.Designer.cs |
Any file ending in .Designer.cs in any sub-folder of the current folder |
libs/A.Designer.cs |
libs/A/A.csproj |
A single file (exact match) | libs/A/A.csproj |
libs/A/*/*B.cs |
Any file ending in B.cs in any single sub-folder of libs/A |
libs/A/B/B.cs |
Glob Example
The example below sets up the default patterns for sources in Quino-based projects. It includes all files but those in TestData
and Expectations
folders.
<sources>
<default>
<include>**/*.cs</include>
<exclude>**/TestData/**"</exclude>
<exclude>**/Expectations/**"</exclude>
</default>
</sources>
Using a trigger
A fileset can set a trigger to indicate that it should only be applied when that trigger is activated. The following triggers are supported:
Name | Command-line Option |
---|---|
docs | -d or --docs |
nuspec | -s or --nuspec |
Trigger usage
The following example comes from the default configuration. It enables documentation-generation for all projects in the libs
folder when the docs
trigger is activated.
<docs>
<trigger>docs</trigger>
<include>libs/**/*.csproj</include>
<options>
<documentationEnabled>true</documentationEnabled>
</options>
</docs>
Setting Triggers
Instead of using a command-line option, a configuration can also activate a trigger in the configuration.
Trigger-setting Example
The following example changes the default value of both triggers to true
.
<triggers>
<docs>true</docs>
<nuspec>true</docs>
</triggers>
Though triggers are not active by default, a product can also use this mechanism to deactivate triggers activated in default configuration files.
Command line
If the application is executed without a command line, then it does the following:
- If there is a
fix-command.xml
file in the current folder, it will load all configurations and apply all fixers for all default and triggered filesets - Otherwise, it aborts with an error message.
Additionally, the command can be controlled with the following parameters.
Name | Values/Example | Description |
---|---|---|
-h , --help |
Shows the full command-line help | |
-v , --version |
d.d.d.d or d.d.d-beta |
Sets the base version to use; used to calculate the value of version and fileVersion |
-b , --branch |
feature/fixes or release/6 |
Use with -n instead of -v ; used to calculate the value of version and fileVersion |
-n , --buildNumber |
345 |
Use with -b instead of -v ; used to calculate the value of version and fileVersion |
-d , --docs |
true /false |
Sets the docs trigger to the given value |
-s , --nuspec |
true /false |
Sets the nuspec trigger to the given value |
-tc , --teamcity |
Indicates that the tool should emit TeamCity-compatible output |
If there is no configuration in the current folder, then the user must pass at least one of -h
, -v
, -b
/-n
, -d
or -s
.
Command-line Examples
Set version directly
dotnet quinofix -v 6.1.0.0
You can also set a pre-release version, but then you need to provide a build number.
dotnet quinofix -v 6.1.0-beta1 -n 2345
The calculated version numbers are:
version
:6.1.0-beta1x2345
fileVersion
:6.1.0.2345
Set version from branch and build number
The command has logic to generate version numbers from command-line arguments. An external source (like a build server) provides the branch name and the build number and the tool creates and sets version information accordingly.
Any non-release branch will produce a pre-release version. See examples below.
dotnet quinofix -b feature/beta -n 3324 -tc -d -s
Assuming a current version number of 6.1.0.0
, the calculated version numbers are:
version
:6.1.0-beta3324
fileVersion
:6.1.0.3324
TeamCity integration
Pass the -tc
flag to echo the calculated version to the command line so that TeamCity picks it up as the name of the build.
The following shows an example of the echo text.
##teamcity[buildNumber '6.1.0.2345']
CI Example
Assuming a current version number of 6.1.0.0
, the command below does the following:
- Sets the version number to be
6.1.0-beta3324
- Generates TeamCity output
- Sets the
docs
trigger (triggering associated filesets) - Sets the
nuspec
trigger (triggering associated filesets)
dotnet quinofix -b feature/beta -n 3324 -tc -d -s
The following text is echoed.
##teamcity[buildNumber '6.1.0-beta3324']
Assuming a current version number of 6.1.0.0
, the command below does the following:
- Sets the version number to be
6.1.0.3324
- Generates TeamCity output
- Sets the
docs
trigger (triggering associated filesets) - Sets the
nuspec
trigger (triggering associated filesets)
dotnet quinofix -b release/6 -n 3324 -tc -d -s
The following text is echoed.
##teamcity[buildNumber '6.1.0.3324']
Project and file properties
The tool updates the following project and file properties.
Projects
Project Property | Option | Projects |
---|---|---|
Version |
version |
.NET Core/Standard |
AssemblyVersion |
fileVersion |
.NET Core/Standard |
FileVersion |
fileVersion |
.NET Core/Standard |
Authors |
companyName |
.NET Core/Standard |
Product |
productName |
.NET Core/Standard |
AssemblyName |
Name of project if titleEnabled is true |
.NET Core/Standard |
TargetFramework |
targetFramework |
.NET Core/Standard |
PackageLicenseUrl |
packageLicenseUrl |
.NET Core/Standard |
RepositoryUrl |
repositoryUrl |
.NET Core/Standard |
RepositoryType |
repositoryType |
.NET Core/Standard |
PackageIconUrl |
packageIconUrl |
.NET Core/Standard |
PackageProjectUrl |
packageProjectUrl |
.NET Core/Standard |
ToolsVersion |
toolsVersion |
.NET Framework |
TargetFrameworkVersion |
targetFramework |
.NET Framework |
CodeAnalysisRuleset |
codeAnalysisRuleset |
All |
LangVersion |
languageVersion |
All |
AssemblyInfo.cs
Files
Properties in the AssemblyInfo.cs
file will be adjusted, but not added.
Assembly Attribute | Option | Projects |
---|---|---|
CLSCompliant |
CLSCompliant |
All |
AssemblyTitle |
Name of project if titleEnabled is true |
.NET Framework |
AssemblyDescription |
description |
.NET Framework |
AssemblyCompany |
companyName |
.NET Framework |
AssemblyProduct |
productName |
.NET Framework |
AssemblyCopyright |
copyright |
.NET Framework |
AssemblyVersion |
fileVersion |
.NET Framework |
AssemblyFileVersion |
fileVersion |
.NET Framework |
AssemblyInformationalVersion |
version |
.NET Framework |
Full Examples
The following example shows the default configuration delivered with the fix command.
- Sets default values for
copyright
andheader
- Sets up project fixers
default
: processes all projects except expectations and test-datadocs
: indicates for which projects to enable documentation if triggered by 'docs'nuspec
: indicates to which projects to update dependencies if triggered by 'nuspec'
- Sets up source fixers
default
: processes all sources except designer files, expectations and test-data
<?xml version="1.0" encoding="utf-8" ?>
<config>
<options>
<copyright>Copyright (c) {Year} {CompanyName}. All rights reserved.</copyright>
<header><![CDATA[
// <copyright file="{FileName}" company="{Company}">
// Copyright (c) {Year} {Company}. All rights reserved.
// </copyright>
// <license>
// This file is subject to the terms and conditions defined in the 'LICENSE' file.
// </license>
]]></header>
</options>
<projects>
<default>
<include>**/*.csproj</include>
<exclude>tests/**/Expectations/**</exclude>
<exclude>tests/**/TestData/**</exclude>
</default>
<docs>
<trigger>docs</trigger>
<include>libs/**/*.csproj</include>
<options>
<documentationEnabled>true</documentationEnabled>
</options>
</docs>
<nuspec>
<trigger>nuspec</trigger>
<include>**/*.nuspec</include>
<options>
<nuspecDependenciesEnabled>true</nuspecDependenciesEnabled>
</options>
</nuspec>
</projects>
<sources>
<default>
<include>**/*.cs</include>
<exclude>**/*.Designer.cs"</exclude>
<exclude>**/TestData/**"</exclude>
<exclude>**/Expectations/**"</exclude>
</default>
</sources>
</config>
The following example shows the customizations for Quino-Standard.
- Sets up default values for nearly all options
- Sets up project fixers
- Redefines the
default
fileset to exclude more files - Uses a different target framework and output path in
/utils
- Uses a different target framework for a few specific projects
- Redefines the
- Sets up source fixers
- Redefines the
default
fileset to exclude more files
- Redefines the
<?xml version="1.0" encoding="utf-8" ?>
<config>
<options>
<version>6.0.3.0</version>
<companyName>Encodo Systems AG</companyName>
<productName>Quino Metadata Framework</productName>
<description>Quino Metadata Framework Component</description>
<packageProjectUrl>https://encodo.com/quino/</packageProjectUrl>
<packageIconUrl>https://secure.encodo.ch/nuget/quino_logo.png</packageIconUrl>
<repositoryType>Git</repositoryType>
<repositoryUrl>https://github.com/encodo/quino-standard</repositoryUrl>
<packageLicenseUrl>https://github.com/encodo/quino-standard/blob/master/LICENSE</packageLicenseUrl>
<outputFolder>..\..\..\out</outputFolder>
<targetFramework>netstandard2.0</targetFramework>
<toolsVersion>15.0</toolsVersion>
<languageVersion>7</languageVersion>
<clsCompliant>true</clsCompliant>
<documentationEnabled>false</documentationEnabled>
</options>
<projects>
<default>
<include>**/*.csproj</include>
<exclude>tests/**/Expectations/**</exclude>
<exclude>tests/**/TestData/**</exclude>
<exclude>utils/**</exclude>
<exclude>libs/Encodo.Compiler.CSharp/Encodo.Compiler.CSharp.csproj</exclude>
<exclude>libs/Encodo.Compiler.Tests/Encodo.Compiler.Tests.csproj</exclude>
<exclude>libs/Quino.CodeGenerator.Tests/Quino.CodeGenerator.Tests.csproj</exclude>
</default>
<utils>
<include>utils/**/*.csproj</include>
<options>
<targetFramework>netstandard2.1</targetFramework>
<outputPath>../../../out/utils</outputPath>
</options>
</utils>
<legacy>
<include>libs/Encodo.Compiler.CSharp/Encodo.Compiler.CSharp.csproj</include>
<include>libs/Encodo.Compiler.Tests/Encodo.Compiler.Tests.csproj</include>
<include>libs/Quino.CodeGenerator.Tests/Quino.CodeGenerator.Tests.csproj</include>
<options>
<targetFramework>v4.6.2</targetFramework>
</options>
</legacy>
</projects>
<sources>
<default>
<include>**/*.cs</include>
<exclude>**/*.Designer.cs"</exclude>
<exclude>**/TestData/**"</exclude>
<exclude>**/Expectations/**"</exclude>
<exclude>libs/Encodo.Parsers.Antlr/*/*GrammarLexer.cs"</exclude>
<exclude>libs/Encodo.Parsers.Antlr/*/*GrammarParser.cs"</exclude>
<exclude>libs/Quino.Parsers.Antlr/*/*GrammarLexer.cs"</exclude>
</default>
</sources>
</config>