Skip to content

Commit 5a7eb83

Browse files
committed
Environment now gets a .ignore file that un-ignores plugin folders so VS Code searches still work.
1 parent 5e582cd commit 5a7eb83

7 files changed

Lines changed: 313 additions & 8 deletions

File tree

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
src\eslint-config-rock-recommended
88
src\obsidian-build-tools
99
-->
10-
<Version>1.0.4</Version>
10+
<Version>1.0.5</Version>
1111
</PropertyGroup>
1212

1313
<PropertyGroup>

src/SparkDevNetwork.Rock.DevTool/Commands/EnvironmentCommand.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,6 @@ public EnvironmentCommand( IServiceProvider serviceProvider )
2323
AddCommand( ActivatorUtilities.CreateInstance<NewCommand>( serviceProvider ) );
2424
AddCommand( ActivatorUtilities.CreateInstance<UpdateCommand>( serviceProvider ) );
2525
AddCommand( ActivatorUtilities.CreateInstance<StatusCommand>( serviceProvider ) );
26+
AddCommand( ActivatorUtilities.CreateInstance<UpgradeCommand>( serviceProvider ) );
2627
}
2728
}

src/SparkDevNetwork.Rock.DevTool/Commands/EnvironmentCommands/NewCommand.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,12 @@ private async Task<int> CreateEnvironment( string outputDirectory, string orgNam
140140
141141
""" );
142142

143+
// Write the ".ignore" file.
144+
WriteFile( _fs.Path.Join( outputDirectory, ".ignore" ),
145+
"""
146+
# Unignore Plugins - DO NOT MODIFY
147+
""" );
148+
143149
// Write the "/.vscode/extensions.json" file.
144150
WriteFile( _fs.Path.Join( outputDirectory, ".vscode", "extensions.json" ),
145151
"""
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
using System.CommandLine;
2+
using System.CommandLine.Invocation;
3+
using System.IO.Abstractions;
4+
5+
using Microsoft.Extensions.DependencyInjection;
6+
7+
using SparkDevNetwork.Rock.DevTool.DevEnvironment;
8+
9+
using Spectre.Console;
10+
11+
namespace SparkDevNetwork.Rock.DevTool.Commands.EnvironmentCommands;
12+
13+
/// <summary>
14+
/// Upgrade command for development environments.
15+
/// </summary>
16+
class UpgradeCommand : Abstractions.BaseActionCommand
17+
{
18+
#region Fields
19+
20+
/// <summary>
21+
/// The option that defines the directory of the environment.
22+
/// </summary>
23+
private readonly Option<string?> _environmentOption;
24+
25+
/// <summary>
26+
/// The provider of services for this instance.
27+
/// </summary>
28+
private readonly IServiceProvider _serviceProvider;
29+
30+
/// <summary>
31+
/// The object that will be used to access the filesystem.
32+
/// </summary>
33+
private readonly IFileSystem _fs;
34+
35+
#endregion
36+
37+
#region Properties
38+
39+
/// <summary>
40+
/// The directory that contains the environment.
41+
/// </summary>
42+
public string? EnvironmentPath { get; set; }
43+
44+
#endregion
45+
46+
/// <summary>
47+
/// Creates a command that will handle upgrading an existing environment.
48+
/// </summary>
49+
public UpgradeCommand( IServiceProvider serviceProvider )
50+
: base( "upgrade", "Upgrades the environment to the latest configuration.", serviceProvider )
51+
{
52+
_serviceProvider = serviceProvider;
53+
_fs = _serviceProvider.GetRequiredService<IFileSystem>();
54+
55+
_environmentOption = new Option<string?>( "--environment", "The directory that contains the environment." );
56+
_environmentOption.AddAlias( "--env" );
57+
58+
AddOption( _environmentOption );
59+
}
60+
61+
/// <inheritdoc/>
62+
protected override void GetOptions( InvocationContext context )
63+
{
64+
base.GetOptions( context );
65+
66+
EnvironmentPath = context.ParseResult.GetValueForOption( _environmentOption );
67+
}
68+
69+
/// <inheritdoc/>
70+
protected override Task<int> ExecuteAsync()
71+
{
72+
var targetDirectory = EnvironmentPath ?? _fs.Directory.GetCurrentDirectory();
73+
DevEnvironment.Environment environment;
74+
75+
targetDirectory = _fs.Path.GetFullPath( targetDirectory );
76+
77+
try
78+
{
79+
environment = DevEnvironment.Environment.Open( targetDirectory, _serviceProvider, warnIfUpgradeNeeded: false );
80+
}
81+
catch ( InvalidEnvironmentException ex )
82+
{
83+
Console.WriteLine( ex.Message );
84+
return Task.FromResult( 1 );
85+
}
86+
87+
if ( !environment.IsUpgradeNeeded() )
88+
{
89+
Console.MarkupLine( "[green]The environment is already up to date.[/]" );
90+
return Task.FromResult( 0 );
91+
}
92+
93+
var upgrader = new EnvironmentUpgrader( _fs, Console );
94+
95+
if ( !upgrader.Upgrade( environment ) )
96+
{
97+
return Task.FromResult( 1 );
98+
}
99+
100+
Console.MarkupLine( "[green]The environment has been successfully upgraded.[/]" );
101+
102+
return Task.FromResult( 0 );
103+
}
104+
}

src/SparkDevNetwork.Rock.DevTool/Commands/PluginCommands/NewCommand.cs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -430,9 +430,10 @@ private async Task CopyTemplateAsync( string sourceName, string[] destination )
430430
private void AddPluginToGitIgnore()
431431
{
432432
var environmentDirectory = EnvironmentPath ?? _fs.Directory.GetCurrentDirectory();
433-
var path = _fs.Path.Combine( environmentDirectory, ".gitignore" );
433+
var gitIgnorePath = _fs.Path.Combine( environmentDirectory, ".gitignore" );
434+
var ignorePath = _fs.Path.Combine( environmentDirectory, ".ignore" );
434435

435-
var content = _fs.File.ReadAllText( path );
436+
var content = _fs.File.ReadAllText( gitIgnorePath );
436437
var lineEnding = content.Contains( "\r\n" ) ? "\r\n" : "\n";
437438

438439
// If the gitignore file already contains this item then skip it. This
@@ -451,7 +452,32 @@ private void AddPluginToGitIgnore()
451452
content = $"{content}/{PluginCode}{lineEnding}";
452453
}
453454

454-
WriteFile( path, content );
455+
WriteFile( gitIgnorePath, content );
456+
457+
// Also add invert to .ignore so VS Code will still search the file.
458+
if ( _fs.File.Exists( ignorePath ) )
459+
{
460+
content = _fs.File.ReadAllText( ignorePath );
461+
lineEnding = content.Contains( "\r\n" ) ? "\r\n" : "\n";
462+
463+
// If the ignore file already contains this item then skip it. This
464+
// most often happens when the force option is used.
465+
if ( content.Split( ['\r', '\n'] ).Contains( $"!/{PluginCode}" ) )
466+
{
467+
return;
468+
}
469+
470+
if ( !content.EndsWith( lineEnding ) )
471+
{
472+
content = $"{content}{lineEnding}!/{PluginCode}{lineEnding}";
473+
}
474+
else
475+
{
476+
content = $"{content}!/{PluginCode}{lineEnding}";
477+
}
478+
479+
WriteFile( ignorePath, content );
480+
}
455481
}
456482

457483
/// <summary>

src/SparkDevNetwork.Rock.DevTool/DevEnvironment/Environment.cs

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,16 @@ class Environment
6161
/// </summary>
6262
public bool IsForce { get; set; }
6363

64+
/// <summary>
65+
/// Gets the data that represents the environment configuration.
66+
/// </summary>
67+
public EnvironmentData Data => _data;
68+
69+
/// <summary>
70+
/// Gets the directory that contains the environment.
71+
/// </summary>
72+
public string Directory => _environmentDirectory;
73+
6474
#endregion
6575

6676
/// <summary>
@@ -80,10 +90,10 @@ private Environment( string environmentDirectory, EnvironmentData data, IService
8090
/// Opens an existing environment from a directory.
8191
/// </summary>
8292
/// <param name="environmentDirectory">The directory that contains the environment.</param>
83-
/// <param name="console">The console object to use when writing console messages.</param>
84-
/// <param name="loggerFactory">The factory to create new logging facilities.</param>
93+
/// <param name="serviceProvider">The service provider to use when resolving dependencies.</param>
94+
/// <param name="warnIfUpgradeNeeded">Determines if a warning should be displayed if an upgrade is needed.</param>
8595
/// <returns>An instance of <see cref="Environment"/> or <c>null</c> if it could not be opened.</returns>
86-
public static Environment Open( string environmentDirectory, IServiceProvider serviceProvider )
96+
public static Environment Open( string environmentDirectory, IServiceProvider serviceProvider, bool warnIfUpgradeNeeded = true )
8797
{
8898
var fs = serviceProvider.GetRequiredService<IFileSystem>();
8999
var environmentFile = fs.Path.Combine( environmentDirectory, EnvironmentData.Filename );
@@ -108,7 +118,14 @@ public static Environment Open( string environmentDirectory, IServiceProvider se
108118
}
109119
}
110120

111-
return new Environment( environmentDirectory, data, serviceProvider );
121+
var environment = new Environment( environmentDirectory, data, serviceProvider );
122+
123+
if ( warnIfUpgradeNeeded )
124+
{
125+
environment.WarnIfUpgradeNeeded();
126+
}
127+
128+
return environment;
112129
}
113130

114131
/// <summary>
@@ -545,4 +562,28 @@ private bool CreateJunction( string junctionDirectory, string targetDirectory )
545562

546563
return true;
547564
}
565+
566+
/// <summary>
567+
/// Determines if the environment needs to be upgraded.
568+
/// </summary>
569+
/// <returns><c>true</c> if the environment needs to be upgraded; otherwise, <c>false</c>.</returns>
570+
public bool IsUpgradeNeeded()
571+
{
572+
return _data.ToolVersion.ComparePrecedenceTo( new SemVersion( 1, 0, 5 ) ) < 0;
573+
}
574+
575+
/// <summary>
576+
/// Warns the user if the environment needs to be upgraded.
577+
/// </summary>
578+
/// <returns><c>true</c> if the environment needs to be upgraded; otherwise, <c>false</c>.</returns>
579+
private bool WarnIfUpgradeNeeded()
580+
{
581+
if ( IsUpgradeNeeded() )
582+
{
583+
_console.MarkupLine( "[yellow]Warning: This environment was created with an older version of the Dev Tool. It is recommended to upgrade the environment using the 'rock-dev-tool env upgrade' command.[/]" );
584+
return true;
585+
}
586+
587+
return false;
588+
}
548589
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
using System.IO.Abstractions;
2+
using System.Text.Json;
3+
4+
using Semver;
5+
6+
using Spectre.Console;
7+
8+
namespace SparkDevNetwork.Rock.DevTool.DevEnvironment;
9+
10+
/// <summary>
11+
/// Handles upgrading an environment to the latest tool version.
12+
/// </summary>
13+
class EnvironmentUpgrader
14+
{
15+
#region Fields
16+
17+
/// <summary>
18+
/// The file system abstraction.
19+
/// </summary>
20+
private readonly IFileSystem _fs;
21+
22+
/// <summary>
23+
/// The console for writing messages to the console.
24+
/// </summary>
25+
private readonly IAnsiConsole _console;
26+
27+
#endregion
28+
29+
#region Constructors
30+
31+
/// <summary>
32+
/// Initializes a new instance of the <see cref="EnvironmentUpgrader"/> class.
33+
/// </summary>
34+
/// <param name="fs">The file system abstraction.</param>
35+
/// <param name="console">The console for writing messages to the console.</param>
36+
public EnvironmentUpgrader( IFileSystem fs, IAnsiConsole console )
37+
{
38+
_fs = fs;
39+
_console = console;
40+
}
41+
42+
#endregion
43+
44+
#region Methods
45+
46+
/// <summary>
47+
/// Upgrades the specified environment to the latest tool version.
48+
/// </summary>
49+
/// <param name="environment">The environment to upgrade.</param>
50+
/// <returns><c>true</c> if the upgrade was successful; otherwise, <c>false</c>.</returns>
51+
public bool Upgrade( Environment environment )
52+
{
53+
// In version 1.0.5 we added a .ignore file.
54+
if ( environment.Data.ToolVersion.ComparePrecedenceTo( new SemVersion( 1, 0, 5 ) ) < 0 )
55+
{
56+
if ( !CreateIgnoreFile( environment ) )
57+
{
58+
return false;
59+
}
60+
61+
environment.Data.ToolVersion = new SemVersion( 1, 0, 5 );
62+
environment.Save();
63+
}
64+
65+
// Set the final tool version to the current version.
66+
environment.Data.ToolVersion = Support.CurrentToolVersion;
67+
68+
environment.Save();
69+
70+
return true;
71+
}
72+
73+
/// <summary>
74+
/// Creates a .ignore file for the environment.
75+
/// </summary>
76+
/// <param name="environment">The environment.</param>
77+
/// <returns><c>true</c> if the .ignore file was created successfully; otherwise, <c>false</c>.</returns>
78+
private bool CreateIgnoreFile( Environment environment )
79+
{
80+
var ignorePath = _fs.Path.Combine( environment.Directory, ".ignore" );
81+
string content;
82+
83+
if ( _fs.File.Exists( ignorePath ) )
84+
{
85+
content = _fs.File.ReadAllText( ignorePath );
86+
}
87+
else
88+
{
89+
content = "# Unignore Plugins - DO NOT MODIFY\n";
90+
}
91+
92+
var lineEnding = content.Contains( "\r\n" ) ? "\r\n" : "\n";
93+
94+
foreach ( var plugin in environment.Data.Plugins )
95+
{
96+
// If the gitignore file already contains this item then skip it. This
97+
// most often happens when the force option is used.
98+
if ( content.Split( ['\r', '\n'] ).Contains( $"!/{plugin.Path}" ) )
99+
{
100+
continue;
101+
}
102+
103+
if ( !content.EndsWith( lineEnding ) )
104+
{
105+
content = $"{content}{lineEnding}!/{plugin.Path}{lineEnding}";
106+
}
107+
else
108+
{
109+
content = $"{content}!/{plugin.Path}{lineEnding}";
110+
}
111+
}
112+
113+
if ( environment.IsDryRun )
114+
{
115+
var friendlyPath = _fs.Path.GetFriendlyPath( ignorePath );
116+
_console.MarkupLineInterpolated( $"Create ignore file [cyan]{friendlyPath}[/]." );
117+
}
118+
else
119+
{
120+
_fs.File.WriteAllText( ignorePath, content );
121+
}
122+
123+
return true;
124+
}
125+
126+
#endregion
127+
}

0 commit comments

Comments
 (0)