Skip to content

Commit 51f5493

Browse files
authored
Add darc vmr add-repo and remove-repo commands (#5415)
1 parent 29657e1 commit 51f5493

File tree

13 files changed

+481
-194
lines changed

13 files changed

+481
-194
lines changed
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Linq;
7+
using System.Threading;
8+
using System.Threading.Tasks;
9+
using Maestro.Common;
10+
using Microsoft.DotNet.Darc.Helpers;
11+
using Microsoft.DotNet.Darc.Options.VirtualMonoRepo;
12+
using Microsoft.DotNet.DarcLib.Helpers;
13+
using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo;
14+
using Microsoft.DotNet.DarcLib.VirtualMonoRepo;
15+
using Microsoft.Extensions.Logging;
16+
17+
#nullable enable
18+
namespace Microsoft.DotNet.Darc.Operations.VirtualMonoRepo;
19+
20+
internal class AddRepoOperation : Operation
21+
{
22+
private readonly AddRepoCommandLineOptions _options;
23+
private readonly IVmrInitializer _vmrInitializer;
24+
private readonly IVmrInfo _vmrInfo;
25+
private readonly ILogger<AddRepoOperation> _logger;
26+
27+
public AddRepoOperation(
28+
AddRepoCommandLineOptions options,
29+
IVmrInitializer vmrInitializer,
30+
IVmrInfo vmrInfo,
31+
ILogger<AddRepoOperation> logger)
32+
{
33+
_options = options;
34+
_vmrInitializer = vmrInitializer;
35+
_vmrInfo = vmrInfo;
36+
_logger = logger;
37+
}
38+
39+
public override async Task<int> ExecuteAsync()
40+
{
41+
var repositories = _options.Repositories.ToList();
42+
43+
if (!repositories.Any())
44+
{
45+
_logger.LogError("Please specify at least one repository to add");
46+
return Constants.ErrorCode;
47+
}
48+
49+
// Repository names are in the form of URI:REVISION where URI is the git repository URL
50+
// and REVISION is a git ref (commit SHA, branch, or tag)
51+
foreach (var repository in repositories)
52+
{
53+
var parts = repository.Split(':', 2);
54+
if (parts.Length != 2)
55+
{
56+
_logger.LogError("Repository '{repository}' must be in the format URI:REVISION", repository);
57+
return Constants.ErrorCode;
58+
}
59+
60+
string uri = parts[0];
61+
string revision = parts[1];
62+
63+
// For URIs starting with https://, we need to reconstruct the full URI
64+
// since the split on ':' would have separated it
65+
if (uri == "https" || uri == "http")
66+
{
67+
// The original input had a URI with protocol, find the last : to split properly
68+
int lastColonIndex = repository.LastIndexOf(':');
69+
if (lastColonIndex <= uri.Length + 2) // +2 for "://"
70+
{
71+
_logger.LogError("Repository '{repository}' must be in the format URI:REVISION", repository);
72+
return Constants.ErrorCode;
73+
}
74+
75+
uri = repository.Substring(0, lastColonIndex);
76+
revision = repository.Substring(lastColonIndex + 1);
77+
}
78+
79+
try
80+
{
81+
// Extract repo name from URI
82+
var (repoName, _) = GitRepoUrlUtils.GetRepoNameAndOwner(uri);
83+
84+
var sourceMappingsPath = _vmrInfo.VmrPath / VmrInfo.DefaultRelativeSourceMappingsPath;
85+
86+
await _vmrInitializer.InitializeRepository(
87+
repoName,
88+
revision,
89+
uri,
90+
sourceMappingsPath,
91+
new CodeFlowParameters(
92+
Array.Empty<AdditionalRemote>(),
93+
VmrInfo.ThirdPartyNoticesFileName,
94+
GenerateCodeOwners: false,
95+
GenerateCredScanSuppressions: true),
96+
CancellationToken.None);
97+
98+
_logger.LogInformation("Successfully added repository '{repoName}' from '{uri}' at revision '{revision}'", repoName, uri, revision);
99+
}
100+
catch (Exception ex)
101+
{
102+
_logger.LogError(ex, "Failed to add repository from '{uri}'", uri);
103+
return Constants.ErrorCode;
104+
}
105+
}
106+
107+
return Constants.SuccessCode;
108+
}
109+
}

src/Microsoft.DotNet.Darc/Darc/Operations/VirtualMonoRepo/InitializeOperation.cs renamed to src/Microsoft.DotNet.Darc/Darc/Operations/VirtualMonoRepo/RemoveRepoOperation.cs

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,26 @@
55
using System.Threading;
66
using System.Threading.Tasks;
77
using Microsoft.DotNet.Darc.Options.VirtualMonoRepo;
8-
using Microsoft.DotNet.DarcLib.Helpers;
98
using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo;
109
using Microsoft.DotNet.DarcLib.VirtualMonoRepo;
1110
using Microsoft.Extensions.Logging;
1211

1312
#nullable enable
1413
namespace Microsoft.DotNet.Darc.Operations.VirtualMonoRepo;
1514

16-
internal class InitializeOperation : VmrOperationBase
15+
internal class RemoveRepoOperation : VmrOperationBase
1716
{
18-
private readonly InitializeCommandLineOptions _options;
19-
private readonly IVmrInitializer _vmrInitializer;
17+
private readonly RemoveRepoCommandLineOptions _options;
18+
private readonly IVmrRemover _vmrRemover;
2019

21-
public InitializeOperation(
22-
InitializeCommandLineOptions options,
23-
IVmrInitializer vmrInitializer,
24-
ILogger<InitializeOperation> logger)
20+
public RemoveRepoOperation(
21+
RemoveRepoCommandLineOptions options,
22+
IVmrRemover vmrRemover,
23+
ILogger<RemoveRepoOperation> logger)
2524
: base(options, logger)
2625
{
2726
_options = options;
28-
_vmrInitializer = vmrInitializer;
27+
_vmrRemover = vmrRemover;
2928
}
3029

3130
protected override async Task ExecuteInternalAsync(
@@ -34,15 +33,13 @@ protected override async Task ExecuteInternalAsync(
3433
IReadOnlyCollection<AdditionalRemote> additionalRemotes,
3534
CancellationToken cancellationToken)
3635
{
37-
await _vmrInitializer.InitializeRepository(
36+
await _vmrRemover.RemoveRepository(
3837
repoName,
39-
targetRevision,
40-
new NativePath(_options.SourceMappings),
4138
new CodeFlowParameters(
4239
additionalRemotes,
43-
_options.TpnTemplate,
44-
_options.GenerateCodeowners,
45-
_options.GenerateCredScanSuppressions),
40+
VmrInfo.ThirdPartyNoticesFileName,
41+
GenerateCodeOwners: false,
42+
GenerateCredScanSuppressions: true),
4643
cancellationToken);
4744
}
4845
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Collections.Generic;
5+
using CommandLine;
6+
using Microsoft.DotNet.Darc.Operations.VirtualMonoRepo;
7+
using Microsoft.Extensions.DependencyInjection;
8+
9+
namespace Microsoft.DotNet.Darc.Options.VirtualMonoRepo;
10+
11+
[Verb("add-repo", HelpText = "Adds new repo(s) to the VMR that haven't been synchronized yet.")]
12+
internal class AddRepoCommandLineOptions : VmrCommandLineOptions<AddRepoOperation>, IBaseVmrCommandLineOptions
13+
{
14+
[Value(0, Required = true, HelpText =
15+
"Repository URIs in the form of URI:REVISION where URI is the git repository URL (e.g., https://github.com/dotnet/runtime) and REVISION is a commit SHA or other git reference (branch, tag).")]
16+
public IEnumerable<string> Repositories { get; set; }
17+
18+
// Required by IBaseVmrCommandLineOptions but not used for this command
19+
public IEnumerable<string> AdditionalRemotes { get; set; } = [];
20+
21+
public override IServiceCollection RegisterServices(IServiceCollection services)
22+
{
23+
if (!Verbose && !Debug)
24+
{
25+
// Force verbose output for these commands
26+
Verbose = true;
27+
}
28+
29+
return base.RegisterServices(services);
30+
}
31+
}

src/Microsoft.DotNet.Darc/Darc/Options/VirtualMonoRepo/InitializeCommandLineOptions.cs

Lines changed: 0 additions & 36 deletions
This file was deleted.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Collections.Generic;
5+
using CommandLine;
6+
using Microsoft.DotNet.Darc.Operations.VirtualMonoRepo;
7+
using Microsoft.Extensions.DependencyInjection;
8+
9+
namespace Microsoft.DotNet.Darc.Options.VirtualMonoRepo;
10+
11+
[Verb("remove-repo", HelpText = "Removes repo(s) from the VMR.")]
12+
internal class RemoveRepoCommandLineOptions : VmrCommandLineOptions<RemoveRepoOperation>, IBaseVmrCommandLineOptions
13+
{
14+
[Value(0, Required = true, HelpText = "Repository names to remove from the VMR.")]
15+
public IEnumerable<string> Repositories { get; set; }
16+
17+
// Required by IBaseVmrCommandLineOptions but not used for this command
18+
public IEnumerable<string> AdditionalRemotes { get; set; } = [];
19+
20+
public override IServiceCollection RegisterServices(IServiceCollection services)
21+
{
22+
if (!Verbose && !Debug)
23+
{
24+
// Force verbose output for these commands
25+
Verbose = true;
26+
}
27+
28+
return base.RegisterServices(services);
29+
}
30+
}

src/Microsoft.DotNet.Darc/Darc/Program.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@ public static Type[] GetOptions() =>
145145
// These are under the "vmr" subcommand
146146
public static Type[] GetVmrOptions() =>
147147
[
148-
typeof(InitializeCommandLineOptions),
148+
typeof(AddRepoCommandLineOptions),
149+
typeof(RemoveRepoCommandLineOptions),
149150
typeof(BackflowCommandLineOptions),
150151
typeof(ForwardFlowCommandLineOptions),
151152
typeof(CherryPickCommandLineOptions),

src/Microsoft.DotNet.Darc/DarcLib/Models/VirtualMonoRepo/SourceMappingFile.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.Collections.Generic;
5+
using System.Text.Json.Serialization;
56

67
#nullable enable
78
namespace Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo;
@@ -44,7 +45,9 @@ public class SourceMappingSetting
4445
public string? DefaultRef { get; set; }
4546
public string[]? Include { get; set; }
4647
public string[]? Exclude { get; set; }
48+
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
4749
public bool IgnoreDefaults { get; set; }
50+
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
4851
public bool DisableSynchronization { get; set; }
4952
}
5053

src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/IVmrInitializer.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@ public interface IVmrInitializer
1616
/// </summary>
1717
/// <param name="mappingName">Name of a repository mapping</param>
1818
/// <param name="targetRevision">Revision (commit SHA, branch, tag..) onto which to synchronize, leave empty for HEAD</param>
19+
/// <param name="remoteUri">Remote URI of the repository (optional, will default to https://github.com/dotnet/{mappingName})</param>
1920
/// <param name="sourceMappingsPath">Path to the source-mappings.json file</param>
2021
/// <param name="codeFlowParameters">Record containing parameters for VMR initialization</param>
2122
Task InitializeRepository(
2223
string mappingName,
2324
string? targetRevision,
25+
string? remoteUri,
2426
LocalPath sourceMappingsPath,
2527
CodeFlowParameters codeFlowParameters,
2628
CancellationToken cancellationToken);
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Threading;
5+
using System.Threading.Tasks;
6+
using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo;
7+
8+
#nullable enable
9+
namespace Microsoft.DotNet.DarcLib.VirtualMonoRepo;
10+
11+
public interface IVmrRemover
12+
{
13+
/// <summary>
14+
/// Removes a repository from the VMR.
15+
/// </summary>
16+
/// <param name="mappingName">Name of a repository mapping</param>
17+
/// <param name="codeFlowParameters">Record containing parameters for VMR operations</param>
18+
/// <param name="cancellationToken">Cancellation token</param>
19+
Task RemoveRepository(
20+
string mappingName,
21+
CodeFlowParameters codeFlowParameters,
22+
CancellationToken cancellationToken);
23+
}

0 commit comments

Comments
 (0)