Skip to content

Comments

Add --delete-source option and interactive prompt to project convert#52802

Open
Copilot wants to merge 10 commits intorelease/10.0.3xxfrom
copilot/fix-old-cs-file-issue
Open

Add --delete-source option and interactive prompt to project convert#52802
Copilot wants to merge 10 commits intorelease/10.0.3xxfrom
copilot/fix-old-cs-file-issue

Conversation

Copy link
Contributor

Copilot AI commented Feb 3, 2026

dotnet project convert copies the source file to the new project directory but leaves the original file. Users expect "convert" to move the file, not duplicate it.

Changes

  • New --delete-source flag: Explicitly deletes source file after successful conversion
  • Interactive prompt: When --interactive is enabled without --delete-source, prompts user via Spectre.Console selection to choose whether to delete the source file
  • Backward compatible: Default behavior unchanged (source file preserved)
  • Dry-run support: Shows deletion preview with --dry-run --delete-source
  • Scripting support: --interactive=false explicitly disables all prompts for reliable scripting
  • Migrated output directory prompt to Spectre.Console: Both prompts now use Spectre.Console for consistent UX

Behavior

# Default - source file preserved (existing behavior)
dotnet project convert hello.cs

# Explicit deletion
dotnet project convert hello.cs --delete-source
# Output: Deleted source file: /path/to/hello.cs

# Interactive mode prompts user for both output directory and source deletion
dotnet project convert hello.cs --interactive
# Prompts for output directory, then: "Delete the source file 'hello.cs' after conversion?"
#   > Yes - delete the source file
#     No - keep the source file

# Scripting - explicitly disable prompts
dotnet project convert hello.cs --interactive=false
# No prompts, uses defaults, preserves source file

Implementation Notes

  • Only the entry point file is deleted when --delete-source is used; other default files (e.g., appsettings.json, Util.cs) are preserved
  • Interactive prompts use Spectre.Console with localized choice strings
  • Falls back gracefully if Spectre.Console fails (e.g., unsupported terminal)
  • All user-facing strings added to resource files for localization
  • The --interactive option now accepts boolean arguments (--interactive=true/false) for explicit control in scripts
  • Tests cover all scenarios: explicit flag, non-interactive default, dry-run, custom output, and default files
Original prompt

This section details on the original issue you should resolve

<issue_title>Converting file-based app to project-based app does not get rid of old .cs file</issue_title>
<issue_description>### Steps to repro

  1. Open VSC Insiders
  2. Create folder/workspace
  3. Create hello.cs
  4. Add any code and save
  5. Run dotnet project convert hello.cs

Actual

Project gets created but the old file remains

Image

Expectation

That the project be converted aka the old file should just be moved

Note: In chatting with @DamianEdwards he did mention this choice was originally made to prevent data loss since the action is destructive, but I really did not expect the file to remain, especially since this action is called a "conversion", not "copy as project" for example. It really feels like a bug. At a minimum hopefully the command can ask a secondary question after I input the target directory if I want to remove the old file if you want it to remain interactive or command can have args that i can pass to do this automatically

Environment Info

.NET SDK: (10.0.100-rc.2.25468.101)
VS Code Insiders: 1.105.0-insider
C# Dev Kit Extension: V 1.61.12
C# Extension: V 2.92.18</issue_description>

<agent_instructions>Can you add a command-line argument and an interactive prompt to dotnet project convert that will ask what to do with the original file (copy or move it)? If the command-line option is specified, don't display the prompt (I think that's similar to what we do for --output now). Consider also using Spectre for that interactivity since it's now available in the repo (also migrate the "output" prompt to Spectre if not already).</agent_instructions>

Comments on the Issue (you are @copilot in this section)

@DamianEdwards In the original issue to make `dotnet project convert` interactive, #49624, the detail said to include a question about whether to ask the user whether the original files should be deleted or not and support an option to force it to copy or move, but I'm not seeing that question get asked when I try this myself (which matches the report). There was also some discussion about it in the PR https://github.com//pull/49584#pullrequestreview-2983961087

@jjonescz do you recall why we didn't add the question about copy or moving files as part of convert? Did we just want to wait for feedback?

@jjonescz Yes, the option was confusing, so we removed it. See https://github.com//pull/49660#discussion_r2198099055 where you suggested that :) @DamianEdwards Lol awesome, seems folks found the question confusing so we opted to remove it and let the user delete the files for now. If we get repeated feedback that folks want the files deleted we can revisit, or we could consider adding an option like `--delete-source-files` to allow folks to do it in one command easily. @claudiaregio We are running user testing on this this week so I'll hopefully get some feedback on it, another thing worth considering (and this would be a tooling thing but I dont want to lose the thought) is potentially changing focus to the new file in the project once the conversion is complete. @claudiaregio @DamianEdwards @jjonescz is there any update on whether this can/will be implemented? In user testing they were 50/50 split on whether old project should be destroyed or kept so i think having the parameters that gives the choice would be good @jjonescz We can easily add a parameter (or interactive prompt) but there is some complexity about what this should apply to - just the `file.cs` or other included default items too (like `file.run.json`, `resources.resx`, or even `util.cs` once we have multi-file support)?

Perhaps we could start with just the entrypoint file.</comment_new>


💡 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 changed the title [WIP] Fix issue with leftover .cs file during project conversion Add --delete-source option and interactive prompt to project convert Feb 3, 2026
Copilot AI requested a review from jjonescz February 3, 2026 12:25
@jjonescz jjonescz added the Area-run-file Items related to the "dotnet run <file>" effort label Feb 3, 2026
…ts, migrate to Spectre.Console, add tests with default files

Co-authored-by: jjonescz <[email protected]>
Copilot AI requested a review from jjonescz February 3, 2026 13:38
Copilot AI requested a review from jjonescz February 3, 2026 14:02
Copilot AI requested a review from jjonescz February 3, 2026 14:21
Copilot AI requested a review from jjonescz February 3, 2026 14:42
@jjonescz
Copy link
Member

@333fred @RikkiGibson for reviews, thanks

@RikkiGibson
Copy link
Member

Will try to take a look tomorrow.

}

// Handle deletion of source file if requested.
bool shouldDelete = _deleteSource || TryAskForDeleteSource(file);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels confusing/limiting that, to prevent an interactive behavior, the user must specify to delete the source file. They can't specify to keep the source file in a scripting scenario.

Perhaps the command should accept something like --delete-source=false in addition to --delete-source. I'm not 100% up to speed on the best practices for CLI arguments like these.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The System.CommandLine framework used in this codebase doesn't support --flag=false syntax for boolean options with ArgumentArity.Zero (confirmed by testing and examining all other boolean options in the codebase). All boolean flags in the SDK follow this pattern - they're either present (true) or absent (false).

For scripting scenarios where users want to explicitly prevent interactive prompts:

  • Use --interactive=false is not supported
  • Instead, simply omit the --interactive flag (default is non-interactive)
  • The default behavior (no --delete-source, no --interactive) already keeps the source file without prompting

This matches the convention used throughout the .NET CLI for all boolean flags.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead, simply omit the --interactive flag (default is non-interactive)

it’s not clear to me that this is true. The command line help doesn’t report this, and, it’s not obvious that this would be the case in a script running on a local user machine.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, Rikki is right, the default for --interactive is different in CI and elsewhere, see this in CommonOptions.cs:

DefaultValueFactory = (ar) => !IsCIEnvironmentOrRedirected(),

But it looks like we can create an interactive option that accepts an argument - could we perhaps use that version of the interactive option in the project convert command?

@copilot

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in commit 5b38917. Changed InteractiveOption to use CreateInteractiveOption(acceptArgument: true) which allows --interactive=false in scripting scenarios.

The --interactive option now accepts a boolean argument (ArgumentArity.ZeroOrOne), so users can explicitly specify:

  • --interactive or --interactive=true to force interactive mode
  • --interactive=false to explicitly disable interactive prompts in scripts
  • No flag: defaults based on CI detection (true on local machines, false in CI/redirected output)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area-run-file Items related to the "dotnet run <file>" effort

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants