Skip to content

Commit 19add93

Browse files
committed
Fix catalog sync regression and header nav
Closes #493
1 parent 82a5431 commit 19add93

7 files changed

Lines changed: 481 additions & 139 deletions

File tree

cli/ManagedCode.DotnetSkills/Program.cs

Lines changed: 150 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -253,160 +253,67 @@ private static async Task<int> RunRecommendAsync(string[] args)
253253

254254
private static async Task<int> RunInstallAsync(string[] args)
255255
{
256-
var requestedSkills = new List<string>();
257-
string? targetPath = null;
258-
string? cachePath = null;
259-
string? catalogVersion = null;
260-
string? projectDirectory = null;
261-
var installAll = false;
262-
var autoInstall = false;
263-
var pruneAutoManaged = false;
264-
var force = false;
265-
var bundledOnly = false;
266-
var refreshCatalog = false;
267-
var agent = AgentPlatform.Auto;
268-
var scope = InstallScope.Project;
269-
270-
for (var index = 0; index < args.Length; index++)
271-
{
272-
switch (args[index])
273-
{
274-
case "--all":
275-
installAll = true;
276-
break;
277-
case "--auto":
278-
autoInstall = true;
279-
break;
280-
case "--prune":
281-
pruneAutoManaged = true;
282-
break;
283-
case "--force":
284-
force = true;
285-
break;
286-
case "--target":
287-
targetPath = ReadValue(args, ++index, "--target");
288-
break;
289-
case "--cache-dir":
290-
cachePath = ReadValue(args, ++index, "--cache-dir");
291-
break;
292-
case "--catalog-version":
293-
catalogVersion = ReadValue(args, ++index, "--catalog-version");
294-
break;
295-
case "--agent":
296-
agent = SkillInstallTarget.ParseAgent(ReadValue(args, ++index, "--agent"));
297-
break;
298-
case "--scope":
299-
scope = SkillInstallTarget.ParseScope(ReadValue(args, ++index, "--scope"));
300-
break;
301-
case "--project-dir":
302-
projectDirectory = ReadValue(args, ++index, "--project-dir");
303-
break;
304-
case "--bundled":
305-
bundledOnly = true;
306-
break;
307-
case "--refresh":
308-
refreshCatalog = true;
309-
break;
310-
default:
311-
requestedSkills.Add(args[index]);
312-
break;
313-
}
314-
}
315-
316-
var packageMode = requestedSkills.Count > 0
317-
&& string.Equals(requestedSkills[0], "package", StringComparison.OrdinalIgnoreCase);
256+
var options = ParseInstallOptions(args);
318257

319-
if (packageMode)
320-
{
321-
requestedSkills.RemoveAt(0);
322-
323-
if (installAll)
324-
{
325-
throw new InvalidOperationException("`dotnet skills install package` requires explicit package names and does not support --all.");
326-
}
327-
328-
if (requestedSkills.Count == 0)
329-
{
330-
throw new InvalidOperationException("Specify one or more package names after `dotnet skills install package`.");
331-
}
332-
}
333-
334-
if (autoInstall)
335-
{
336-
if (installAll)
337-
{
338-
throw new InvalidOperationException("`dotnet skills install --auto` scans the project and does not support --all.");
339-
}
340-
341-
if (packageMode || requestedSkills.Count > 0)
342-
{
343-
throw new InvalidOperationException("`dotnet skills install --auto` does not accept explicit skill or package names.");
344-
}
345-
}
346-
else if (pruneAutoManaged)
347-
{
348-
throw new InvalidOperationException("`--prune` is only available together with `dotnet skills install --auto`.");
349-
}
350-
351-
if (pruneAutoManaged && scope != InstallScope.Project)
258+
if (options.PruneAutoManaged && options.Scope != InstallScope.Project)
352259
{
353260
throw new InvalidOperationException("`dotnet skills install --auto --prune` requires --scope project because global skill roots are shared across repositories.");
354261
}
355262

356-
await MaybeShowToolUpdateAsync(cachePath);
263+
await MaybeShowToolUpdateAsync(options.CachePath);
357264

358-
var catalog = await ResolveCatalogForInstallAsync(bundledOnly, cachePath, catalogVersion, refreshCatalog);
265+
var catalog = await ResolveCatalogForInstallAsync(options.BundledOnly, options.CachePath, options.CatalogVersion, options.RefreshCatalog);
359266
var installer = new SkillInstaller(catalog);
360-
if (autoInstall)
267+
if (options.AutoInstall)
361268
{
362269
var autoSyncService = new ProjectSkillAutoSyncService(catalog);
363270

364-
if (ShouldUseAutoDetectedLayouts(targetPath, agent))
271+
if (ShouldUseAutoDetectedLayouts(options.TargetPath, options.Agent))
365272
{
366-
var layouts = SkillInstallTarget.ResolveAllDetected(projectDirectory, scope);
273+
var layouts = SkillInstallTarget.ResolveAllDetected(options.ProjectDirectory, options.Scope);
367274
for (var index = 0; index < layouts.Count; index++)
368275
{
369276
if (index > 0)
370277
{
371278
Console.WriteLine();
372279
}
373280

374-
ExecuteAutoInstallIntoLayout(catalog, installer, autoSyncService, layouts[index], projectDirectory, force, pruneAutoManaged);
281+
ExecuteAutoInstallIntoLayout(catalog, installer, autoSyncService, layouts[index], options.ProjectDirectory, options.Force, options.PruneAutoManaged);
375282
}
376283

377284
return 0;
378285
}
379286

380-
var autoLayout = SkillInstallTarget.Resolve(targetPath, agent, scope, projectDirectory);
381-
ExecuteAutoInstallIntoLayout(catalog, installer, autoSyncService, autoLayout, projectDirectory, force, pruneAutoManaged);
287+
var autoLayout = SkillInstallTarget.Resolve(options.TargetPath, options.Agent, options.Scope, options.ProjectDirectory);
288+
ExecuteAutoInstallIntoLayout(catalog, installer, autoSyncService, autoLayout, options.ProjectDirectory, options.Force, options.PruneAutoManaged);
382289
return 0;
383290
}
384291

385-
var selectedSkills = packageMode
386-
? installer.SelectSkillsFromPackages(requestedSkills)
387-
: installer.SelectSkills(requestedSkills, installAll);
388-
if (ShouldUseAutoDetectedLayouts(targetPath, agent))
292+
var selectedSkills = options.PackageMode
293+
? installer.SelectSkillsFromPackages(options.RequestedSkills)
294+
: installer.SelectSkills(options.RequestedSkills, options.InstallAll);
295+
if (ShouldUseAutoDetectedLayouts(options.TargetPath, options.Agent))
389296
{
390297
var batchResults = new List<SkillInstallBatchResult>();
391298

392-
foreach (var layout in SkillInstallTarget.ResolveAllDetected(projectDirectory, scope))
299+
foreach (var layout in SkillInstallTarget.ResolveAllDetected(options.ProjectDirectory, options.Scope))
393300
{
394301
var installedBefore = installer.GetInstalledSkills(layout)
395302
.ToDictionary(record => record.Skill.Name, StringComparer.OrdinalIgnoreCase);
396-
var summary = installer.Install(selectedSkills, layout, force);
397-
var rows = BuildInstallRows(selectedSkills, installedBefore, force, summary);
303+
var summary = installer.Install(selectedSkills, layout, options.Force);
304+
var rows = BuildInstallRows(selectedSkills, installedBefore, options.Force, summary);
398305
batchResults.Add(new SkillInstallBatchResult(layout, rows, summary));
399306
}
400307

401308
ConsoleUi.RenderInstallSummaryMultiple(catalog, batchResults);
402309
return 0;
403310
}
404311

405-
var singleLayout = SkillInstallTarget.Resolve(targetPath, agent, scope, projectDirectory);
312+
var singleLayout = SkillInstallTarget.Resolve(options.TargetPath, options.Agent, options.Scope, options.ProjectDirectory);
406313
var installedInSingleLayout = installer.GetInstalledSkills(singleLayout)
407314
.ToDictionary(record => record.Skill.Name, StringComparer.OrdinalIgnoreCase);
408-
var singleSummary = installer.Install(selectedSkills, singleLayout, force);
409-
var singleRows = BuildInstallRows(selectedSkills, installedInSingleLayout, force, singleSummary);
315+
var singleSummary = installer.Install(selectedSkills, singleLayout, options.Force);
316+
var singleRows = BuildInstallRows(selectedSkills, installedInSingleLayout, options.Force, singleSummary);
410317

411318
ConsoleUi.RenderInstallSummary(catalog, singleLayout, singleRows, singleSummary);
412319
return 0;
@@ -832,6 +739,120 @@ internal static bool IsUsageStartup(string[] args) =>
832739

833740
internal static bool IsInteractiveStartup(string[] args) => args.Length == 0;
834741

742+
internal static InstallCommandOptions ParseInstallOptions(string[] args)
743+
{
744+
var requestedSkills = new List<string>();
745+
string? targetPath = null;
746+
string? cachePath = null;
747+
string? catalogVersion = null;
748+
string? projectDirectory = null;
749+
var installAll = false;
750+
var autoInstall = false;
751+
var pruneAutoManaged = false;
752+
var force = false;
753+
var bundledOnly = false;
754+
var refreshCatalog = false;
755+
var agent = AgentPlatform.Auto;
756+
var scope = InstallScope.Project;
757+
758+
for (var index = 0; index < args.Length; index++)
759+
{
760+
switch (args[index])
761+
{
762+
case "--all":
763+
installAll = true;
764+
break;
765+
case "--auto":
766+
autoInstall = true;
767+
break;
768+
case "--prune":
769+
pruneAutoManaged = true;
770+
break;
771+
case "--force":
772+
force = true;
773+
break;
774+
case "--target":
775+
targetPath = ReadValue(args, ++index, "--target");
776+
break;
777+
case "--cache-dir":
778+
cachePath = ReadValue(args, ++index, "--cache-dir");
779+
break;
780+
case "--catalog-version":
781+
catalogVersion = ReadValue(args, ++index, "--catalog-version");
782+
break;
783+
case "--agent":
784+
agent = SkillInstallTarget.ParseAgent(ReadValue(args, ++index, "--agent"));
785+
break;
786+
case "--scope":
787+
scope = SkillInstallTarget.ParseScope(ReadValue(args, ++index, "--scope"));
788+
break;
789+
case "--project-dir":
790+
projectDirectory = ReadValue(args, ++index, "--project-dir");
791+
break;
792+
case "--bundled":
793+
bundledOnly = true;
794+
break;
795+
case "--refresh":
796+
refreshCatalog = true;
797+
break;
798+
default:
799+
requestedSkills.Add(args[index]);
800+
break;
801+
}
802+
}
803+
804+
var packageMode = requestedSkills.Count > 0
805+
&& string.Equals(requestedSkills[0], "package", StringComparison.OrdinalIgnoreCase);
806+
807+
if (packageMode)
808+
{
809+
requestedSkills.RemoveAt(0);
810+
811+
if (installAll)
812+
{
813+
throw new InvalidOperationException("`dotnet skills install package` requires explicit package names and does not support --all.");
814+
}
815+
816+
if (requestedSkills.Count == 0)
817+
{
818+
throw new InvalidOperationException("Specify one or more package names after `dotnet skills install package`.");
819+
}
820+
}
821+
822+
if (autoInstall)
823+
{
824+
if (installAll)
825+
{
826+
throw new InvalidOperationException("`dotnet skills install --auto` scans the project and does not support --all.");
827+
}
828+
829+
if (packageMode || requestedSkills.Count > 0)
830+
{
831+
throw new InvalidOperationException("`dotnet skills install --auto` does not accept explicit skill or package names.");
832+
}
833+
}
834+
else if (pruneAutoManaged)
835+
{
836+
throw new InvalidOperationException("`--prune` is only available together with `dotnet skills install --auto`.");
837+
}
838+
839+
return new InstallCommandOptions(
840+
requestedSkills.ToArray(),
841+
targetPath,
842+
cachePath,
843+
catalogVersion,
844+
projectDirectory,
845+
installAll,
846+
autoInstall,
847+
pruneAutoManaged,
848+
force,
849+
bundledOnly,
850+
refreshCatalog,
851+
agent,
852+
scope,
853+
packageMode);
854+
}
855+
835856
private static bool IsVersionCommand(string command) =>
836857
string.Equals(command, "version", StringComparison.OrdinalIgnoreCase)
837858
|| string.Equals(command, "--version", StringComparison.OrdinalIgnoreCase);
@@ -1213,3 +1234,19 @@ private static async Task<int> RunAgentWhereAsync(string[] args)
12131234
return 0;
12141235
}
12151236
}
1237+
1238+
internal sealed record InstallCommandOptions(
1239+
IReadOnlyList<string> RequestedSkills,
1240+
string? TargetPath,
1241+
string? CachePath,
1242+
string? CatalogVersion,
1243+
string? ProjectDirectory,
1244+
bool InstallAll,
1245+
bool AutoInstall,
1246+
bool PruneAutoManaged,
1247+
bool Force,
1248+
bool BundledOnly,
1249+
bool RefreshCatalog,
1250+
AgentPlatform Agent,
1251+
InstallScope Scope,
1252+
bool PackageMode);

0 commit comments

Comments
 (0)