Git Product home page Git Product logo

dotnet-combine's Introduction

dotnet-combine

GitHub Actions

NuGet

Code coverage Sonar vulnerabilities Sonar bugs Sonar code smells

dotnet-combine is .NET global tool that allows you to:

  • Merge multiple C# source files (.cs) into a single one.
  • Generate a .zip with the specified files within a directory.

Installing dotnet-combine

.NET 6 SDK is required to use this tool. You can download it from here.

The tool can be installed globally by running:

dotnet tool install -g dotnet-combine

More info about installing dotnet tools can be found here.

Once installed, dotnet-combine --help should show you the general options:

  single-file    Combines multiple source code files (.cs) into a single one.

  zip            Zips multiple files.

  help           Display more information on a specific command.

  version        Display version information.

dotnet-combine single-file

dotnet-combine single-file combines multiple C# source files (.cs) into a single, valid one.

This tool, originally inspired by TomKirby/CGCompactor, is handy if you need to submit a single source file somewhere; but you prefer to develop your solution locally using your preferred IDE and structuring it in multiple files.

Some examples are competitive programming contests such as Google Code Jam, CodeChef, CodingGame, etc.

Help for dotnet-combine single-file can be accessed by running:

dotnet-combine single-file --help

Usage: dotnet-combine single-file <INPUT> [options]

  input (pos. 0)     Required.
                     Input path.

  -o, --output       Output path (file or dir).
                     If no dir path is provided (i.e. --output file.cs), the file will be created in the input dir.
                     If no filename is provided (i.e. --output dir/), a unique name will be used.

  -f, --overwrite    (Default: false)
                     Overwrites the output file (if it exists).

  --exclude          (Default: bin/ obj/)
                     Excluded files and directories, separated by semicolons (;).

  -p, --prefix       Prefix for the output file.

  -s, --suffix       Suffix for the output file

  -v, --verbose      (Default: false)
                     Verbose output. Shows combined files, progress, etc.

  --format           (Default: false)
                     Formats output file. Enabling it slows down file generation process.

  --help             Display this help screen.

  --version          Display version information.

dotnet-combine single-file usage examples

If you want to merge the source code of MyAmazingProject.csproj, located in C:/MyAmazingProject, you can simply do:

dotnet-combine single-file C:/MyAmazingProject

That will generated a file under C:/MyAmazingProject/. Since having that file there may conflict with your project compilation, you probably want it to be created somewhere else, let's say, under C:/tmp/. You can use --output for that:

dotnet-combine single-file C:/MyAmazingProject --output C:/tmp/

If you want that output file to have a specific name, you can also provide it:

dotnet-combine single-file C:/MyAmazingProject --output C:/tmp/amazing.cs

The option --override can be used in subsequent runs to replace that file:

dotnet-combine single-file C:/MyAmazingProject --override --output C:/tmp/amazing.cs

If you prefer to keep different versions of your output file, but would still like to identify them, you can use --prefix and/or --suffix together with your output dir in --output:

dotnet-combine single-file C:/MyAmazingProject --output C:/tmp/ --prefix amazing_
dotnet-combine single-file C:/MyAmazingProject --output C:/tmp/ --suffix _amazing

By default, bin/ and obj/ directories are excluded. That can be modified using --exclude:

dotnet-combine single-file C:/MyAmazingProject --output C:/tmp/ --prefix amazing_ --exclude "bin/;obj/;AutogeneratedDir/;AssemblyInfo.cs"

If you want your MyAmazingProject.csproj files to be combined every time you build the project in release mode, you can integrate dotnet-combine single-file as a MsBuild target in your .csproj file:

  <Target Name="dotnet-combine single-file" AfterTargets="Build" DependsOnTargets="Build" Condition="'$(Configuration)' == 'Release' ">
    <Message Importance="high" Text="Running dotnet-combine tool"/>
    <Message Importance="high" Text="dotnet-combine single-file $(MSBuildProjectDirectory) --overwrite --output $(MSBuildProjectDirectory)/bin/ --prefix amazing_ --exclude &quot;bin/;obj/;AutogeneratedDir/;AssemblyInfo.cs&quot;"/>
    <Exec Command="dotnet-combine single-file $(MSBuildProjectDirectory) --overwrite --output $(MSBuildProjectDirectory)/bin/ --prefix amazing_ --exclude &quot;bin/;obj/;AutogeneratedDir/;AssemblyInfo.cs&quot;"/>
  </Target>

dotnet-combine zip

dotnet-combine zip generates a .zip with the specified files within a given directory.

Currently it supports filtering files by extension and excluding both files and directories.

This tool can be used for more general purposes than the previous one. Some of them can be:

  • Extracting all .pdf files from a folder in your hard drive with complex hierarchies that has them mixed up with other files (.docx, .pptx, .jpg, etc.).

  • Extracting all .mp3 files from your mirrored cloud's folder.

  • Extracting all .css files from a web development project.

  • Extracting all the relevant source code files (.sln, .csproj, .cs, .json, .razor, .xaml, etc.) from your .NET project in a GitHub Action step, to be able to make them available as an artifact.

  • ...

Help for dotnet-combine zip can be accessed by running:

dotnet-combine zip --help

Usage: dotnet-combine zip <INPUT> [options]

  input (pos. 0)     Required.
                     Input path (file or dir).

  -o, --output       Output path (file or dir).
                     If no dir path is provided (i.e. --output file.cs), the file will be created in the input
                     directory.
                     If no filename is provided (i.e. --output dir/), a unique name will be used.

  --extensions       (Default: .sln .csproj .cs .json)
                     File extensions to include, separated by semicolons (;).

  -f, --overwrite    (Default: false)
                     Overwrites the output file (if it exists).

  --exclude          (Default: bin/ obj/)
                     Excluded files and directories, separated by semicolons (;).

  -p, --prefix       Prefix for the output file.

  -s, --suffix       Suffix for the output file.

  -v, --verbose      (Default: false)
                     Verbose output. Shows compressed files, progress, etc.

  --help             Display this help screen.

  --version          Display version information.

dotnet-combine zip usage examples

If you want to create a .zip with all the C++ source code in your MyGeekyProject project, located in /home/ed/GeekyProject/, you can simply do:

dotnet-combine zip /home/ed/GeekyProject --extensions ".cpp;cxx:cc;.h;.hpp"

That will generated a file under /home/ed/GeekyProject. If you plan to create .zip files regularly, you may want to place them somewhere else, such as /home/ed/GeekyProject/artifacts/. You can use --output for that:

dotnet-combine zip /home/ed/GeekyProject --extensions ".cpp;cxx:cc;.h;.hpp;" --output /home/ed/GeekyProject/artifacts/

If you want that output file to have a specific name, you can also provide it using --output:

dotnet-combine zip /home/ed/GeekyProject --extensions ".cpp;cxx:cc;.h;.hpp" --output /home/ed/GeekyProject/artifacts/src_v1`

The tool will prevent you from generating another file with the same name unless you use --override (also abbreviated as -f):

dotnet-combine zip /home/ed/GeekyProject -f --extensions ".cpp;cxx:cc;.h;.hpp" --output /home/ed/GeekyProject/artifacts/src_v1

However, you may prefer to keep different versions of your output file without having to worry about specifying different version numbers in the name. You can achieve that by only including a dir path in --output, and making use of --prefix and/or --suffix:

dotnet-combine zip /home/ed/GeekyProject --extensions ".cpp;cxx:cc;.h;.hpp" --prefix geeky- --output /home/ed/GeekyProject/artifacts/

By default, bin/ and obj/ directories are excluded. That can be modified by using --exclude:

dotnet-combine zip /home/ed/GeekyProject --extensions ".cpp;cxx:cc;.h;.hpp;.vcxproj;" --prefix geeky- --output /home/ed/GeekyProject/artifacts/ --exclude "build/;UnwantedFile.h"

If you want to pack your MyGeekyProject source files as part of your GitHub Actions CI pipeline, you can do it like this:

    steps:
    - uses: actions/[email protected]

    - name: Install dotnet-combine locally.
      run: |
        dotnet new tool-manifest
        dotnet tool install dotnet-combine

    - name: Create source code artifact using dotnet-combine.
      run: dotnet dotnet-combine zip . --extensions ".cpp;cxx:cc;.h;.hpp;.vcxproj;" --prefix geeky- --output ./artifacts/ --exclude "build/;UnwantedFile.h"

    - name: Upload source code artifact.
      uses: actions/upload-artifact@v2
      with:
        name: source-code-ci-${{ github.run_number }}
        path: artifacts/
        if-no-files-found: error

Additional notes

  • Although dotnet-combine does support \ path separators in Windows, bear in mind that using them will prevent your commands/targets from being cross-platform.

  • If you want use a suffix that starts with a dash (-), you can do that by using 'double-dash' (--) to indicate the end of options (i.e. dotnet-combine single-file ./MyDir --suffix -- -my-suffix).

Contributing

If you experience difficulties using dotnet-combine, please open an issue detailing what you want to achieve and the command you've tried.

Feature requests are welcome.

PRs are also more than welcome, but feel free to open an issue before carrying out any major changes to avoid any misalignments.

dotnet-combine's People

Contributors

dependabot[bot] avatar eduherminio avatar github-actions[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

dotnet-combine's Issues

Consider changing CLI helper

CommandLineParser doesn't seem as polished as it could be:

  • dotnet combine --version shows the wrong Copyright section.
  • dotnet combine --version shows the options in the wrong order.
  • etc.

Consider moving to Microsoft.Extensions.CommandLineUtils or its fork McMaster.Extensions.CommandLineUtils

Add option to merge namespaces

                [Option(shortName: 'm', longName: "merge-namespaces", Required = false, Default = false, HelpText = @"
        Groups the output code by namespace.")]
                public bool MergeNamespaces { get; set; }

Implement 'properly' using Roslyn.

Remove creation date from file content

If generated files are checked-in into source control and its generation process is automated, changes will always be detected due to the change of that generation time.

Path separation characters have been unified cross-OS to minimize those source-control discrepancies, so it could make sense to also get rid of the creation date.

No extra functionality would be added, since users can already provide a --prefixand a--sufifixand as long as nooutput` is provided, the creation date will be used in the name of the file.

-f appends rather than overwrites

Running this command twice in a row doubles the size of Combined.cs:

dotnet-combine single-file . -o Combined.cs -f --exclude "Tests/;obj/;bin/;AssemblyInfo.cs"

Add support for file scoped namespaces

  • Transform input file scoped namespaces in traditional ones in the output file.

Current behavior:

Errors in the console:

Errors detected in .\src\DotnetCombine\Program.cs:
(7,24): error CS1514: Se esperaba {
(89,2): error CS1513: Se esperaba }
Errors detected in .\src\DotnetCombine\PathHelpers.cs:
(1,24): error CS1514: Se esperaba {
(9,2): error CS1513: Se esperaba }
Errors detected in .\src\DotnetCombine\UniqueIdGenerator.cs:
(1,24): error CS1514: Se esperaba {
(7,2): error CS1513: Se esperaba }
Errors detected in .\src\DotnetCombine\Options\ZipOptions.cs:
(3,32): error CS1514: Se esperaba {
(54,2): error CS1513: Se esperaba }
Errors detected in .\src\DotnetCombine\Services\Combiner.cs:
(5,33): error CS1514: Se esperaba {
(180,2): error CS1513: Se esperaba }

Faulty output file:

// File generated by dotnet-combine at 2022-12-14__01_38_06

using CommandLine;
using CommandLine.Text;
using DotnetCombine.Model;
using DotnetCombine.Options;
using DotnetCombine.Services;
using DotnetCombine.SyntaxRewriters;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.IO.Compression;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text;

namespace DotnetCombine;

[Serializable]
public class CombineException : Exception
{
    public CombineException() : base()
    {
    }

    public CombineException(string? message) : base(message)
    {
    }

    public CombineException(string? message, Exception? innerException) : base(message, innerException)
    {
    }

    protected CombineException(SerializationInfo info, StreamingContext context) : base(info, context)
    {
    }
}


namespace DotnetCombine;

public static class PathHelpers
{
    public static string ReplaceEndingDirectorySeparatorWithProperEndingDirectorySeparator(this string dirPath)
    {
        return Path.TrimEndingDirectorySeparator(dirPath) + Path.DirectorySeparatorChar;
    }
}

Preprocessor directives get ignored when they are at the end of a file

Real-life example:

using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Running;
using System.Reflection;

//Lynx.Benchmark.BitBoard_Struct_ReadonlyStruct_Class_Record.SizeTest();

#if DEBUG
BenchmarkSwitcher.FromAssembly(Assembly.GetExecutingAssembly()).Run(args, new DebugInProcessConfig());
#else
            BenchmarkSwitcher.FromAssembly(Assembly.GetExecutingAssembly()).Run(args);
#endif // ignored

Also: some #pragma warning restore

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.