Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 18, 2025

Thanks for asking me to work on this. I will get started on it and keep this PR's description up to date as I form a plan and make progress.

Original prompt

Problem

Currently the CLI provides a "dotnet sln migrate" command which converts legacy .sln files to the newer .slnx format (see src/Cli/dotnet/Commands/Solution/Migrate/SolutionMigrateCommand.cs). There is no command to go the other direction (export or convert a .slnx back to a traditional .sln). Users who work with tooling that requires the old .sln format cannot easily obtain one from a .slnx.

Goal

Add a new "export" subcommand under the existing "dotnet solution" / "dotnet sln" command that converts a .slnx file into a .sln file. The command should:

  • Be invocable as either "dotnet solution export [<SLNX_FILE>]" or "dotnet sln export [<SLNX_FILE>]" (i.e. alias matches solution command behavior).
  • Accept either a path to a .slnx file or a directory (in which case it should find a .slnx file at or above the provided path, consistent with existing behavior used by post actions).
  • Fail fast with a clear, graceful error if the input file is already a .sln (or if there is no .slnx found).
  • Write a .sln file in the same directory with the same base name (change extension to .sln) and report success to the user.
  • Mirror the error handling and reporting style of SolutionMigrateCommand (use GracefulException and IReporter).

Files to add/modify

  1. New parser for the subcommand
  • src/Cli/dotnet/Commands/Solution/Export/SolutionExportCommandParser.cs
    • Similar structure to SolutionMigrateCommandParser (if present) or SolutionCommandParser. It should hook into the solution command in SolutionCommandParser.cs by registering the new subcommand. The parser must expose an Argument for the SLN argument that defaults to current directory (reuse SolutionCommandParser.SlnArgument if appropriate).
  1. New command implementation
  • src/Cli/dotnet/Commands/Solution/Export/SolutionExportCommand.cs
    • Class implementing CommandBase (following pattern in SolutionMigrateCommand.cs / MSBuildCommand.cs) with a Run/Execute method that:
      • Resolves the incoming path to a solution file using SlnFileFactory.GetSolutionFileFullPath (used by Migrate) or similar helper.
      • If the resolved file has extension ".sln" throw GracefulException with message (e.g. CliCommandStrings.CannotExportSln)
      • If the resolved file has extension ".slnx", read the slnx into SolutionModel using SlnFileFactory.CreateFromFileOrDirectory(filePath) or a suitable factory function.
      • Serialize the model into a .sln file format. If repository already has a serializer for text .sln files, reuse it (e.g., SolutionSerializers.Sln or similar). If not available, implement a small serializer that writes equivalent .sln text output from SolutionModel (follow patterns in SolutionSerializers.SlnXml.SaveAsync used by Migrate but in reverse).
      • Write the .sln file to disk (Path.ChangeExtension to .sln) and report success using IReporter.
      • Return exit code 0 on success; map exceptions to GracefulException as in SolutionMigrateCommand.
  1. Tests
  • test/dotnet.Tests/CommandTests/Solution/Export/GivenDotnetSlnExport.cs
    • Unit/command tests modeled after test/dotnet.Tests/CommandTests/Solution/Add/GivenDotnetSlnAdd.cs and any existing migrate tests. Tests should cover:
      • Export help text
      • Exporting from a directory that contains .slnx
      • Exporting by directly specifying a .slnx path
      • Error when specifying a .sln as input
      • Output sln content matches expected sample
  1. Documentation
  • Update documentation/manpages/sdk/dotnet-sln.1 to include the new "export" subcommand usage and short description.

Implementation notes and references

  • See existing solution command parser and migrate command:
    • src/Cli/dotnet/Commands/Solution/SolutionCommandParser.cs
    • src/Cli/dotnet/Commands/Solution/Migrate/SolutionMigrateCommand.cs
  • Use SlnFileFactory.GetSolutionFileFullPath and SlnFileFactory.CreateFromFileOrDirectory for locating and loading the solution model (used by migrate and new-post action processors already).
  • For serialization, search for existing text-based Sln serializer in the repo (SolutionSerializers.*). If a ready-made serializer exists, reuse it; otherwise implement an SlnText serializer that generates the canonical .sln text layout from SolutionModel. Try to keep the generated .sln compatible with Visual Studio and tooling; tests will verify correctness for covered scenarios.

Acceptance criteria

  • New "dotnet sln export" command appears under "dotnet sln" commands and prints help.
  • Running "dotnet sln export " produces a .sln file with the same base name in the same folder and returns exit code 0.
  • Running the command with a directory containing a single .slnx finds it and exports the .sln.
  • Appropriate error messages are shown when input is invalid or conversion fails.
  • Tests added and passing locally.

Notes

  • This problem description intentionally leaves the exact serializer implementation flexible. If a robust serializer for .sln text already exists in the repo, prefer reusin...

This pull request was created as a result of the following prompt from Copilot chat.

Problem

Currently the CLI provides a "dotnet sln migrate" command which converts legacy .sln files to the newer .slnx format (see src/Cli/dotnet/Commands/Solution/Migrate/SolutionMigrateCommand.cs). There is no command to go the other direction (export or convert a .slnx back to a traditional .sln). Users who work with tooling that requires the old .sln format cannot easily obtain one from a .slnx.

Goal

Add a new "export" subcommand under the existing "dotnet solution" / "dotnet sln" command that converts a .slnx file into a .sln file. The command should:

  • Be invocable as either "dotnet solution export [<SLNX_FILE>]" or "dotnet sln export [<SLNX_FILE>]" (i.e. alias matches solution command behavior).
  • Accept either a path to a .slnx file or a directory (in which case it should find a .slnx file at or above the provided path, consistent with existing behavior used by post actions).
  • Fail fast with a clear, graceful error if the input file is already a .sln (or if there is no .slnx found).
  • Write a .sln file in the same directory with the same base name (change extension to .sln) and report success to the user.
  • Mirror the error handling and reporting style of SolutionMigrateCommand (use GracefulException and IReporter).

Files to add/modify

  1. New parser for the subcommand
  • src/Cli/dotnet/Commands/Solution/Export/SolutionExportCommandParser.cs
    • Similar structure to SolutionMigrateCommandParser (if present) or SolutionCommandParser. It should hook into the solution command in SolutionCommandParser.cs by registering the new subcommand. The parser must expose an Argument for the SLN argument that defaults to current directory (reuse SolutionCommandParser.SlnArgument if appropriate).
  1. New command implementation
  • src/Cli/dotnet/Commands/Solution/Export/SolutionExportCommand.cs
    • Class implementing CommandBase (following pattern in SolutionMigrateCommand.cs / MSBuildCommand.cs) with a Run/Execute method that:
      • Resolves the incoming path to a solution file using SlnFileFactory.GetSolutionFileFullPath (used by Migrate) or similar helper.
      • If the resolved file has extension ".sln" throw GracefulException with message (e.g. CliCommandStrings.CannotExportSln)
      • If the resolved file has extension ".slnx", read the slnx into SolutionModel using SlnFileFactory.CreateFromFileOrDirectory(filePath) or a suitable factory function.
      • Serialize the model into a .sln file format. If repository already has a serializer for text .sln files, reuse it (e.g., SolutionSerializers.Sln or similar). If not available, implement a small serializer that writes equivalent .sln text output from SolutionModel (follow patterns in SolutionSerializers.SlnXml.SaveAsync used by Migrate but in reverse).
      • Write the .sln file to disk (Path.ChangeExtension to .sln) and report success using IReporter.
      • Return exit code 0 on success; map exceptions to GracefulException as in SolutionMigrateCommand.
  1. Tests
  • test/dotnet.Tests/CommandTests/Solution/Export/GivenDotnetSlnExport.cs
    • Unit/command tests modeled after test/dotnet.Tests/CommandTests/Solution/Add/GivenDotnetSlnAdd.cs and any existing migrate tests. Tests should cover:
      • Export help text
      • Exporting from a directory that contains .slnx
      • Exporting by directly specifying a .slnx path
      • Error when specifying a .sln as input
      • Output sln content matches expected sample
  1. Documentation
  • Update documentation/manpages/sdk/dotnet-sln.1 to include the new "export" subcommand usage and short description.

Implementation notes and references

  • See existing solution command parser and migrate command:
    • src/Cli/dotnet/Commands/Solution/SolutionCommandParser.cs
    • src/Cli/dotnet/Commands/Solution/Migrate/SolutionMigrateCommand.cs
  • Use SlnFileFactory.GetSolutionFileFullPath and SlnFileFactory.CreateFromFileOrDirectory for locating and loading the solution model (used by migrate and new-post action processors already).
  • For serialization, search for existing text-based Sln serializer in the repo (SolutionSerializers.*). If a ready-made serializer exists, reuse it; otherwise implement an SlnText serializer that generates the canonical .sln text layout from SolutionModel. Try to keep the generated .sln compatible with Visual Studio and tooling; tests will verify correctness for covered scenarios.

Acceptance criteria

  • New "dotnet sln export" command appears under "dotnet sln" commands and prints help.
  • Running "dotnet sln export " produces a .sln file with the same base name in the same folder and returns exit code 0.
  • Running the command with a directory containing a single .slnx finds it and exports the .sln.
  • Appropriate error messages are shown when input is invalid or conversion fails.
  • Tests added and passing locally.

Notes

  • This problem description intentionally leaves the exact serializer implementation flexible. If a robust serializer for .sln text already exists in the repo, prefer reusing it. If not, implement a minimal serializer sufficient for test assets and common scenarios.

References (files found during discovery):

Please open a pull request implementing the above in the dotnet/sdk repository. Include the new command, tests, and documentation changes. If you want, I can also produce a proposed patch (diff) for the new files and modifications — tell me if you want me to attach actual code for the new parser/command and tests, and I will generate the change set in the PR.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI self-assigned this Nov 18, 2025
Copilot stopped work on behalf of tomlm due to an error November 18, 2025 22:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant