Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -939,6 +939,9 @@ If not specified the file will be generated inside the default 'TestResults' dir
<data name="ProjectConvertDryRun" xml:space="preserve">
<value>Determines changes without actually modifying the file system</value>
</data>
<data name="ProjectConvertDeleteSource" xml:space="preserve">
<value>Delete the source file after conversion</value>
</data>
<data name="ProjectManifest" xml:space="preserve">
<value>PROJECT_MANIFEST</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ internal sealed class ProjectConvertCommandDefinition : Command
Arity = ArgumentArity.Zero,
};

public readonly Option<bool> DeleteSourceOption = new("--delete-source")
{
Description = CommandDefinitionStrings.ProjectConvertDeleteSource,
Arity = ArgumentArity.Zero,
};

public ProjectConvertCommandDefinition()
: base("convert", CommandDefinitionStrings.ProjectConvertAppFullName)
{
Expand All @@ -42,5 +48,6 @@ public ProjectConvertCommandDefinition()
Options.Add(ForceOption);
Options.Add(InteractiveOption);
Options.Add(DryRunOption);
Options.Add(DeleteSourceOption);
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions src/Cli/dotnet/Commands/CliCommandStrings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,24 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man
<value>Dry run: would create file: {0}</value>
<comment>{0} is the file full path.</comment>
</data>
<data name="ProjectConvertAskDeleteSource" xml:space="preserve">
<value>Delete the source file '{0}' after conversion?</value>
<comment>{0} is the source file path.</comment>
</data>
<data name="ProjectConvertDeletedSourceFile" xml:space="preserve">
<value>Deleted source file: {0}</value>
<comment>{0} is the source file path.</comment>
</data>
<data name="ProjectConvertWouldDeleteSourceFile" xml:space="preserve">
<value>Dry run: would delete source file: {0}</value>
<comment>{0} is the source file path.</comment>
</data>
<data name="ProjectConvertDeleteSourceChoiceYes" xml:space="preserve">
<value>Yes - delete the source file</value>
</data>
<data name="ProjectConvertDeleteSourceChoiceNo" xml:space="preserve">
<value>No - keep the source file</value>
</data>
<data name="ProjectsHeader" xml:space="preserve">
<value>Project(s)</value>
</data>
Expand Down
49 changes: 49 additions & 0 deletions src/Cli/dotnet/Commands/Project/Convert/ProjectConvertCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.FileBasedPrograms;
using Microsoft.DotNet.ProjectTools;
using Spectre.Console;

namespace Microsoft.DotNet.Cli.Commands.Project.Convert;

Expand All @@ -19,6 +20,7 @@ internal sealed class ProjectConvertCommand : CommandBase<ProjectConvertCommandD
private readonly string? _outputDirectory;
private readonly bool _force;
private readonly bool _dryRun;
private readonly bool _deleteSource;

public ProjectConvertCommand(ParseResult parseResult)
: base(parseResult)
Expand All @@ -27,6 +29,7 @@ public ProjectConvertCommand(ParseResult parseResult)
_outputDirectory = parseResult.GetValue(Definition.OutputOption)?.FullName;
_force = parseResult.GetValue(Definition.ForceOption);
_dryRun = parseResult.GetValue(Definition.DryRunOption);
_deleteSource = parseResult.GetValue(Definition.DeleteSourceOption);
}

public override int Execute()
Expand Down Expand Up @@ -102,6 +105,13 @@ public override int Execute()
CopyFile(item.FullPath, targetItemFullPath);
}

// Handle deletion of source file if requested.
bool shouldDeleteSource = _deleteSource || TryAskForDeleteSource(file);
if (shouldDeleteSource)
{
DeleteSourceFile(file);
}

return 0;

void CreateDirectory(string path)
Expand Down Expand Up @@ -282,4 +292,43 @@ private string DetermineOutputDirectory(string file)
? result
: null;
}

private bool TryAskForDeleteSource(string sourceFile)
{
// Don't ask in non-interactive mode or if --delete-source was already specified
if (!_parseResult.GetValue<bool>(CommonOptions.InteractiveOptionName))
{
return false;
}

try
{
// Use Spectre.Console for a better interactive experience
var choice = Spectre.Console.AnsiConsole.Prompt(
new SelectionPrompt<string>()
.Title($"[cyan]{Markup.Escape(string.Format(CliCommandStrings.ProjectConvertAskDeleteSource, Path.GetFileName(sourceFile)))}[/]")
.AddChoices([CliCommandStrings.ProjectConvertDeleteSourceChoiceYes, CliCommandStrings.ProjectConvertDeleteSourceChoiceNo])
);

return choice == CliCommandStrings.ProjectConvertDeleteSourceChoiceYes;
}
catch (Exception)
{
// If Spectre.Console fails (e.g., terminal doesn't support it), fall back to basic prompt
return false;
}
}

private void DeleteSourceFile(string sourceFile)
{
if (_dryRun)
{
Reporter.Output.WriteLine(CliCommandStrings.ProjectConvertWouldDeleteSourceFile, sourceFile);
}
else
{
File.Delete(sourceFile);
Reporter.Output.WriteLine(CliCommandStrings.ProjectConvertDeletedSourceFile, sourceFile);
}
}
}
25 changes: 25 additions & 0 deletions src/Cli/dotnet/Commands/xlf/CliCommandStrings.cs.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 25 additions & 0 deletions src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading