diff --git a/.azure-ci.yaml b/.azure-ci.yaml
index c903d61cd9..22bd6f352d 100644
--- a/.azure-ci.yaml
+++ b/.azure-ci.yaml
@@ -14,7 +14,7 @@ jobs:
- job: Linux
pool:
- vmImage: ubuntu-16.04
+ vmImage: ubuntu-latest
strategy:
maxParallel: 2
matrix:
diff --git a/RoslynTools.sln b/RoslynTools.sln
index a484e92169..22e59f0f8c 100644
--- a/RoslynTools.sln
+++ b/RoslynTools.sln
@@ -52,8 +52,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Common", "Common", "{F8274B
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RoslynTools.RepoToolset", "src\RepoToolset\RoslynTools.RepoToolset.csproj", "{9CD244CF-F578-4F4E-A28D-38BB914BFE79}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VstsMergeTool", "src\VstsMergeTool\VstsMergeTool.csproj", "{6143F625-C2DC-4B25-854C-9A3B9CB20A83}"
-EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "OptProf", "OptProf", "{821F3F43-E221-4507-95BD-64843868AC11}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "roslyn.optprof", "src\OptProf\roslyn.optprof\roslyn.optprof.csproj", "{75ADCD47-079E-4628-A920-659482F4A030}"
@@ -62,12 +60,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "roslyn.optprof.lib", "src\O
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "roslyn.optprof.runsettings.generator", "src\OptProf\roslyn.optprof.runsettings.generator\roslyn.optprof.runsettings.generator.csproj", "{CCE71F35-DCD5-4008-9DC5-677431E87494}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BuildCleanupTool", "src\BuildCleanupTool\BuildCleanupTool.csproj", "{30A74B33-E707-4942-8B97-59D714106D94}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "roslyn.optprof.runsettings.generator.UnitTests", "src\OptProf\roslyn.optprof.runsettings.generator.unittests\roslyn.optprof.runsettings.generator.UnitTests.csproj", "{44B80D37-F395-40CF-8BB6-9AAEB5606672}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BuildRetainer", "src\BuildRetainer\BuildRetainer.csproj", "{DAD4C83F-8C86-4099-AA2A-EFCF1F5D5459}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GitHubCreateMergePRs", "src\GitHubCreateMergePRs\GitHubCreateMergePRs.csproj", "{491D6953-5267-463F-9796-E9906B2FE516}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PRFinder", "src\RoslynInsertionTool\PRFinder\PRFinder.csproj", "{15BE78E3-355F-4B15-ABB4-FA750B2D846B}"
@@ -76,7 +70,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CreateTagsForVSRelease", "s
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VSBranchInfo", "src\VSBranchInfo\VSBranchInfo.csproj", "{D10CCD63-A7F6-4310-81AA-0D00526320D1}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NugetDependencyFinder", "src\NugetDependencyFinder\NugetDependencyFinder.csproj", "{7A6963D6-1F40-4CC6-9941-7F912252F877}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NugetDependencyFinder", "src\NugetDependencyFinder\NugetDependencyFinder.csproj", "{7A6963D6-1F40-4CC6-9941-7F912252F877}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -280,18 +274,6 @@ Global
{9CD244CF-F578-4F4E-A28D-38BB914BFE79}.Release|x64.Build.0 = Release|Any CPU
{9CD244CF-F578-4F4E-A28D-38BB914BFE79}.Release|x86.ActiveCfg = Release|Any CPU
{9CD244CF-F578-4F4E-A28D-38BB914BFE79}.Release|x86.Build.0 = Release|Any CPU
- {6143F625-C2DC-4B25-854C-9A3B9CB20A83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {6143F625-C2DC-4B25-854C-9A3B9CB20A83}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {6143F625-C2DC-4B25-854C-9A3B9CB20A83}.Debug|x64.ActiveCfg = Debug|Any CPU
- {6143F625-C2DC-4B25-854C-9A3B9CB20A83}.Debug|x64.Build.0 = Debug|Any CPU
- {6143F625-C2DC-4B25-854C-9A3B9CB20A83}.Debug|x86.ActiveCfg = Debug|Any CPU
- {6143F625-C2DC-4B25-854C-9A3B9CB20A83}.Debug|x86.Build.0 = Debug|Any CPU
- {6143F625-C2DC-4B25-854C-9A3B9CB20A83}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {6143F625-C2DC-4B25-854C-9A3B9CB20A83}.Release|Any CPU.Build.0 = Release|Any CPU
- {6143F625-C2DC-4B25-854C-9A3B9CB20A83}.Release|x64.ActiveCfg = Release|Any CPU
- {6143F625-C2DC-4B25-854C-9A3B9CB20A83}.Release|x64.Build.0 = Release|Any CPU
- {6143F625-C2DC-4B25-854C-9A3B9CB20A83}.Release|x86.ActiveCfg = Release|Any CPU
- {6143F625-C2DC-4B25-854C-9A3B9CB20A83}.Release|x86.Build.0 = Release|Any CPU
{75ADCD47-079E-4628-A920-659482F4A030}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{75ADCD47-079E-4628-A920-659482F4A030}.Debug|Any CPU.Build.0 = Debug|Any CPU
{75ADCD47-079E-4628-A920-659482F4A030}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -328,18 +310,6 @@ Global
{CCE71F35-DCD5-4008-9DC5-677431E87494}.Release|x64.Build.0 = Release|Any CPU
{CCE71F35-DCD5-4008-9DC5-677431E87494}.Release|x86.ActiveCfg = Release|Any CPU
{CCE71F35-DCD5-4008-9DC5-677431E87494}.Release|x86.Build.0 = Release|Any CPU
- {30A74B33-E707-4942-8B97-59D714106D94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {30A74B33-E707-4942-8B97-59D714106D94}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {30A74B33-E707-4942-8B97-59D714106D94}.Debug|x64.ActiveCfg = Debug|Any CPU
- {30A74B33-E707-4942-8B97-59D714106D94}.Debug|x64.Build.0 = Debug|Any CPU
- {30A74B33-E707-4942-8B97-59D714106D94}.Debug|x86.ActiveCfg = Debug|Any CPU
- {30A74B33-E707-4942-8B97-59D714106D94}.Debug|x86.Build.0 = Debug|Any CPU
- {30A74B33-E707-4942-8B97-59D714106D94}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {30A74B33-E707-4942-8B97-59D714106D94}.Release|Any CPU.Build.0 = Release|Any CPU
- {30A74B33-E707-4942-8B97-59D714106D94}.Release|x64.ActiveCfg = Release|Any CPU
- {30A74B33-E707-4942-8B97-59D714106D94}.Release|x64.Build.0 = Release|Any CPU
- {30A74B33-E707-4942-8B97-59D714106D94}.Release|x86.ActiveCfg = Release|Any CPU
- {30A74B33-E707-4942-8B97-59D714106D94}.Release|x86.Build.0 = Release|Any CPU
{44B80D37-F395-40CF-8BB6-9AAEB5606672}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{44B80D37-F395-40CF-8BB6-9AAEB5606672}.Debug|Any CPU.Build.0 = Debug|Any CPU
{44B80D37-F395-40CF-8BB6-9AAEB5606672}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -352,18 +322,6 @@ Global
{44B80D37-F395-40CF-8BB6-9AAEB5606672}.Release|x64.Build.0 = Release|Any CPU
{44B80D37-F395-40CF-8BB6-9AAEB5606672}.Release|x86.ActiveCfg = Release|Any CPU
{44B80D37-F395-40CF-8BB6-9AAEB5606672}.Release|x86.Build.0 = Release|Any CPU
- {DAD4C83F-8C86-4099-AA2A-EFCF1F5D5459}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {DAD4C83F-8C86-4099-AA2A-EFCF1F5D5459}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {DAD4C83F-8C86-4099-AA2A-EFCF1F5D5459}.Debug|x64.ActiveCfg = Debug|Any CPU
- {DAD4C83F-8C86-4099-AA2A-EFCF1F5D5459}.Debug|x64.Build.0 = Debug|Any CPU
- {DAD4C83F-8C86-4099-AA2A-EFCF1F5D5459}.Debug|x86.ActiveCfg = Debug|Any CPU
- {DAD4C83F-8C86-4099-AA2A-EFCF1F5D5459}.Debug|x86.Build.0 = Debug|Any CPU
- {DAD4C83F-8C86-4099-AA2A-EFCF1F5D5459}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {DAD4C83F-8C86-4099-AA2A-EFCF1F5D5459}.Release|Any CPU.Build.0 = Release|Any CPU
- {DAD4C83F-8C86-4099-AA2A-EFCF1F5D5459}.Release|x64.ActiveCfg = Release|Any CPU
- {DAD4C83F-8C86-4099-AA2A-EFCF1F5D5459}.Release|x64.Build.0 = Release|Any CPU
- {DAD4C83F-8C86-4099-AA2A-EFCF1F5D5459}.Release|x86.ActiveCfg = Release|Any CPU
- {DAD4C83F-8C86-4099-AA2A-EFCF1F5D5459}.Release|x86.Build.0 = Release|Any CPU
{491D6953-5267-463F-9796-E9906B2FE516}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{491D6953-5267-463F-9796-E9906B2FE516}.Debug|Any CPU.Build.0 = Debug|Any CPU
{491D6953-5267-463F-9796-E9906B2FE516}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -448,9 +406,7 @@ Global
{75ADCD47-079E-4628-A920-659482F4A030} = {821F3F43-E221-4507-95BD-64843868AC11}
{01128CF6-4519-436E-B21F-F691DC6A9832} = {821F3F43-E221-4507-95BD-64843868AC11}
{CCE71F35-DCD5-4008-9DC5-677431E87494} = {821F3F43-E221-4507-95BD-64843868AC11}
- {30A74B33-E707-4942-8B97-59D714106D94} = {54B3835F-17DD-4749-B40D-1533BD81D36C}
{44B80D37-F395-40CF-8BB6-9AAEB5606672} = {821F3F43-E221-4507-95BD-64843868AC11}
- {DAD4C83F-8C86-4099-AA2A-EFCF1F5D5459} = {54B3835F-17DD-4749-B40D-1533BD81D36C}
{15BE78E3-355F-4B15-ABB4-FA750B2D846B} = {54B3835F-17DD-4749-B40D-1533BD81D36C}
{7A6963D6-1F40-4CC6-9941-7F912252F877} = {732A897A-76AE-41E3-A7E4-55F16C1D56EB}
EndGlobalSection
diff --git a/src/AzureFunctionPackage/AzureFunctionPackage.csproj b/src/AzureFunctionPackage/AzureFunctionPackage.csproj
deleted file mode 100644
index 1ea1a25d65..0000000000
--- a/src/AzureFunctionPackage/AzureFunctionPackage.csproj
+++ /dev/null
@@ -1,77 +0,0 @@
-
-
-
-
-
- net46
- $(OutputPath)\package
- $(OutputPath)\$(MSBuildThisFileName).zip
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/AzureFunctionPackage/CreateZipPackage.ps1 b/src/AzureFunctionPackage/CreateZipPackage.ps1
deleted file mode 100644
index 0f0e674ef4..0000000000
--- a/src/AzureFunctionPackage/CreateZipPackage.ps1
+++ /dev/null
@@ -1,7 +0,0 @@
-param (
- [string]$sourceDirectoryName,
- [string]$destinationArchiveFileName
-)
-
-Add-Type -AssemblyName 'System.IO.Compression.FileSystem'
-[System.IO.Compression.ZipFile]::CreateFromDirectory($sourceDirectoryName, $destinationArchiveFileName)
diff --git a/src/AzureFunctionPackage/Functions/Common/VstsPrConfig.xml b/src/AzureFunctionPackage/Functions/Common/VstsPrConfig.xml
deleted file mode 100644
index 0e602f7213..0000000000
--- a/src/AzureFunctionPackage/Functions/Common/VstsPrConfig.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
diff --git a/src/AzureFunctionPackage/Functions/Common/auth.csx b/src/AzureFunctionPackage/Functions/Common/auth.csx
deleted file mode 100644
index 20ae3e5fe5..0000000000
--- a/src/AzureFunctionPackage/Functions/Common/auth.csx
+++ /dev/null
@@ -1,26 +0,0 @@
-#r "System.Web"
-
-using Microsoft.Azure.KeyVault;
-using Microsoft.IdentityModel.Clients.ActiveDirectory;
-using System.Web.Configuration;
-using static System.Environment;
-
-private const string KeyVaultUrl = "https://roslyninfra.vault.azure.net:443";
-
-public static async Task GetSecret(string secretName)
-{
- var kv = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(GetAccessToken));
- var secret = await kv.GetSecretAsync(KeyVaultUrl, secretName);
- return secret.Value;
-}
-
-private static async Task GetAccessToken(string authority, string resource, string scope)
-{
- var ctx = new AuthenticationContext(authority);
- var clientId = WebConfigurationManager.AppSettings["ClientId"];
- var clientSecret = WebConfigurationManager.AppSettings["ClientSecret"];
- var clientCred = new ClientCredential(clientId, clientSecret);
-
- var authResult = await ctx.AcquireTokenAsync(resource, clientCred);
- return authResult.AccessToken;
-}
diff --git a/src/AzureFunctionPackage/Functions/Directory.Build.targets b/src/AzureFunctionPackage/Functions/Directory.Build.targets
deleted file mode 100644
index 6ba7a5027b..0000000000
--- a/src/AzureFunctionPackage/Functions/Directory.Build.targets
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- $(OutputPath)\AzureFunctionFiles
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/AzureFunctionPackage/Functions/VstsCreateMergePRs/Program.cs b/src/AzureFunctionPackage/Functions/VstsCreateMergePRs/Program.cs
deleted file mode 100644
index e2060063cf..0000000000
--- a/src/AzureFunctionPackage/Functions/VstsCreateMergePRs/Program.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the License.txt file in the project root for more information.
-public class Program
-{
- public static void Main(string[] args)
- {
- // This isn't really a C# project, we just need to re-use a bunch of the targets that are
- // automatically pulled in for .csproj. Because of this we need to have an empty Program.cs.
- }
-}
diff --git a/src/AzureFunctionPackage/Functions/VstsCreateMergePRs/VstsCreateMergePRs.csproj b/src/AzureFunctionPackage/Functions/VstsCreateMergePRs/VstsCreateMergePRs.csproj
deleted file mode 100644
index b41e893f54..0000000000
--- a/src/AzureFunctionPackage/Functions/VstsCreateMergePRs/VstsCreateMergePRs.csproj
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-
-
-
- Exe
- net46
-
-
-
-
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/AzureFunctionPackage/Functions/VstsCreateMergePRs/function.json b/src/AzureFunctionPackage/Functions/VstsCreateMergePRs/function.json
deleted file mode 100644
index a93a919ec7..0000000000
--- a/src/AzureFunctionPackage/Functions/VstsCreateMergePRs/function.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "bindings": [
- {
- "type": "timerTrigger",
- "name": "myTimer",
- "schedule": "0 0 */12 * * *",
- "direction": "in"
- }
- ],
- "disabled": true
-}
diff --git a/src/AzureFunctionPackage/Functions/VstsCreateMergePRs/project.json b/src/AzureFunctionPackage/Functions/VstsCreateMergePRs/project.json
deleted file mode 100644
index 90a07c02a4..0000000000
--- a/src/AzureFunctionPackage/Functions/VstsCreateMergePRs/project.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "frameworks": {
- "net46": {
- "comment": "NOTE: The dependencies listed here must be duplicated in the .csproj for the Azure Function to work.",
- "dependencies": {
- "LibGit2Sharp": "0.22.0",
- "Microsoft.IdentityModel.Clients.ActiveDirectory": "3.13.8",
- "Microsoft.TeamFoundationServer.Client": "15.112.1",
- "Microsoft.TeamFoundationServer.ExtendedClient": "15.112.1",
- "Microsoft.WindowsAzure.ConfigurationManager": "3.2.1",
- "System.ValueTuple": "4.3.1",
- "Microsoft.Azure.KeyVault": "2.0.6"
- }
- }
- }
-}
diff --git a/src/AzureFunctionPackage/Functions/VstsCreateMergePRs/run.csx b/src/AzureFunctionPackage/Functions/VstsCreateMergePRs/run.csx
deleted file mode 100644
index 2c3189b85a..0000000000
--- a/src/AzureFunctionPackage/Functions/VstsCreateMergePRs/run.csx
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-
-#r "System.Xml.Linq"
-#r ".\VstsMergeTool.dll"
-
-#load "auth.csx"
-
-using System;
-using System.IO;
-using System.Net;
-using System.Threading.Tasks;
-using System.Xml.Linq;
-
-private static TraceWriter Log = null;
-
-private static async Task MakeVstsPr(string repoName, string srcBranch, string destBranch)
-{
- Log.Info($"Merging {repoName} from {srcBranch} to {destBranch}");
-
- var vstsInitializer = new VstsMergeTool.Initializer(srcBranch, destBranch);
-
- var (prCreated, errorMessage) = await vstsInitializer.MergeTool.CreatePullRequest();
-
- if (prCreated)
- {
- Log.Info("PR created successfully");
- }
- else if(errorMessage == null)
- {
- Log.Info("PR creation skipped. PR already exists or all commits are present in base branch.");
- }
- else
- {
- Log.Error($"Could not create PR. {errorMessage}");
- }
-}
-
-private static async Task RunAsync(ExecutionContext context)
-{
- var configPath = Path.Combine(context.FunctionDirectory, "VstsPrConfig.xml");
- var config = XDocument.Load(configPath).Root;
- foreach (var repo in config.Elements("repo"))
- {
- var repoName = repo.Attribute("name").Value;
- foreach (var merge in repo.Elements("merge"))
- {
- var fromBranch = merge.Attribute("from").Value;
- var toBranch = merge.Attribute("to").Value;
- await MakeVstsPr(repoName, fromBranch, toBranch);
- }
- }
-}
-
-public static void Run(TimerInfo myTimer, TraceWriter log, ExecutionContext context)
-{
- Log = log;
-
- log.Info($"C# Timer trigger function executed at: {DateTime.Now}");
-
- RunAsync(context).GetAwaiter().GetResult();
-}
diff --git a/src/AzureFunctionPackage/Program.cs b/src/AzureFunctionPackage/Program.cs
deleted file mode 100644
index 28b48479ce..0000000000
--- a/src/AzureFunctionPackage/Program.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the License.txt file in the project root for more information.
-namespace AzureFunctions
-{
- public class Program
- {
- public static void Main(string[] args)
- {
- }
- }
-}
diff --git a/src/AzureFunctionPackage/host.json b/src/AzureFunctionPackage/host.json
deleted file mode 100644
index 2972c535b3..0000000000
--- a/src/AzureFunctionPackage/host.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "functionTimeout": "00:10:00"
-}
diff --git a/src/BuildCleanupTool/BuildCleanupTool.csproj b/src/BuildCleanupTool/BuildCleanupTool.csproj
deleted file mode 100644
index 3c620789ff..0000000000
--- a/src/BuildCleanupTool/BuildCleanupTool.csproj
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
- Exe
- net46
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/BuildCleanupTool/Mono.Options/Options.cs b/src/BuildCleanupTool/Mono.Options/Options.cs
deleted file mode 100644
index 7dd6255e16..0000000000
--- a/src/BuildCleanupTool/Mono.Options/Options.cs
+++ /dev/null
@@ -1,1435 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the License.txt file in the project root for more information.
-
-// Compile With:
-// gmcs -debug+ -r:System.Core Options.cs -o:NDesk.Options.dll
-// gmcs -debug+ -d:LINQ -r:System.Core Options.cs -o:NDesk.Options.dll
-//
-// The LINQ version just changes the implementation of
-// OptionSet.Parse(IEnumerable), and confers no semantic changes.
-
-//
-// A Getopt::Long-inspired option parsing library for C#.
-//
-// NDesk.Options.OptionSet is built upon a key/value table, where the
-// key is a option format string and the value is a delegate that is
-// invoked when the format string is matched.
-//
-// Option format strings:
-// Regex-like BNF Grammar:
-// name: .+
-// type: [=:]
-// sep: ( [^{}]+ | '{' .+ '}' )?
-// aliases: ( name type sep ) ( '|' name type sep )*
-//
-// Each '|'-delimited name is an alias for the associated action. If the
-// format string ends in a '=', it has a required value. If the format
-// string ends in a ':', it has an optional value. If neither '=' or ':'
-// is present, no value is supported. `=' or `:' need only be defined on one
-// alias, but if they are provided on more than one they must be consistent.
-//
-// Each alias portion may also end with a "key/value separator", which is used
-// to split option values if the option accepts > 1 value. If not specified,
-// it defaults to '=' and ':'. If specified, it can be any character except
-// '{' and '}' OR the *string* between '{' and '}'. If no separator should be
-// used (i.e. the separate values should be distinct arguments), then "{}"
-// should be used as the separator.
-//
-// Options are extracted either from the current option by looking for
-// the option name followed by an '=' or ':', or is taken from the
-// following option IFF:
-// - The current option does not contain a '=' or a ':'
-// - The current option requires a value (i.e. not a Option type of ':')
-//
-// The `name' used in the option format string does NOT include any leading
-// option indicator, such as '-', '--', or '/'. All three of these are
-// permitted/required on any named option.
-//
-// Option bundling is permitted so long as:
-// - '-' is used to start the option group
-// - all of the bundled options are a single character
-// - at most one of the bundled options accepts a value, and the value
-// provided starts from the next character to the end of the string.
-//
-// This allows specifying '-a -b -c' as '-abc', and specifying '-D name=value'
-// as '-Dname=value'.
-//
-// Option processing is disabled by specifying "--". All options after "--"
-// are returned by OptionSet.Parse() unchanged and unprocessed.
-//
-// Unprocessed options are returned from OptionSet.Parse().
-//
-// Examples:
-// int verbose = 0;
-// OptionSet p = new OptionSet ()
-// .Add ("v", v => ++verbose)
-// .Add ("name=|value=", v => Console.WriteLine (v));
-// p.Parse (new string[]{"-v", "--v", "/v", "-name=A", "/name", "B", "extra"});
-//
-// The above would parse the argument string array, and would invoke the
-// lambda expression three times, setting `verbose' to 3 when complete.
-// It would also print out "A" and "B" to standard output.
-// The returned array would contain the string "extra".
-//
-// C# 3.0 collection initializers are supported and encouraged:
-// var p = new OptionSet () {
-// { "h|?|help", v => ShowHelp () },
-// };
-//
-// System.ComponentModel.TypeConverter is also supported, allowing the use of
-// custom data types in the callback type; TypeConverter.ConvertFromString()
-// is used to convert the value option to an instance of the specified
-// type:
-//
-// var p = new OptionSet () {
-// { "foo=", (Foo f) => Console.WriteLine (f.ToString ()) },
-// };
-//
-// Random other tidbits:
-// - Boolean options (those w/o '=' or ':' in the option format string)
-// are explicitly enabled if they are followed with '+', and explicitly
-// disabled if they are followed with '-':
-// string a = null;
-// var p = new OptionSet () {
-// { "a", s => a = s },
-// };
-// p.Parse (new string[]{"-a"}); // sets v != null
-// p.Parse (new string[]{"-a+"}); // sets v != null
-// p.Parse (new string[]{"-a-"}); // sets v == null
-//
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.ComponentModel;
-using System.Globalization;
-using System.IO;
-using System.Runtime.Serialization;
-using System.Security.Permissions;
-using System.Text;
-using System.Text.RegularExpressions;
-
-#if LINQ
-using System.Linq;
-#endif
-
-#if TEST
-using NDesk.Options;
-#endif
-
-#if NDESK_OPTIONS
-namespace NDesk.Options
-#else
-namespace Mono.Options
-#endif
-{
- static class StringCoda
- {
-
- public static IEnumerable WrappedLines(string self, params int[] widths)
- {
- IEnumerable w = widths;
- return WrappedLines(self, w);
- }
-
- public static IEnumerable WrappedLines(string self, IEnumerable widths)
- {
- if (widths == null)
- throw new ArgumentNullException("widths");
- return CreateWrappedLinesIterator(self, widths);
- }
-
- private static IEnumerable CreateWrappedLinesIterator(string self, IEnumerable widths)
- {
- if (string.IsNullOrEmpty(self))
- {
- yield return string.Empty;
- yield break;
- }
- using (IEnumerator ewidths = widths.GetEnumerator())
- {
- bool? hw = null;
- int width = GetNextWidth(ewidths, int.MaxValue, ref hw);
- int start = 0, end;
- do
- {
- end = GetLineEnd(start, width, self);
- char c = self[end - 1];
- if (char.IsWhiteSpace(c))
- --end;
- bool needContinuation = end != self.Length && !IsEolChar(c);
- string continuation = "";
- if (needContinuation)
- {
- --end;
- continuation = "-";
- }
- string line = self.Substring(start, end - start) + continuation;
- yield return line;
- start = end;
- if (char.IsWhiteSpace(c))
- ++start;
- width = GetNextWidth(ewidths, width, ref hw);
- } while (start < self.Length);
- }
- }
-
- private static int GetNextWidth(IEnumerator ewidths, int curWidth, ref bool? eValid)
- {
- if (!eValid.HasValue || (eValid.HasValue && eValid.Value))
- {
- curWidth = (eValid = ewidths.MoveNext()).Value ? ewidths.Current : curWidth;
- // '.' is any character, - is for a continuation
- const string minWidth = ".-";
- if (curWidth < minWidth.Length)
- throw new ArgumentOutOfRangeException("widths",
- string.Format("Element must be >= {0}, was {1}.", minWidth.Length, curWidth));
- return curWidth;
- }
- // no more elements, use the last element.
- return curWidth;
- }
-
- private static bool IsEolChar(char c)
- {
- return !char.IsLetterOrDigit(c);
- }
-
- private static int GetLineEnd(int start, int length, string description)
- {
- int end = System.Math.Min(start + length, description.Length);
- int sep = -1;
- for (int i = start; i < end; ++i)
- {
- if (description[i] == '\n')
- return i + 1;
- if (IsEolChar(description[i]))
- sep = i + 1;
- }
- if (sep == -1 || end == description.Length)
- return end;
- return sep;
- }
- }
-
- public class OptionValueCollection : IList, IList
- {
-
- List values = new List();
- OptionContext c;
-
- internal OptionValueCollection(OptionContext c)
- {
- this.c = c;
- }
-
- #region ICollection
- void ICollection.CopyTo(Array array, int index) { (values as ICollection).CopyTo(array, index); }
- bool ICollection.IsSynchronized { get { return (values as ICollection).IsSynchronized; } }
- object ICollection.SyncRoot { get { return (values as ICollection).SyncRoot; } }
- #endregion
-
- #region ICollection
- public void Add(string item) { values.Add(item); }
- public void Clear() { values.Clear(); }
- public bool Contains(string item) { return values.Contains(item); }
- public void CopyTo(string[] array, int arrayIndex) { values.CopyTo(array, arrayIndex); }
- public bool Remove(string item) { return values.Remove(item); }
- public int Count { get { return values.Count; } }
- public bool IsReadOnly { get { return false; } }
- #endregion
-
- #region IEnumerable
- IEnumerator IEnumerable.GetEnumerator() { return values.GetEnumerator(); }
- #endregion
-
- #region IEnumerable
- public IEnumerator GetEnumerator() { return values.GetEnumerator(); }
- #endregion
-
- #region IList
- int IList.Add(object value) { return (values as IList).Add(value); }
- bool IList.Contains(object value) { return (values as IList).Contains(value); }
- int IList.IndexOf(object value) { return (values as IList).IndexOf(value); }
- void IList.Insert(int index, object value) { (values as IList).Insert(index, value); }
- void IList.Remove(object value) { (values as IList).Remove(value); }
- void IList.RemoveAt(int index) { (values as IList).RemoveAt(index); }
- bool IList.IsFixedSize { get { return false; } }
- object IList.this[int index] { get { return this[index]; } set { (values as IList)[index] = value; } }
- #endregion
-
- #region IList
- public int IndexOf(string item) { return values.IndexOf(item); }
- public void Insert(int index, string item) { values.Insert(index, item); }
- public void RemoveAt(int index) { values.RemoveAt(index); }
-
- private void AssertValid(int index)
- {
- if (c.Option == null)
- throw new InvalidOperationException("OptionContext.Option is null.");
- if (index >= c.Option.MaxValueCount)
- throw new ArgumentOutOfRangeException("index");
- if (c.Option.OptionValueType == OptionValueType.Required &&
- index >= values.Count)
- throw new OptionException(string.Format(
- c.OptionSet.MessageLocalizer("Missing required value for option '{0}'."), c.OptionName),
- c.OptionName);
- }
-
- public string this[int index]
- {
- get
- {
- AssertValid(index);
- return index >= values.Count ? null : values[index];
- }
- set
- {
- values[index] = value;
- }
- }
- #endregion
-
- public List ToList()
- {
- return new List(values);
- }
-
- public string[] ToArray()
- {
- return values.ToArray();
- }
-
- public override string ToString()
- {
- return string.Join(", ", values.ToArray());
- }
- }
-
- public class OptionContext
- {
- private Option option;
- private string name;
- private int index;
- private OptionSet set;
- private OptionValueCollection c;
-
- public OptionContext(OptionSet set)
- {
- this.set = set;
- this.c = new OptionValueCollection(this);
- }
-
- public Option Option
- {
- get { return option; }
- set { option = value; }
- }
-
- public string OptionName
- {
- get { return name; }
- set { name = value; }
- }
-
- public int OptionIndex
- {
- get { return index; }
- set { index = value; }
- }
-
- public OptionSet OptionSet
- {
- get { return set; }
- }
-
- public OptionValueCollection OptionValues
- {
- get { return c; }
- }
- }
-
- public enum OptionValueType
- {
- None,
- Optional,
- Required,
- }
-
- public abstract class Option
- {
- string prototype, description;
- string[] names;
- OptionValueType type;
- int count;
- string[] separators;
- bool hidden;
-
- protected Option(string prototype, string description)
- : this(prototype, description, 1, false)
- {
- }
-
- protected Option(string prototype, string description, int maxValueCount)
- : this(prototype, description, maxValueCount, false)
- {
- }
-
- protected Option(string prototype, string description, int maxValueCount, bool hidden)
- {
- if (prototype == null)
- throw new ArgumentNullException("prototype");
- if (prototype.Length == 0)
- throw new ArgumentException("Cannot be the empty string.", "prototype");
- if (maxValueCount < 0)
- throw new ArgumentOutOfRangeException("maxValueCount");
-
- this.prototype = prototype;
- this.description = description;
- this.count = maxValueCount;
- this.names = (this is OptionSet.Category)
- // append GetHashCode() so that "duplicate" categories have distinct
- // names, e.g. adding multiple "" categories should be valid.
- ? new[] { prototype + this.GetHashCode() }
- : prototype.Split('|');
-
- if (this is OptionSet.Category)
- return;
-
- this.type = ParsePrototype();
- this.hidden = hidden;
-
- if (this.count == 0 && type != OptionValueType.None)
- throw new ArgumentException(
- "Cannot provide maxValueCount of 0 for OptionValueType.Required or " +
- "OptionValueType.Optional.",
- "maxValueCount");
- if (this.type == OptionValueType.None && maxValueCount > 1)
- throw new ArgumentException(
- string.Format("Cannot provide maxValueCount of {0} for OptionValueType.None.", maxValueCount),
- "maxValueCount");
- if (Array.IndexOf(names, "<>") >= 0 &&
- ((names.Length == 1 && this.type != OptionValueType.None) ||
- (names.Length > 1 && this.MaxValueCount > 1)))
- throw new ArgumentException(
- "The default option handler '<>' cannot require values.",
- "prototype");
- }
-
- public string Prototype { get { return prototype; } }
- public string Description { get { return description; } }
- public OptionValueType OptionValueType { get { return type; } }
- public int MaxValueCount { get { return count; } }
- public bool Hidden { get { return hidden; } }
-
- public string[] GetNames()
- {
- return (string[])names.Clone();
- }
-
- public string[] GetValueSeparators()
- {
- if (separators == null)
- return new string[0];
- return (string[])separators.Clone();
- }
-
- protected static T Parse(string value, OptionContext c)
- {
- Type tt = typeof(T);
- bool nullable = tt.IsValueType && tt.IsGenericType &&
- !tt.IsGenericTypeDefinition &&
- tt.GetGenericTypeDefinition() == typeof(Nullable<>);
- Type targetType = nullable ? tt.GetGenericArguments()[0] : typeof(T);
- TypeConverter conv = TypeDescriptor.GetConverter(targetType);
- T t = default(T);
- try
- {
- if (value != null)
- t = (T)conv.ConvertFromString(value);
- }
- catch (Exception e)
- {
- throw new OptionException(
- string.Format(
- c.OptionSet.MessageLocalizer("Could not convert string `{0}' to type {1} for option `{2}'."),
- value, targetType.Name, c.OptionName),
- c.OptionName, e);
- }
- return t;
- }
-
- internal string[] Names { get { return names; } }
- internal string[] ValueSeparators { get { return separators; } }
-
- static readonly char[] NameTerminator = new char[] { '=', ':' };
-
- private OptionValueType ParsePrototype()
- {
- char type = '\0';
- List seps = new List();
- for (int i = 0; i < names.Length; ++i)
- {
- string name = names[i];
- if (name.Length == 0)
- throw new ArgumentException("Empty option names are not supported.", "prototype");
-
- int end = name.IndexOfAny(NameTerminator);
- if (end == -1)
- continue;
- names[i] = name.Substring(0, end);
- if (type == '\0' || type == name[end])
- type = name[end];
- else
- throw new ArgumentException(
- string.Format("Conflicting option types: '{0}' vs. '{1}'.", type, name[end]),
- "prototype");
- AddSeparators(name, end, seps);
- }
-
- if (type == '\0')
- return OptionValueType.None;
-
- if (count <= 1 && seps.Count != 0)
- throw new ArgumentException(
- string.Format("Cannot provide key/value separators for Options taking {0} value(s).", count),
- "prototype");
- if (count > 1)
- {
- if (seps.Count == 0)
- this.separators = new string[] { ":", "=" };
- else if (seps.Count == 1 && seps[0].Length == 0)
- this.separators = null;
- else
- this.separators = seps.ToArray();
- }
-
- return type == '=' ? OptionValueType.Required : OptionValueType.Optional;
- }
-
- private static void AddSeparators(string name, int end, ICollection seps)
- {
- int start = -1;
- for (int i = end + 1; i < name.Length; ++i)
- {
- switch (name[i])
- {
- case '{':
- if (start != -1)
- throw new ArgumentException(
- string.Format("Ill-formed name/value separator found in \"{0}\".", name),
- "prototype");
- start = i + 1;
- break;
- case '}':
- if (start == -1)
- throw new ArgumentException(
- string.Format("Ill-formed name/value separator found in \"{0}\".", name),
- "prototype");
- seps.Add(name.Substring(start, i - start));
- start = -1;
- break;
- default:
- if (start == -1)
- seps.Add(name[i].ToString());
- break;
- }
- }
- if (start != -1)
- throw new ArgumentException(
- string.Format("Ill-formed name/value separator found in \"{0}\".", name),
- "prototype");
- }
-
- public void Invoke(OptionContext c)
- {
- OnParseComplete(c);
- c.OptionName = null;
- c.Option = null;
- c.OptionValues.Clear();
- }
-
- protected abstract void OnParseComplete(OptionContext c);
-
- public override string ToString()
- {
- return Prototype;
- }
- }
-
- public abstract class ArgumentSource
- {
-
- protected ArgumentSource()
- {
- }
-
- public abstract string[] GetNames();
- public abstract string Description { get; }
- public abstract bool GetArguments(string value, out IEnumerable replacement);
-
- public static IEnumerable GetArgumentsFromFile(string file)
- {
- return GetArguments(File.OpenText(file), true);
- }
-
- public static IEnumerable GetArguments(TextReader reader)
- {
- return GetArguments(reader, false);
- }
-
- // Cribbed from mcs/driver.cs:LoadArgs(string)
- static IEnumerable GetArguments(TextReader reader, bool close)
- {
- try
- {
- StringBuilder arg = new StringBuilder();
-
- string line;
- while ((line = reader.ReadLine()) != null)
- {
- int t = line.Length;
-
- for (int i = 0; i < t; i++)
- {
- char c = line[i];
-
- if (c == '"' || c == '\'')
- {
- char end = c;
-
- for (i++; i < t; i++)
- {
- c = line[i];
-
- if (c == end)
- break;
- arg.Append(c);
- }
- }
- else if (c == ' ')
- {
- if (arg.Length > 0)
- {
- yield return arg.ToString();
- arg.Length = 0;
- }
- }
- else
- arg.Append(c);
- }
- if (arg.Length > 0)
- {
- yield return arg.ToString();
- arg.Length = 0;
- }
- }
- }
- finally
- {
- if (close)
- reader.Close();
- }
- }
- }
-
- public class ResponseFileSource : ArgumentSource
- {
-
- public override string[] GetNames()
- {
- return new string[] { "@file" };
- }
-
- public override string Description
- {
- get { return "Read response file for more options."; }
- }
-
- public override bool GetArguments(string value, out IEnumerable replacement)
- {
- if (string.IsNullOrEmpty(value) || !value.StartsWith("@"))
- {
- replacement = null;
- return false;
- }
- replacement = ArgumentSource.GetArgumentsFromFile(value.Substring(1));
- return true;
- }
- }
-
- [Serializable]
- public class OptionException : Exception
- {
- private string option;
-
- public OptionException()
- {
- }
-
- public OptionException(string message, string optionName)
- : base(message)
- {
- this.option = optionName;
- }
-
- public OptionException(string message, string optionName, Exception innerException)
- : base(message, innerException)
- {
- this.option = optionName;
- }
-
- protected OptionException(SerializationInfo info, StreamingContext context)
- : base(info, context)
- {
- this.option = info.GetString("OptionName");
- }
-
- public string OptionName
- {
- get { return this.option; }
- }
-
- [SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)]
- public override void GetObjectData(SerializationInfo info, StreamingContext context)
- {
- base.GetObjectData(info, context);
- info.AddValue("OptionName", option);
- }
- }
-
- public delegate void OptionAction(TKey key, TValue value);
-
- public class OptionSet : KeyedCollection
- {
- public OptionSet()
- : this(delegate (string f) { return f; })
- {
- }
-
- public OptionSet(Converter localizer)
- {
- this.localizer = localizer;
- this.roSources = new ReadOnlyCollection(sources);
- }
-
- Converter localizer;
-
- public Converter MessageLocalizer
- {
- get { return localizer; }
- }
-
- List sources = new List();
- ReadOnlyCollection roSources;
-
- public ReadOnlyCollection ArgumentSources
- {
- get { return roSources; }
- }
-
-
- protected override string GetKeyForItem(Option item)
- {
- if (item == null)
- throw new ArgumentNullException("option");
- if (item.Names != null && item.Names.Length > 0)
- return item.Names[0];
- // This should never happen, as it's invalid for Option to be
- // constructed w/o any names.
- throw new InvalidOperationException("Option has no names!");
- }
-
- [Obsolete("Use KeyedCollection.this[string]")]
- protected Option GetOptionForName(string option)
- {
- if (option == null)
- throw new ArgumentNullException("option");
- try
- {
- return base[option];
- }
- catch (KeyNotFoundException)
- {
- return null;
- }
- }
-
- protected override void InsertItem(int index, Option item)
- {
- base.InsertItem(index, item);
- AddImpl(item);
- }
-
- protected override void RemoveItem(int index)
- {
- Option p = Items[index];
- base.RemoveItem(index);
- // KeyedCollection.RemoveItem() handles the 0th item
- for (int i = 1; i < p.Names.Length; ++i)
- {
- Dictionary.Remove(p.Names[i]);
- }
- }
-
- protected override void SetItem(int index, Option item)
- {
- base.SetItem(index, item);
- AddImpl(item);
- }
-
- private void AddImpl(Option option)
- {
- if (option == null)
- throw new ArgumentNullException("option");
- List added = new List(option.Names.Length);
- try
- {
- // KeyedCollection.InsertItem/SetItem handle the 0th name.
- for (int i = 1; i < option.Names.Length; ++i)
- {
- Dictionary.Add(option.Names[i], option);
- added.Add(option.Names[i]);
- }
- }
- catch (Exception)
- {
- foreach (string name in added)
- Dictionary.Remove(name);
- throw;
- }
- }
-
- public OptionSet Add(string header)
- {
- if (header == null)
- throw new ArgumentNullException("header");
- Add(new Category(header));
- return this;
- }
-
- internal sealed class Category : Option
- {
-
- // Prototype starts with '=' because this is an invalid prototype
- // (see Option.ParsePrototype(), and thus it'll prevent Category
- // instances from being accidentally used as normal options.
- public Category(string description)
- : base("=:Category:= " + description, description)
- {
- }
-
- protected override void OnParseComplete(OptionContext c)
- {
- throw new NotSupportedException("Category.OnParseComplete should not be invoked.");
- }
- }
-
-
- public new OptionSet Add(Option option)
- {
- base.Add(option);
- return this;
- }
-
- sealed class ActionOption : Option
- {
- Action action;
-
- public ActionOption(string prototype, string description, int count, Action action)
- : this(prototype, description, count, action, false)
- {
- }
-
- public ActionOption(string prototype, string description, int count, Action action, bool hidden)
- : base(prototype, description, count, hidden)
- {
- if (action == null)
- throw new ArgumentNullException("action");
- this.action = action;
- }
-
- protected override void OnParseComplete(OptionContext c)
- {
- action(c.OptionValues);
- }
- }
-
- public OptionSet Add(string prototype, Action action)
- {
- return Add(prototype, null, action);
- }
-
- public OptionSet Add(string prototype, string description, Action action)
- {
- return Add(prototype, description, action, false);
- }
-
- public OptionSet Add(string prototype, string description, Action action, bool hidden)
- {
- if (action == null)
- throw new ArgumentNullException("action");
- Option p = new ActionOption(prototype, description, 1,
- delegate (OptionValueCollection v) { action(v[0]); }, hidden);
- base.Add(p);
- return this;
- }
-
- public OptionSet Add(string prototype, OptionAction action)
- {
- return Add(prototype, null, action);
- }
-
- public OptionSet Add(string prototype, string description, OptionAction action)
- {
- return Add(prototype, description, action, false);
- }
-
- public OptionSet Add(string prototype, string description, OptionAction action, bool hidden)
- {
- if (action == null)
- throw new ArgumentNullException("action");
- Option p = new ActionOption(prototype, description, 2,
- delegate (OptionValueCollection v) { action(v[0], v[1]); }, hidden);
- base.Add(p);
- return this;
- }
-
- sealed class ActionOption : Option
- {
- Action action;
-
- public ActionOption(string prototype, string description, Action action)
- : base(prototype, description, 1)
- {
- if (action == null)
- throw new ArgumentNullException("action");
- this.action = action;
- }
-
- protected override void OnParseComplete(OptionContext c)
- {
- action(Parse(c.OptionValues[0], c));
- }
- }
-
- sealed class ActionOption : Option
- {
- OptionAction action;
-
- public ActionOption(string prototype, string description, OptionAction action)
- : base(prototype, description, 2)
- {
- if (action == null)
- throw new ArgumentNullException("action");
- this.action = action;
- }
-
- protected override void OnParseComplete(OptionContext c)
- {
- action(
- Parse(c.OptionValues[0], c),
- Parse(c.OptionValues[1], c));
- }
- }
-
- public OptionSet Add(string prototype, Action action)
- {
- return Add(prototype, null, action);
- }
-
- public OptionSet Add(string prototype, string description, Action action)
- {
- return Add(new ActionOption(prototype, description, action));
- }
-
- public OptionSet Add(string prototype, OptionAction action)
- {
- return Add(prototype, null, action);
- }
-
- public OptionSet Add(string prototype, string description, OptionAction action)
- {
- return Add(new ActionOption(prototype, description, action));
- }
-
- public OptionSet Add(ArgumentSource source)
- {
- if (source == null)
- throw new ArgumentNullException("source");
- sources.Add(source);
- return this;
- }
-
- protected virtual OptionContext CreateOptionContext()
- {
- return new OptionContext(this);
- }
-
- public List Parse(IEnumerable arguments)
- {
- if (arguments == null)
- throw new ArgumentNullException("arguments");
- OptionContext c = CreateOptionContext();
- c.OptionIndex = -1;
- bool process = true;
- List unprocessed = new List();
- Option def = Contains("<>") ? this["<>"] : null;
- ArgumentEnumerator ae = new ArgumentEnumerator(arguments);
- foreach (string argument in ae)
- {
- ++c.OptionIndex;
- if (argument == "--")
- {
- process = false;
- continue;
- }
- if (!process)
- {
- Unprocessed(unprocessed, def, c, argument);
- continue;
- }
- if (AddSource(ae, argument))
- continue;
- if (!Parse(argument, c))
- Unprocessed(unprocessed, def, c, argument);
- }
- if (c.Option != null)
- c.Option.Invoke(c);
- return unprocessed;
- }
-
- class ArgumentEnumerator : IEnumerable
- {
- List> sources = new List>();
-
- public ArgumentEnumerator(IEnumerable arguments)
- {
- sources.Add(arguments.GetEnumerator());
- }
-
- public void Add(IEnumerable arguments)
- {
- sources.Add(arguments.GetEnumerator());
- }
-
- public IEnumerator GetEnumerator()
- {
- do
- {
- IEnumerator c = sources[sources.Count - 1];
- if (c.MoveNext())
- yield return c.Current;
- else
- {
- c.Dispose();
- sources.RemoveAt(sources.Count - 1);
- }
- } while (sources.Count > 0);
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
- }
-
- bool AddSource(ArgumentEnumerator ae, string argument)
- {
- foreach (ArgumentSource source in sources)
- {
- IEnumerable replacement;
- if (!source.GetArguments(argument, out replacement))
- continue;
- ae.Add(replacement);
- return true;
- }
- return false;
- }
-
- private static bool Unprocessed(ICollection extra, Option def, OptionContext c, string argument)
- {
- if (def == null)
- {
- extra.Add(argument);
- return false;
- }
- c.OptionValues.Add(argument);
- c.Option = def;
- c.Option.Invoke(c);
- return false;
- }
-
- private readonly Regex ValueOption = new Regex(
- @"^(?--|-|/)(?[^:=]+)((?[:=])(?.*))?$");
-
- protected bool GetOptionParts(string argument, out string flag, out string name, out string sep, out string value)
- {
- if (argument == null)
- throw new ArgumentNullException("argument");
-
- flag = name = sep = value = null;
- Match m = ValueOption.Match(argument);
- if (!m.Success)
- {
- return false;
- }
- flag = m.Groups["flag"].Value;
- name = m.Groups["name"].Value;
- if (m.Groups["sep"].Success && m.Groups["value"].Success)
- {
- sep = m.Groups["sep"].Value;
- value = m.Groups["value"].Value;
- }
- return true;
- }
-
- protected virtual bool Parse(string argument, OptionContext c)
- {
- if (c.Option != null)
- {
- ParseValue(argument, c);
- return true;
- }
-
- string f, n, s, v;
- if (!GetOptionParts(argument, out f, out n, out s, out v))
- return false;
-
- Option p;
- if (Contains(n))
- {
- p = this[n];
- c.OptionName = f + n;
- c.Option = p;
- switch (p.OptionValueType)
- {
- case OptionValueType.None:
- c.OptionValues.Add(n);
- c.Option.Invoke(c);
- break;
- case OptionValueType.Optional:
- case OptionValueType.Required:
- ParseValue(v, c);
- break;
- }
- return true;
- }
- // no match; is it a bool option?
- if (ParseBool(argument, n, c))
- return true;
- // is it a bundled option?
- if (ParseBundledValue(f, string.Concat(n + s + v), c))
- return true;
-
- return false;
- }
-
- private void ParseValue(string option, OptionContext c)
- {
- if (option != null)
- foreach (string o in c.Option.ValueSeparators != null
- ? option.Split(c.Option.ValueSeparators, c.Option.MaxValueCount - c.OptionValues.Count, StringSplitOptions.None)
- : new string[] { option })
- {
- c.OptionValues.Add(o);
- }
- if (c.OptionValues.Count == c.Option.MaxValueCount ||
- c.Option.OptionValueType == OptionValueType.Optional)
- c.Option.Invoke(c);
- else if (c.OptionValues.Count > c.Option.MaxValueCount)
- {
- throw new OptionException(localizer(string.Format(
- "Error: Found {0} option values when expecting {1}.",
- c.OptionValues.Count, c.Option.MaxValueCount)),
- c.OptionName);
- }
- }
-
- private bool ParseBool(string option, string n, OptionContext c)
- {
- Option p;
- string rn;
- if (n.Length >= 1 && (n[n.Length - 1] == '+' || n[n.Length - 1] == '-') &&
- Contains((rn = n.Substring(0, n.Length - 1))))
- {
- p = this[rn];
- string v = n[n.Length - 1] == '+' ? option : null;
- c.OptionName = option;
- c.Option = p;
- c.OptionValues.Add(v);
- p.Invoke(c);
- return true;
- }
- return false;
- }
-
- private bool ParseBundledValue(string f, string n, OptionContext c)
- {
- if (f != "-")
- return false;
- for (int i = 0; i < n.Length; ++i)
- {
- Option p;
- string opt = f + n[i].ToString();
- string rn = n[i].ToString();
- if (!Contains(rn))
- {
- if (i == 0)
- return false;
- throw new OptionException(string.Format(localizer(
- "Cannot bundle unregistered option '{0}'."), opt), opt);
- }
- p = this[rn];
- switch (p.OptionValueType)
- {
- case OptionValueType.None:
- Invoke(c, opt, n, p);
- break;
- case OptionValueType.Optional:
- case OptionValueType.Required:
- {
- string v = n.Substring(i + 1);
- c.Option = p;
- c.OptionName = opt;
- ParseValue(v.Length != 0 ? v : null, c);
- return true;
- }
- default:
- throw new InvalidOperationException("Unknown OptionValueType: " + p.OptionValueType);
- }
- }
- return true;
- }
-
- private static void Invoke(OptionContext c, string name, string value, Option option)
- {
- c.OptionName = name;
- c.Option = option;
- c.OptionValues.Add(value);
- option.Invoke(c);
- }
-
- private const int OptionWidth = 29;
- private const int Description_FirstWidth = 80 - OptionWidth;
- private const int Description_RemWidth = 80 - OptionWidth - 2;
-
- public void WriteOptionDescriptions(TextWriter o)
- {
- foreach (Option p in this)
- {
- int written = 0;
-
- if (p.Hidden)
- continue;
-
- Category c = p as Category;
- if (c != null)
- {
- WriteDescription(o, p.Description, "", 80, 80);
- continue;
- }
-
- if (!WriteOptionPrototype(o, p, ref written))
- continue;
-
- if (written < OptionWidth)
- o.Write(new string(' ', OptionWidth - written));
- else
- {
- o.WriteLine();
- o.Write(new string(' ', OptionWidth));
- }
-
- WriteDescription(o, p.Description, new string(' ', OptionWidth + 2),
- Description_FirstWidth, Description_RemWidth);
- }
-
- foreach (ArgumentSource s in sources)
- {
- string[] names = s.GetNames();
- if (names == null || names.Length == 0)
- continue;
-
- int written = 0;
-
- Write(o, ref written, " ");
- Write(o, ref written, names[0]);
- for (int i = 1; i < names.Length; ++i)
- {
- Write(o, ref written, ", ");
- Write(o, ref written, names[i]);
- }
-
- if (written < OptionWidth)
- o.Write(new string(' ', OptionWidth - written));
- else
- {
- o.WriteLine();
- o.Write(new string(' ', OptionWidth));
- }
-
- WriteDescription(o, s.Description, new string(' ', OptionWidth + 2),
- Description_FirstWidth, Description_RemWidth);
- }
- }
-
- void WriteDescription(TextWriter o, string value, string prefix, int firstWidth, int remWidth)
- {
- bool indent = false;
- foreach (string line in GetLines(localizer(GetDescription(value)), firstWidth, remWidth))
- {
- if (indent)
- o.Write(prefix);
- o.WriteLine(line);
- indent = true;
- }
- }
-
- bool WriteOptionPrototype(TextWriter o, Option p, ref int written)
- {
- string[] names = p.Names;
-
- int i = GetNextOptionIndex(names, 0);
- if (i == names.Length)
- return false;
-
- if (names[i].Length == 1)
- {
- Write(o, ref written, " -");
- Write(o, ref written, names[0]);
- }
- else
- {
- Write(o, ref written, " --");
- Write(o, ref written, names[0]);
- }
-
- for (i = GetNextOptionIndex(names, i + 1);
- i < names.Length; i = GetNextOptionIndex(names, i + 1))
- {
- Write(o, ref written, ", ");
- Write(o, ref written, names[i].Length == 1 ? "-" : "--");
- Write(o, ref written, names[i]);
- }
-
- if (p.OptionValueType == OptionValueType.Optional ||
- p.OptionValueType == OptionValueType.Required)
- {
- if (p.OptionValueType == OptionValueType.Optional)
- {
- Write(o, ref written, localizer("["));
- }
- Write(o, ref written, localizer("=" + GetArgumentName(0, p.MaxValueCount, p.Description)));
- string sep = p.ValueSeparators != null && p.ValueSeparators.Length > 0
- ? p.ValueSeparators[0]
- : " ";
- for (int c = 1; c < p.MaxValueCount; ++c)
- {
- Write(o, ref written, localizer(sep + GetArgumentName(c, p.MaxValueCount, p.Description)));
- }
- if (p.OptionValueType == OptionValueType.Optional)
- {
- Write(o, ref written, localizer("]"));
- }
- }
- return true;
- }
-
- static int GetNextOptionIndex(string[] names, int i)
- {
- while (i < names.Length && names[i] == "<>")
- {
- ++i;
- }
- return i;
- }
-
- static void Write(TextWriter o, ref int n, string s)
- {
- n += s.Length;
- o.Write(s);
- }
-
- private static string GetArgumentName(int index, int maxIndex, string description)
- {
- if (description == null)
- return maxIndex == 1 ? "VALUE" : "VALUE" + (index + 1);
- string[] nameStart;
- if (maxIndex == 1)
- nameStart = new string[] { "{0:", "{" };
- else
- nameStart = new string[] { "{" + index + ":" };
- for (int i = 0; i < nameStart.Length; ++i)
- {
- int start, j = 0;
- do
- {
- start = description.IndexOf(nameStart[i], j);
- } while (start >= 0 && j != 0 ? description[j++ - 1] == '{' : false);
- if (start == -1)
- continue;
- int end = description.IndexOf("}", start);
- if (end == -1)
- continue;
- return description.Substring(start + nameStart[i].Length, end - start - nameStart[i].Length);
- }
- return maxIndex == 1 ? "VALUE" : "VALUE" + (index + 1);
- }
-
- private static string GetDescription(string description)
- {
- if (description == null)
- return string.Empty;
- StringBuilder sb = new StringBuilder(description.Length);
- int start = -1;
- for (int i = 0; i < description.Length; ++i)
- {
- switch (description[i])
- {
- case '{':
- if (i == start)
- {
- sb.Append('{');
- start = -1;
- }
- else if (start < 0)
- start = i + 1;
- break;
- case '}':
- if (start < 0)
- {
- if ((i + 1) == description.Length || description[i + 1] != '}')
- throw new InvalidOperationException("Invalid option description: " + description);
- ++i;
- sb.Append("}");
- }
- else
- {
- sb.Append(description.Substring(start, i - start));
- start = -1;
- }
- break;
- case ':':
- if (start < 0)
- goto default;
- start = i + 1;
- break;
- default:
- if (start < 0)
- sb.Append(description[i]);
- break;
- }
- }
- return sb.ToString();
- }
-
- private static IEnumerable GetLines(string description, int firstWidth, int remWidth)
- {
- return StringCoda.WrappedLines(description, firstWidth, remWidth);
- }
- }
-}
-
diff --git a/src/BuildCleanupTool/Program.cs b/src/BuildCleanupTool/Program.cs
deleted file mode 100644
index 7ca33a5c8e..0000000000
--- a/src/BuildCleanupTool/Program.cs
+++ /dev/null
@@ -1,203 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the License.txt file in the project root for more information.
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Threading;
-using System.Threading.Tasks;
-
-using Microsoft.Azure.KeyVault;
-using Microsoft.IdentityModel.Clients.ActiveDirectory;
-using Microsoft.TeamFoundation.Build.WebApi;
-using Microsoft.VisualStudio.Services.Common;
-using Mono.Options;
-
-namespace DeleteDeletedBuilds
-{
- static class Program
- {
- const string ApplicationId = "1950a258-227b-4e31-a9cf-717495945fc2";
- const string KeyVaultUrl = "https://roslyninfra.vault.azure.net:443";
-
- static async Task Main(string[] args)
- {
- string clientId = "";
- string clientSecret = "";
- bool showHelp = false;
- var parser = new OptionSet
- {
- {
- "h|?|help",
- "Show help.",
- h => showHelp = h != null
- },
- {
- "ci=|clientid=",
- "The client ID to use for authentication token retreival.",
- id => clientId = id
- },
- {
- "cs=|clientsecret=",
- "The client secret to use for authentication token retreival.",
- secret => clientSecret = secret
- },
- };
-
- List extraArguments = null;
- try
- {
- extraArguments = parser.Parse(args);
- }
- catch (Exception e)
- {
- Console.WriteLine("Failed to parse arguments.");
- Console.WriteLine(e.Message);
- return 1;
- }
-
- if (extraArguments.Count > 0)
- {
- Console.WriteLine($"Unknown arguments: {string.Join(" ", extraArguments)}");
- return 1;
- }
-
- if (showHelp)
- {
- parser.WriteOptionDescriptions(Console.Out);
- return 0;
- }
-
- try
- {
- var authToken = await GetSecret("vslsnap-vso-auth-token", clientId, clientSecret);
- var client = new BuildHttpClient(new Uri("https://devdiv.visualstudio.com"), new VssBasicCredential("", authToken));
- int buildsProcessed = 0;
-
- var definitions = new List();
- definitions.AddRange(await client.GetDefinitionsAsync(project: "DevDiv", name: "Roslyn-Signed-Legacy-15.6AndEarlier"));
- definitions.AddRange(await client.GetDefinitionsAsync(project: "DevDiv", name: "Roslyn-Signed"));
- definitions.AddRange(await client.GetDefinitionsAsync(project: "DevDiv", name: "TestImpact-Signed"));
-
- foreach (var definition in definitions)
- {
- var folderName = definition.Name == "Roslyn-Signed-Legacy-15.6AndEarlier" ? "Roslyn-Signed" : definition.Name;
-
- string dropBase = $@"\\cpvsbuild\drops\roslyn\{folderName}";
-
- var builds = await client.GetBuildsAsync(definition.Project.Id, definitions: new[] { definition.Id }, deletedFilter: QueryDeletedOption.IncludeDeleted);
-
- foreach (var build in builds)
- {
- if (build.Status == BuildStatus.Completed)
- {
- string dropPath = Path.Combine(dropBase, Path.GetFileName(build.SourceBranch), "Release", build.BuildNumber);
-
- if (Directory.Exists(dropPath))
- {
- bool deleted = build.Deleted;
-
- if (!deleted)
- {
- // HACK: if your retention policy says to keep the build record (but delete everything else),
- // you can't rely on build.Deleted.
- var logs = await client.GetBuildLogsAsync(definition.Project.Id, build.Id);
- var artifacts = await client.GetArtifactsAsync(definition.Project.Id, build.Id);
-
- if (logs == null && artifacts.Count == 0)
- {
- deleted = true;
- }
- }
-
- if (deleted)
- {
- buildsProcessed++;
- Console.WriteLine($"Deleting {dropPath}...");
- try
- {
- Directory.Delete(dropPath, recursive: true);
- }
- catch (UnauthorizedAccessException)
- {
- Console.WriteLine("ACCESS EXCEPTION!");
- }
- catch (DirectoryNotFoundException e)
- {
- Console.WriteLine(e.Message);
- }
- catch (IOException e)
- {
- Console.WriteLine(e.ToString());
- }
- }
- }
- }
- }
-
- /*
- // Also clean up any now empty branch folders
- foreach (var branchFolder in new DirectoryInfo(dropBase).GetDirectories())
- {
- var releaseFolder = branchFolder.GetDirectories("Release").SingleOrDefault();
-
- if (releaseFolder != null)
- {
- releaseFolder.DeleteIfEmpty();
- }
-
- branchFolder.DeleteIfEmpty();
- }
- */
- }
-
- Console.WriteLine($"Builds processed: {buildsProcessed}");
- return 0;
- }
- catch (Exception e)
- {
- Console.WriteLine(e);
- return 1;
- }
- }
-
- private static void DeleteIfEmpty(this DirectoryInfo directoryInfo)
- {
- if (!directoryInfo.GetFileSystemInfos().Any())
- {
- directoryInfo.Delete(recursive: false);
- }
- }
-
- private static async Task GetSecret(string secretName, string clientId, string clientSecret)
- {
- var kv = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(GetAccessTokenFunction(clientId, clientSecret)));
- var secret = await kv.GetSecretAsync(KeyVaultUrl, secretName);
- return secret.Value;
- }
-
- private static Func> GetAccessTokenFunction(string clientId, string clientSecret)
- {
- return async (authority, resource, scope) =>
- {
- var context = new AuthenticationContext(authority);
- AuthenticationResult authResult;
- if (string.IsNullOrEmpty(clientId) || string.IsNullOrEmpty(clientSecret))
- {
- // use default domain authentication
- authResult = await context.AcquireTokenAsync(resource, ApplicationId, new UserCredential());
- }
- else
- {
- // use client authentication from command line arguments
- var credentials = new ClientCredential(clientId, clientSecret);
- authResult = await context.AcquireTokenAsync(resource, credentials);
- }
-
- return authResult.AccessToken;
- };
- }
- }
-}
diff --git a/src/BuildRetainer/BuildRetainer.cs b/src/BuildRetainer/BuildRetainer.cs
deleted file mode 100644
index d87faa06fb..0000000000
--- a/src/BuildRetainer/BuildRetainer.cs
+++ /dev/null
@@ -1,426 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the License.txt file in the project root for more information.
-
-using System;
-using System.Collections.Concurrent;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Text.RegularExpressions;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.Azure.KeyVault;
-using Microsoft.IdentityModel.Clients.ActiveDirectory;
-using Microsoft.TeamFoundation.Build.WebApi;
-using Microsoft.TeamFoundation.SourceControl.WebApi;
-using Microsoft.VisualStudio.Services.WebApi;
-using Microsoft.WindowsAzure.Storage;
-using Microsoft.WindowsAzure.Storage.Auth;
-using Microsoft.WindowsAzure.Storage.Blob;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-
-using WindowsCredential = Microsoft.VisualStudio.Services.Common.WindowsCredential;
-using System.Collections.Generic;
-
-namespace BuildRetainer
-{
- internal class BuildRetainer
- {
- private const string BranchNamePrefix = "refs/heads/";
- private const string ReleasedToPublicTag = "Released to Public";
-
- private Options _options;
-
- public BuildRetainer(Options options)
- {
- _options = options;
- }
-
- private class TagData
- {
- public string TagName { get; set; }
-
- public string ObjectId { get; set; }
-
- ///
- /// The branch the inserted build originated from (i.e. branch names on GitHub).
- ///
- public string InsertedBuildBranch { get; set; }
-
- ///
- /// The build number we inserted.
- ///
- public string InsertedBuildNumber { get; set; }
-
- ///
- /// The raw drop path of the VS drop.
- ///
- public string RawDropPath { get; set; }
-
- ///
- /// Whether the raw drop path is believed to exist. This always starts at true, and we'll switch it to false once we've
- /// observed the folder no longer exists.
- ///
- public bool MaybeExists { get; set; } = true;
-
- public bool IsRelease() => TagName.StartsWith("refs/tags/release/");
- }
-
- public void Run()
- {
- Console.WriteLine($"Retaining builds from [{_options.BuildQueueName}] for component [{_options.ComponentName}].");
-
- var stopwatch = Stopwatch.StartNew();
-
- Console.WriteLine("Getting KeyVault secret...");
- var password = GetSecret(Settings.Default.VsoSecretName, _options).Result;
-
- var uri = new Uri(Settings.Default.VSTSUrl);
- var connection = new VssConnection(uri, new WindowsCredential(new NetworkCredential(Settings.Default.UserName, password)));
-
- Console.WriteLine("Authenticating connection...");
- using (var gitHttpClient = connection.GetClient())
- {
- Console.WriteLine("Finding repository...");
- var allRepos = gitHttpClient.GetRepositoriesAsync().Result;
- var vsRepos = allRepos.Where(r => r.Name == Settings.Default.RepositoryName && r.ProjectReference.Name == Settings.Default.TFSProjectName).ToList();
- if (vsRepos.Count != 1)
- {
- Console.WriteLine($"Expected to find one repository matching {Settings.Default.TFSProjectName}/{Settings.Default.RepositoryName} but found {vsRepos.Count}.");
- Environment.Exit(1);
- }
-
- var vsRepo = vsRepos.Single();
- var vsRepoGuid = vsRepo.Id;
- Console.WriteLine("Getting all tags...");
- var tagRefs = gitHttpClient.GetTagRefsAsync(vsRepoGuid).Result;
-
- var allTagData = ReadCachedTags();
-
- (int numSkipped, int numProcessed, int numFailed, int numCached) operationTracker = (0, 0, 0, 0);
-
- Console.WriteLine();
- Console.WriteLine($"Processing {tagRefs.Count} tags...");
- Parallel.ForEach(tagRefs, (tagRef) =>
- {
- try
- {
- TagData tag;
-
- if (allTagData.TryGetValue(tagRef.Name, out tag) && tag.ObjectId == tagRef.ObjectId)
- {
- Interlocked.Increment(ref operationTracker.numCached);
-
- // We already have the tag and it's data. Let's recheck if it's been expired
- if (tag.MaybeExists)
- {
- tag.MaybeExists = Directory.Exists(tag.RawDropPath);
- }
-
- return;
- }
-
- tag = new TagData();
- tag.TagName = tagRef.Name;
-
- if (!Regex.IsMatch(tagRef.Name, @"refs/tags/drop/.*/official\.\d{5}.\d{2}") && !tag.IsRelease())
- {
- Interlocked.Increment(ref operationTracker.numSkipped);
- return;
- }
-
- tag.ObjectId = tagRef.ObjectId;
-
- var versionDescriptor = new GitVersionDescriptor()
- {
- Version = tagRef.Name.Substring("refs/tags/".Length),
- VersionOptions = GitVersionOptions.None,
- VersionType = GitVersionType.Tag
- };
-
- var annotatedTagDataTask = gitHttpClient.GetAnnotatedTagAsync(Settings.Default.TFSProjectName, vsRepoGuid, tagRef.ObjectId);
- var annotatedTagData = JObject.Parse(annotatedTagDataTask.Result.Message);
-
- tag.RawDropPath = annotatedTagData["RawDropLocation"].Value();
- tag.MaybeExists = Directory.Exists(tag.RawDropPath);
-
- // If the build is already gone, no reason to get the components.json for it
- if (tag.MaybeExists)
- {
- if (!TryUpdateTag(gitHttpClient, vsRepoGuid, tag, versionDescriptor, @".corext\Configs\components.json") &&
- !TryUpdateTag(gitHttpClient, vsRepoGuid, tag, versionDescriptor, @".corext\Configs\dotnetcodeanalysis-components.json") &&
- !TryUpdateTag(gitHttpClient, vsRepoGuid, tag, versionDescriptor, @".corext\Configs\lutandsbd-components.json") &&
- !TryUpdateTag(gitHttpClient, vsRepoGuid, tag, versionDescriptor, @".corext\Configs\dotnetprojectsystem-components.json"))
- {
- throw new Exception("Unable to locate component.");
- }
- }
-
- if (!allTagData.TryAdd(tagRef.Name, tag))
- {
- throw new Exception("Tag already exists which shouldn't have happened.");
- }
-
- Interlocked.Increment(ref operationTracker.numProcessed);
- }
- catch (Exception)
- {
- // Catastrophic error: don't cache anything since we have no idea what happened
- allTagData.TryRemove(tagRef.Name, out _);
- Interlocked.Increment(ref operationTracker.numFailed);
- }
- });
-
- Console.WriteLine($" Processed {operationTracker.numProcessed + operationTracker.numSkipped + operationTracker.numFailed + operationTracker.numCached} tags. {operationTracker.numProcessed} were new, {operationTracker.numSkipped} were skipped, {operationTracker.numFailed} failed to be interpreted, and {operationTracker.numCached} where previously processed.");
-
- WriteCachedTags(allTagData);
-
- Console.WriteLine();
- Console.WriteLine("Locating unique builds...");
-
- // Figure out all our builds that have been inserted, and which release tags if they happen to be release tags
- var uniqueInsertedBuilds = (from tag in allTagData.Values
- where tag.MaybeExists
- group tag by new { tag.InsertedBuildBranch, tag.InsertedBuildNumber } into g
- select new { g.Key.InsertedBuildBranch, g.Key.InsertedBuildNumber, ReleaseTags = g.Where(t => t.IsRelease()) })
- .Distinct().ToList();
-
- Console.WriteLine($" Found {uniqueInsertedBuilds.Count} unique builds.");
-
- Console.WriteLine();
- var currentBranch = string.Empty;
-
- foreach (var insertedBuildsByBranch in uniqueInsertedBuilds.GroupBy(b => b.InsertedBuildBranch))
- {
- Console.WriteLine(insertedBuildsByBranch.Key);
-
- foreach (var build in insertedBuildsByBranch.OrderBy(b => b.InsertedBuildNumber))
- {
- Console.Write($" {build.InsertedBuildNumber}");
-
- if (build.ReleaseTags.Any())
- {
- Console.Write($" (released to public as {string.Join(", ", build.ReleaseTags.Select(t => t.TagName).OrderBy(t => t))})");
- }
-
- Console.WriteLine();
- }
- }
-
- using (var buildClient = connection.GetClient())
- {
- Console.WriteLine("Finding build definition");
- var projectId = vsRepo.ProjectReference.Id;
- var definitions = buildClient.GetDefinitionsAsync(projectId).Result;
- var buildDefinitions = definitions.Where(d => d.Name == _options.BuildQueueName && d.DefinitionQuality != DefinitionQuality.Draft).ToList();
- if (buildDefinitions.Count != 1)
- {
- throw new Exception($"Expected one build definition named {_options.BuildQueueName} but found {buildDefinitions.Count}.");
- }
-
- var buildDefinitionIds = new int[]
- {
- buildDefinitions.Single().Id
- };
-
- var builds = buildClient.GetBuildsAsync(projectId, buildDefinitionIds, statusFilter: BuildStatus.Completed).Result;
- var modifiedBuilds = new HashSet();
-
- Console.WriteLine();
- Console.WriteLine("Determining which builds should be marked for retention...");
- foreach (var build in builds)
- {
- var insertedBuild = uniqueInsertedBuilds.FirstOrDefault(b => NormalizeBranchName(b.InsertedBuildBranch) == NormalizeBranchName(build.SourceBranch) &&
- b.InsertedBuildNumber == build.BuildNumber);
-
- if (insertedBuild != null && insertedBuild.ReleaseTags.Any() && !build.Tags.Contains(ReleasedToPublicTag))
- {
- buildClient.AddBuildTagAsync(projectId, build.Id, ReleasedToPublicTag).Wait();
- }
-
- if (insertedBuild != null || build.Tags.Contains(ReleasedToPublicTag))
- {
- if (!build.KeepForever.GetValueOrDefault())
- {
- Console.WriteLine($"Adding '{NormalizeBranchName(build.SourceBranch)} - {build.BuildNumber}' to the list of builds to keep forever.");
- build.KeepForever = true;
- modifiedBuilds.Add(build);
- }
- }
- else if (build.KeepForever.GetValueOrDefault())
- {
- // no longer needed
- Console.WriteLine($"Removing '{NormalizeBranchName(build.SourceBranch)} - {build.BuildNumber}' from the list of builds to keep forever.");
- build.KeepForever = false;
- modifiedBuilds.Add(build);
- }
- }
- Console.WriteLine($" Found {modifiedBuilds.Count} builds which need their retention setting modified.");
- Console.WriteLine();
-
- if (modifiedBuilds.Count > 0)
- {
- buildClient.UpdateBuildsAsync(modifiedBuilds, projectId).Wait();
- }
- }
-
- stopwatch.Stop();
-
- Console.WriteLine();
- Console.WriteLine($"Total Time: {stopwatch.Elapsed.TotalSeconds} seconds");
- }
- }
-
- private bool TryUpdateTag(GitHttpClient gitHttpClient, Guid vsRepoGuid, TagData tag, GitVersionDescriptor versionDescriptor, string componentsJsonFile)
- {
- Stream itemContentStream;
-
- try
- {
- itemContentStream = gitHttpClient.GetItemContentAsync(Settings.Default.TFSProjectName, vsRepoGuid, componentsJsonFile, versionDescriptor: versionDescriptor).Result;
- }
- catch (AggregateException e) when (e.InnerException.Message.Contains("TF401174")) // item could not be found
- {
- // That file doesn't exist in this drop;
- return false;
- }
-
- using (itemContentStream)
- using (var jsonReader = new JsonTextReader(new StreamReader(itemContentStream)))
- {
- var jsonDocument = (JObject)(JToken.ReadFrom(jsonReader));
-
- var components = jsonDocument["Components"];
- var component = components[_options.ComponentName];
-
- if (component == null)
- {
- return false;
- }
-
- var componentUrl = component["url"].Value();
- var componentParts = componentUrl.Split(';').First().Split('/');
-
- tag.InsertedBuildBranch = componentParts[componentParts.Length - 2];
- tag.InsertedBuildNumber = componentParts[componentParts.Length - 1];
-
- // Just to protect against us getting something bad, assert the build number is numeric
- if (!Regex.IsMatch(tag.InsertedBuildNumber, "^[0-9.]+$"))
- {
- throw new Exception($"{tag.InsertedBuildNumber} doesn't look numeric.");
- }
- }
-
- return true;
- }
-
- private static string NormalizeBranchName(string branchName)
- {
- return branchName.StartsWith(BranchNamePrefix)
- ? branchName.Substring(BranchNamePrefix.Length)
- : branchName;
- }
-
- ///
- /// Gets the specified secret from the key vault.
- ///
- private async Task GetSecret(string secretName, Options options)
- {
- var kv = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(GetAccessTokenFunction(options.ClientId, options.ClientSecret)));
- var secret = await kv.GetSecretAsync(Settings.Default.KeyVaultUrl, secretName);
- return secret.Value;
- }
-
- private static Func> GetAccessTokenFunction(string clientId, string clientSecret)
- {
- return async (authority, resource, scope) =>
- {
- var context = new AuthenticationContext(authority);
- AuthenticationResult authResult;
- if (string.IsNullOrEmpty(clientId) || string.IsNullOrEmpty(clientSecret))
- {
- // use default domain authentication
- authResult = await context.AcquireTokenAsync(resource, Settings.Default.ApplicationId, new UserCredential());
- }
- else
- {
- // use client authentication from command line arguments
- var credentials = new ClientCredential(clientId, clientSecret);
- authResult = await context.AcquireTokenAsync(resource, credentials);
- }
-
- return authResult.AccessToken;
- };
- }
-
- private ConcurrentDictionary ReadCachedTags()
- {
- var cachedTags = new ConcurrentDictionary();
- var cachedTagDataFileName = $@"ProcessedData.{_options.ComponentName}_v2.txt";
-
- using (var blobStream = GetReadableAzureStream(cachedTagDataFileName).Result)
- {
- using (var cachedTagDataFileStream = new StreamReader(blobStream))
- {
- while (!cachedTagDataFileStream.EndOfStream)
- {
- var currentLine = cachedTagDataFileStream.ReadLine();
- var tagData = JsonConvert.DeserializeObject(currentLine);
-
- cachedTags.TryAdd(tagData.TagName, tagData);
- }
- }
- }
-
- return cachedTags;
- }
-
- private void WriteCachedTags(ConcurrentDictionary cachedTags)
- {
- var cachedTagDataFileName = $@"ProcessedData.{_options.ComponentName}_v2.txt";
- using (var blobStream = GetWritableAzureStream(cachedTagDataFileName).Result)
- {
- using (var cachedTagDataFileStream = new StreamWriter(blobStream))
- {
- foreach (var tag in cachedTags.Values)
- {
- cachedTagDataFileStream.WriteLine(JsonConvert.SerializeObject(tag));
- }
- }
- }
- }
-
- ///
- /// Get a readable stream to an Azure storage blob.
- ///
- private async Task GetReadableAzureStream(string path)
- {
- var blob = await GetBlob(path);
-
- // the reader code is made much simpler if there's always a stream present, even if it's empty
- return blob.Exists() ? await blob.OpenReadAsync() : new MemoryStream();
- }
-
- ///
- /// Get a writable stream to an Azure storage blob.
- ///
- private async Task GetWritableAzureStream(string path)
- {
- var blob = await GetBlob(path);
- return await blob.OpenWriteAsync();
- }
-
- private async Task GetBlob(string path)
- {
- var blobToken = await GetSecret(Settings.Default.BlobStorageSecretName, _options);
- var credentials = new StorageCredentials(Settings.Default.BlobStorageAccountName, blobToken);
- var storageAccount = new CloudStorageAccount(credentials, useHttps: true);
- var container = storageAccount.CreateCloudBlobClient().GetContainerReference(Settings.Default.BlobContainerName);
- var blob = container.GetBlockBlobReference(path);
- return blob;
- }
- }
-}
diff --git a/src/BuildRetainer/BuildRetainer.csproj b/src/BuildRetainer/BuildRetainer.csproj
deleted file mode 100644
index dffb71d953..0000000000
--- a/src/BuildRetainer/BuildRetainer.csproj
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
-
- net472
- Exe
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- SettingsSingleFileGenerator
- Settings.Designer.cs
-
-
-
-
-
diff --git a/src/BuildRetainer/Mono.Options/Options.cs b/src/BuildRetainer/Mono.Options/Options.cs
deleted file mode 100644
index 7dd6255e16..0000000000
--- a/src/BuildRetainer/Mono.Options/Options.cs
+++ /dev/null
@@ -1,1435 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the License.txt file in the project root for more information.
-
-// Compile With:
-// gmcs -debug+ -r:System.Core Options.cs -o:NDesk.Options.dll
-// gmcs -debug+ -d:LINQ -r:System.Core Options.cs -o:NDesk.Options.dll
-//
-// The LINQ version just changes the implementation of
-// OptionSet.Parse(IEnumerable), and confers no semantic changes.
-
-//
-// A Getopt::Long-inspired option parsing library for C#.
-//
-// NDesk.Options.OptionSet is built upon a key/value table, where the
-// key is a option format string and the value is a delegate that is
-// invoked when the format string is matched.
-//
-// Option format strings:
-// Regex-like BNF Grammar:
-// name: .+
-// type: [=:]
-// sep: ( [^{}]+ | '{' .+ '}' )?
-// aliases: ( name type sep ) ( '|' name type sep )*
-//
-// Each '|'-delimited name is an alias for the associated action. If the
-// format string ends in a '=', it has a required value. If the format
-// string ends in a ':', it has an optional value. If neither '=' or ':'
-// is present, no value is supported. `=' or `:' need only be defined on one
-// alias, but if they are provided on more than one they must be consistent.
-//
-// Each alias portion may also end with a "key/value separator", which is used
-// to split option values if the option accepts > 1 value. If not specified,
-// it defaults to '=' and ':'. If specified, it can be any character except
-// '{' and '}' OR the *string* between '{' and '}'. If no separator should be
-// used (i.e. the separate values should be distinct arguments), then "{}"
-// should be used as the separator.
-//
-// Options are extracted either from the current option by looking for
-// the option name followed by an '=' or ':', or is taken from the
-// following option IFF:
-// - The current option does not contain a '=' or a ':'
-// - The current option requires a value (i.e. not a Option type of ':')
-//
-// The `name' used in the option format string does NOT include any leading
-// option indicator, such as '-', '--', or '/'. All three of these are
-// permitted/required on any named option.
-//
-// Option bundling is permitted so long as:
-// - '-' is used to start the option group
-// - all of the bundled options are a single character
-// - at most one of the bundled options accepts a value, and the value
-// provided starts from the next character to the end of the string.
-//
-// This allows specifying '-a -b -c' as '-abc', and specifying '-D name=value'
-// as '-Dname=value'.
-//
-// Option processing is disabled by specifying "--". All options after "--"
-// are returned by OptionSet.Parse() unchanged and unprocessed.
-//
-// Unprocessed options are returned from OptionSet.Parse().
-//
-// Examples:
-// int verbose = 0;
-// OptionSet p = new OptionSet ()
-// .Add ("v", v => ++verbose)
-// .Add ("name=|value=", v => Console.WriteLine (v));
-// p.Parse (new string[]{"-v", "--v", "/v", "-name=A", "/name", "B", "extra"});
-//
-// The above would parse the argument string array, and would invoke the
-// lambda expression three times, setting `verbose' to 3 when complete.
-// It would also print out "A" and "B" to standard output.
-// The returned array would contain the string "extra".
-//
-// C# 3.0 collection initializers are supported and encouraged:
-// var p = new OptionSet () {
-// { "h|?|help", v => ShowHelp () },
-// };
-//
-// System.ComponentModel.TypeConverter is also supported, allowing the use of
-// custom data types in the callback type; TypeConverter.ConvertFromString()
-// is used to convert the value option to an instance of the specified
-// type:
-//
-// var p = new OptionSet () {
-// { "foo=", (Foo f) => Console.WriteLine (f.ToString ()) },
-// };
-//
-// Random other tidbits:
-// - Boolean options (those w/o '=' or ':' in the option format string)
-// are explicitly enabled if they are followed with '+', and explicitly
-// disabled if they are followed with '-':
-// string a = null;
-// var p = new OptionSet () {
-// { "a", s => a = s },
-// };
-// p.Parse (new string[]{"-a"}); // sets v != null
-// p.Parse (new string[]{"-a+"}); // sets v != null
-// p.Parse (new string[]{"-a-"}); // sets v == null
-//
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.ComponentModel;
-using System.Globalization;
-using System.IO;
-using System.Runtime.Serialization;
-using System.Security.Permissions;
-using System.Text;
-using System.Text.RegularExpressions;
-
-#if LINQ
-using System.Linq;
-#endif
-
-#if TEST
-using NDesk.Options;
-#endif
-
-#if NDESK_OPTIONS
-namespace NDesk.Options
-#else
-namespace Mono.Options
-#endif
-{
- static class StringCoda
- {
-
- public static IEnumerable WrappedLines(string self, params int[] widths)
- {
- IEnumerable w = widths;
- return WrappedLines(self, w);
- }
-
- public static IEnumerable WrappedLines(string self, IEnumerable widths)
- {
- if (widths == null)
- throw new ArgumentNullException("widths");
- return CreateWrappedLinesIterator(self, widths);
- }
-
- private static IEnumerable CreateWrappedLinesIterator(string self, IEnumerable widths)
- {
- if (string.IsNullOrEmpty(self))
- {
- yield return string.Empty;
- yield break;
- }
- using (IEnumerator ewidths = widths.GetEnumerator())
- {
- bool? hw = null;
- int width = GetNextWidth(ewidths, int.MaxValue, ref hw);
- int start = 0, end;
- do
- {
- end = GetLineEnd(start, width, self);
- char c = self[end - 1];
- if (char.IsWhiteSpace(c))
- --end;
- bool needContinuation = end != self.Length && !IsEolChar(c);
- string continuation = "";
- if (needContinuation)
- {
- --end;
- continuation = "-";
- }
- string line = self.Substring(start, end - start) + continuation;
- yield return line;
- start = end;
- if (char.IsWhiteSpace(c))
- ++start;
- width = GetNextWidth(ewidths, width, ref hw);
- } while (start < self.Length);
- }
- }
-
- private static int GetNextWidth(IEnumerator ewidths, int curWidth, ref bool? eValid)
- {
- if (!eValid.HasValue || (eValid.HasValue && eValid.Value))
- {
- curWidth = (eValid = ewidths.MoveNext()).Value ? ewidths.Current : curWidth;
- // '.' is any character, - is for a continuation
- const string minWidth = ".-";
- if (curWidth < minWidth.Length)
- throw new ArgumentOutOfRangeException("widths",
- string.Format("Element must be >= {0}, was {1}.", minWidth.Length, curWidth));
- return curWidth;
- }
- // no more elements, use the last element.
- return curWidth;
- }
-
- private static bool IsEolChar(char c)
- {
- return !char.IsLetterOrDigit(c);
- }
-
- private static int GetLineEnd(int start, int length, string description)
- {
- int end = System.Math.Min(start + length, description.Length);
- int sep = -1;
- for (int i = start; i < end; ++i)
- {
- if (description[i] == '\n')
- return i + 1;
- if (IsEolChar(description[i]))
- sep = i + 1;
- }
- if (sep == -1 || end == description.Length)
- return end;
- return sep;
- }
- }
-
- public class OptionValueCollection : IList, IList
- {
-
- List values = new List();
- OptionContext c;
-
- internal OptionValueCollection(OptionContext c)
- {
- this.c = c;
- }
-
- #region ICollection
- void ICollection.CopyTo(Array array, int index) { (values as ICollection).CopyTo(array, index); }
- bool ICollection.IsSynchronized { get { return (values as ICollection).IsSynchronized; } }
- object ICollection.SyncRoot { get { return (values as ICollection).SyncRoot; } }
- #endregion
-
- #region ICollection
- public void Add(string item) { values.Add(item); }
- public void Clear() { values.Clear(); }
- public bool Contains(string item) { return values.Contains(item); }
- public void CopyTo(string[] array, int arrayIndex) { values.CopyTo(array, arrayIndex); }
- public bool Remove(string item) { return values.Remove(item); }
- public int Count { get { return values.Count; } }
- public bool IsReadOnly { get { return false; } }
- #endregion
-
- #region IEnumerable
- IEnumerator IEnumerable.GetEnumerator() { return values.GetEnumerator(); }
- #endregion
-
- #region IEnumerable
- public IEnumerator GetEnumerator() { return values.GetEnumerator(); }
- #endregion
-
- #region IList
- int IList.Add(object value) { return (values as IList).Add(value); }
- bool IList.Contains(object value) { return (values as IList).Contains(value); }
- int IList.IndexOf(object value) { return (values as IList).IndexOf(value); }
- void IList.Insert(int index, object value) { (values as IList).Insert(index, value); }
- void IList.Remove(object value) { (values as IList).Remove(value); }
- void IList.RemoveAt(int index) { (values as IList).RemoveAt(index); }
- bool IList.IsFixedSize { get { return false; } }
- object IList.this[int index] { get { return this[index]; } set { (values as IList)[index] = value; } }
- #endregion
-
- #region IList
- public int IndexOf(string item) { return values.IndexOf(item); }
- public void Insert(int index, string item) { values.Insert(index, item); }
- public void RemoveAt(int index) { values.RemoveAt(index); }
-
- private void AssertValid(int index)
- {
- if (c.Option == null)
- throw new InvalidOperationException("OptionContext.Option is null.");
- if (index >= c.Option.MaxValueCount)
- throw new ArgumentOutOfRangeException("index");
- if (c.Option.OptionValueType == OptionValueType.Required &&
- index >= values.Count)
- throw new OptionException(string.Format(
- c.OptionSet.MessageLocalizer("Missing required value for option '{0}'."), c.OptionName),
- c.OptionName);
- }
-
- public string this[int index]
- {
- get
- {
- AssertValid(index);
- return index >= values.Count ? null : values[index];
- }
- set
- {
- values[index] = value;
- }
- }
- #endregion
-
- public List ToList()
- {
- return new List(values);
- }
-
- public string[] ToArray()
- {
- return values.ToArray();
- }
-
- public override string ToString()
- {
- return string.Join(", ", values.ToArray());
- }
- }
-
- public class OptionContext
- {
- private Option option;
- private string name;
- private int index;
- private OptionSet set;
- private OptionValueCollection c;
-
- public OptionContext(OptionSet set)
- {
- this.set = set;
- this.c = new OptionValueCollection(this);
- }
-
- public Option Option
- {
- get { return option; }
- set { option = value; }
- }
-
- public string OptionName
- {
- get { return name; }
- set { name = value; }
- }
-
- public int OptionIndex
- {
- get { return index; }
- set { index = value; }
- }
-
- public OptionSet OptionSet
- {
- get { return set; }
- }
-
- public OptionValueCollection OptionValues
- {
- get { return c; }
- }
- }
-
- public enum OptionValueType
- {
- None,
- Optional,
- Required,
- }
-
- public abstract class Option
- {
- string prototype, description;
- string[] names;
- OptionValueType type;
- int count;
- string[] separators;
- bool hidden;
-
- protected Option(string prototype, string description)
- : this(prototype, description, 1, false)
- {
- }
-
- protected Option(string prototype, string description, int maxValueCount)
- : this(prototype, description, maxValueCount, false)
- {
- }
-
- protected Option(string prototype, string description, int maxValueCount, bool hidden)
- {
- if (prototype == null)
- throw new ArgumentNullException("prototype");
- if (prototype.Length == 0)
- throw new ArgumentException("Cannot be the empty string.", "prototype");
- if (maxValueCount < 0)
- throw new ArgumentOutOfRangeException("maxValueCount");
-
- this.prototype = prototype;
- this.description = description;
- this.count = maxValueCount;
- this.names = (this is OptionSet.Category)
- // append GetHashCode() so that "duplicate" categories have distinct
- // names, e.g. adding multiple "" categories should be valid.
- ? new[] { prototype + this.GetHashCode() }
- : prototype.Split('|');
-
- if (this is OptionSet.Category)
- return;
-
- this.type = ParsePrototype();
- this.hidden = hidden;
-
- if (this.count == 0 && type != OptionValueType.None)
- throw new ArgumentException(
- "Cannot provide maxValueCount of 0 for OptionValueType.Required or " +
- "OptionValueType.Optional.",
- "maxValueCount");
- if (this.type == OptionValueType.None && maxValueCount > 1)
- throw new ArgumentException(
- string.Format("Cannot provide maxValueCount of {0} for OptionValueType.None.", maxValueCount),
- "maxValueCount");
- if (Array.IndexOf(names, "<>") >= 0 &&
- ((names.Length == 1 && this.type != OptionValueType.None) ||
- (names.Length > 1 && this.MaxValueCount > 1)))
- throw new ArgumentException(
- "The default option handler '<>' cannot require values.",
- "prototype");
- }
-
- public string Prototype { get { return prototype; } }
- public string Description { get { return description; } }
- public OptionValueType OptionValueType { get { return type; } }
- public int MaxValueCount { get { return count; } }
- public bool Hidden { get { return hidden; } }
-
- public string[] GetNames()
- {
- return (string[])names.Clone();
- }
-
- public string[] GetValueSeparators()
- {
- if (separators == null)
- return new string[0];
- return (string[])separators.Clone();
- }
-
- protected static T Parse(string value, OptionContext c)
- {
- Type tt = typeof(T);
- bool nullable = tt.IsValueType && tt.IsGenericType &&
- !tt.IsGenericTypeDefinition &&
- tt.GetGenericTypeDefinition() == typeof(Nullable<>);
- Type targetType = nullable ? tt.GetGenericArguments()[0] : typeof(T);
- TypeConverter conv = TypeDescriptor.GetConverter(targetType);
- T t = default(T);
- try
- {
- if (value != null)
- t = (T)conv.ConvertFromString(value);
- }
- catch (Exception e)
- {
- throw new OptionException(
- string.Format(
- c.OptionSet.MessageLocalizer("Could not convert string `{0}' to type {1} for option `{2}'."),
- value, targetType.Name, c.OptionName),
- c.OptionName, e);
- }
- return t;
- }
-
- internal string[] Names { get { return names; } }
- internal string[] ValueSeparators { get { return separators; } }
-
- static readonly char[] NameTerminator = new char[] { '=', ':' };
-
- private OptionValueType ParsePrototype()
- {
- char type = '\0';
- List seps = new List();
- for (int i = 0; i < names.Length; ++i)
- {
- string name = names[i];
- if (name.Length == 0)
- throw new ArgumentException("Empty option names are not supported.", "prototype");
-
- int end = name.IndexOfAny(NameTerminator);
- if (end == -1)
- continue;
- names[i] = name.Substring(0, end);
- if (type == '\0' || type == name[end])
- type = name[end];
- else
- throw new ArgumentException(
- string.Format("Conflicting option types: '{0}' vs. '{1}'.", type, name[end]),
- "prototype");
- AddSeparators(name, end, seps);
- }
-
- if (type == '\0')
- return OptionValueType.None;
-
- if (count <= 1 && seps.Count != 0)
- throw new ArgumentException(
- string.Format("Cannot provide key/value separators for Options taking {0} value(s).", count),
- "prototype");
- if (count > 1)
- {
- if (seps.Count == 0)
- this.separators = new string[] { ":", "=" };
- else if (seps.Count == 1 && seps[0].Length == 0)
- this.separators = null;
- else
- this.separators = seps.ToArray();
- }
-
- return type == '=' ? OptionValueType.Required : OptionValueType.Optional;
- }
-
- private static void AddSeparators(string name, int end, ICollection seps)
- {
- int start = -1;
- for (int i = end + 1; i < name.Length; ++i)
- {
- switch (name[i])
- {
- case '{':
- if (start != -1)
- throw new ArgumentException(
- string.Format("Ill-formed name/value separator found in \"{0}\".", name),
- "prototype");
- start = i + 1;
- break;
- case '}':
- if (start == -1)
- throw new ArgumentException(
- string.Format("Ill-formed name/value separator found in \"{0}\".", name),
- "prototype");
- seps.Add(name.Substring(start, i - start));
- start = -1;
- break;
- default:
- if (start == -1)
- seps.Add(name[i].ToString());
- break;
- }
- }
- if (start != -1)
- throw new ArgumentException(
- string.Format("Ill-formed name/value separator found in \"{0}\".", name),
- "prototype");
- }
-
- public void Invoke(OptionContext c)
- {
- OnParseComplete(c);
- c.OptionName = null;
- c.Option = null;
- c.OptionValues.Clear();
- }
-
- protected abstract void OnParseComplete(OptionContext c);
-
- public override string ToString()
- {
- return Prototype;
- }
- }
-
- public abstract class ArgumentSource
- {
-
- protected ArgumentSource()
- {
- }
-
- public abstract string[] GetNames();
- public abstract string Description { get; }
- public abstract bool GetArguments(string value, out IEnumerable replacement);
-
- public static IEnumerable GetArgumentsFromFile(string file)
- {
- return GetArguments(File.OpenText(file), true);
- }
-
- public static IEnumerable GetArguments(TextReader reader)
- {
- return GetArguments(reader, false);
- }
-
- // Cribbed from mcs/driver.cs:LoadArgs(string)
- static IEnumerable GetArguments(TextReader reader, bool close)
- {
- try
- {
- StringBuilder arg = new StringBuilder();
-
- string line;
- while ((line = reader.ReadLine()) != null)
- {
- int t = line.Length;
-
- for (int i = 0; i < t; i++)
- {
- char c = line[i];
-
- if (c == '"' || c == '\'')
- {
- char end = c;
-
- for (i++; i < t; i++)
- {
- c = line[i];
-
- if (c == end)
- break;
- arg.Append(c);
- }
- }
- else if (c == ' ')
- {
- if (arg.Length > 0)
- {
- yield return arg.ToString();
- arg.Length = 0;
- }
- }
- else
- arg.Append(c);
- }
- if (arg.Length > 0)
- {
- yield return arg.ToString();
- arg.Length = 0;
- }
- }
- }
- finally
- {
- if (close)
- reader.Close();
- }
- }
- }
-
- public class ResponseFileSource : ArgumentSource
- {
-
- public override string[] GetNames()
- {
- return new string[] { "@file" };
- }
-
- public override string Description
- {
- get { return "Read response file for more options."; }
- }
-
- public override bool GetArguments(string value, out IEnumerable replacement)
- {
- if (string.IsNullOrEmpty(value) || !value.StartsWith("@"))
- {
- replacement = null;
- return false;
- }
- replacement = ArgumentSource.GetArgumentsFromFile(value.Substring(1));
- return true;
- }
- }
-
- [Serializable]
- public class OptionException : Exception
- {
- private string option;
-
- public OptionException()
- {
- }
-
- public OptionException(string message, string optionName)
- : base(message)
- {
- this.option = optionName;
- }
-
- public OptionException(string message, string optionName, Exception innerException)
- : base(message, innerException)
- {
- this.option = optionName;
- }
-
- protected OptionException(SerializationInfo info, StreamingContext context)
- : base(info, context)
- {
- this.option = info.GetString("OptionName");
- }
-
- public string OptionName
- {
- get { return this.option; }
- }
-
- [SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)]
- public override void GetObjectData(SerializationInfo info, StreamingContext context)
- {
- base.GetObjectData(info, context);
- info.AddValue("OptionName", option);
- }
- }
-
- public delegate void OptionAction(TKey key, TValue value);
-
- public class OptionSet : KeyedCollection
- {
- public OptionSet()
- : this(delegate (string f) { return f; })
- {
- }
-
- public OptionSet(Converter localizer)
- {
- this.localizer = localizer;
- this.roSources = new ReadOnlyCollection(sources);
- }
-
- Converter localizer;
-
- public Converter MessageLocalizer
- {
- get { return localizer; }
- }
-
- List sources = new List();
- ReadOnlyCollection roSources;
-
- public ReadOnlyCollection ArgumentSources
- {
- get { return roSources; }
- }
-
-
- protected override string GetKeyForItem(Option item)
- {
- if (item == null)
- throw new ArgumentNullException("option");
- if (item.Names != null && item.Names.Length > 0)
- return item.Names[0];
- // This should never happen, as it's invalid for Option to be
- // constructed w/o any names.
- throw new InvalidOperationException("Option has no names!");
- }
-
- [Obsolete("Use KeyedCollection.this[string]")]
- protected Option GetOptionForName(string option)
- {
- if (option == null)
- throw new ArgumentNullException("option");
- try
- {
- return base[option];
- }
- catch (KeyNotFoundException)
- {
- return null;
- }
- }
-
- protected override void InsertItem(int index, Option item)
- {
- base.InsertItem(index, item);
- AddImpl(item);
- }
-
- protected override void RemoveItem(int index)
- {
- Option p = Items[index];
- base.RemoveItem(index);
- // KeyedCollection.RemoveItem() handles the 0th item
- for (int i = 1; i < p.Names.Length; ++i)
- {
- Dictionary.Remove(p.Names[i]);
- }
- }
-
- protected override void SetItem(int index, Option item)
- {
- base.SetItem(index, item);
- AddImpl(item);
- }
-
- private void AddImpl(Option option)
- {
- if (option == null)
- throw new ArgumentNullException("option");
- List added = new List(option.Names.Length);
- try
- {
- // KeyedCollection.InsertItem/SetItem handle the 0th name.
- for (int i = 1; i < option.Names.Length; ++i)
- {
- Dictionary.Add(option.Names[i], option);
- added.Add(option.Names[i]);
- }
- }
- catch (Exception)
- {
- foreach (string name in added)
- Dictionary.Remove(name);
- throw;
- }
- }
-
- public OptionSet Add(string header)
- {
- if (header == null)
- throw new ArgumentNullException("header");
- Add(new Category(header));
- return this;
- }
-
- internal sealed class Category : Option
- {
-
- // Prototype starts with '=' because this is an invalid prototype
- // (see Option.ParsePrototype(), and thus it'll prevent Category
- // instances from being accidentally used as normal options.
- public Category(string description)
- : base("=:Category:= " + description, description)
- {
- }
-
- protected override void OnParseComplete(OptionContext c)
- {
- throw new NotSupportedException("Category.OnParseComplete should not be invoked.");
- }
- }
-
-
- public new OptionSet Add(Option option)
- {
- base.Add(option);
- return this;
- }
-
- sealed class ActionOption : Option
- {
- Action action;
-
- public ActionOption(string prototype, string description, int count, Action action)
- : this(prototype, description, count, action, false)
- {
- }
-
- public ActionOption(string prototype, string description, int count, Action action, bool hidden)
- : base(prototype, description, count, hidden)
- {
- if (action == null)
- throw new ArgumentNullException("action");
- this.action = action;
- }
-
- protected override void OnParseComplete(OptionContext c)
- {
- action(c.OptionValues);
- }
- }
-
- public OptionSet Add(string prototype, Action action)
- {
- return Add(prototype, null, action);
- }
-
- public OptionSet Add(string prototype, string description, Action action)
- {
- return Add(prototype, description, action, false);
- }
-
- public OptionSet Add(string prototype, string description, Action action, bool hidden)
- {
- if (action == null)
- throw new ArgumentNullException("action");
- Option p = new ActionOption(prototype, description, 1,
- delegate (OptionValueCollection v) { action(v[0]); }, hidden);
- base.Add(p);
- return this;
- }
-
- public OptionSet Add(string prototype, OptionAction action)
- {
- return Add(prototype, null, action);
- }
-
- public OptionSet Add(string prototype, string description, OptionAction action)
- {
- return Add(prototype, description, action, false);
- }
-
- public OptionSet Add(string prototype, string description, OptionAction action, bool hidden)
- {
- if (action == null)
- throw new ArgumentNullException("action");
- Option p = new ActionOption(prototype, description, 2,
- delegate (OptionValueCollection v) { action(v[0], v[1]); }, hidden);
- base.Add(p);
- return this;
- }
-
- sealed class ActionOption : Option
- {
- Action action;
-
- public ActionOption(string prototype, string description, Action action)
- : base(prototype, description, 1)
- {
- if (action == null)
- throw new ArgumentNullException("action");
- this.action = action;
- }
-
- protected override void OnParseComplete(OptionContext c)
- {
- action(Parse(c.OptionValues[0], c));
- }
- }
-
- sealed class ActionOption : Option
- {
- OptionAction action;
-
- public ActionOption(string prototype, string description, OptionAction action)
- : base(prototype, description, 2)
- {
- if (action == null)
- throw new ArgumentNullException("action");
- this.action = action;
- }
-
- protected override void OnParseComplete(OptionContext c)
- {
- action(
- Parse(c.OptionValues[0], c),
- Parse(c.OptionValues[1], c));
- }
- }
-
- public OptionSet Add(string prototype, Action action)
- {
- return Add(prototype, null, action);
- }
-
- public OptionSet Add(string prototype, string description, Action action)
- {
- return Add(new ActionOption(prototype, description, action));
- }
-
- public OptionSet Add(string prototype, OptionAction action)
- {
- return Add(prototype, null, action);
- }
-
- public OptionSet Add(string prototype, string description, OptionAction action)
- {
- return Add(new ActionOption(prototype, description, action));
- }
-
- public OptionSet Add(ArgumentSource source)
- {
- if (source == null)
- throw new ArgumentNullException("source");
- sources.Add(source);
- return this;
- }
-
- protected virtual OptionContext CreateOptionContext()
- {
- return new OptionContext(this);
- }
-
- public List Parse(IEnumerable arguments)
- {
- if (arguments == null)
- throw new ArgumentNullException("arguments");
- OptionContext c = CreateOptionContext();
- c.OptionIndex = -1;
- bool process = true;
- List unprocessed = new List();
- Option def = Contains("<>") ? this["<>"] : null;
- ArgumentEnumerator ae = new ArgumentEnumerator(arguments);
- foreach (string argument in ae)
- {
- ++c.OptionIndex;
- if (argument == "--")
- {
- process = false;
- continue;
- }
- if (!process)
- {
- Unprocessed(unprocessed, def, c, argument);
- continue;
- }
- if (AddSource(ae, argument))
- continue;
- if (!Parse(argument, c))
- Unprocessed(unprocessed, def, c, argument);
- }
- if (c.Option != null)
- c.Option.Invoke(c);
- return unprocessed;
- }
-
- class ArgumentEnumerator : IEnumerable
- {
- List> sources = new List>();
-
- public ArgumentEnumerator(IEnumerable arguments)
- {
- sources.Add(arguments.GetEnumerator());
- }
-
- public void Add(IEnumerable arguments)
- {
- sources.Add(arguments.GetEnumerator());
- }
-
- public IEnumerator GetEnumerator()
- {
- do
- {
- IEnumerator c = sources[sources.Count - 1];
- if (c.MoveNext())
- yield return c.Current;
- else
- {
- c.Dispose();
- sources.RemoveAt(sources.Count - 1);
- }
- } while (sources.Count > 0);
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
- }
-
- bool AddSource(ArgumentEnumerator ae, string argument)
- {
- foreach (ArgumentSource source in sources)
- {
- IEnumerable replacement;
- if (!source.GetArguments(argument, out replacement))
- continue;
- ae.Add(replacement);
- return true;
- }
- return false;
- }
-
- private static bool Unprocessed(ICollection extra, Option def, OptionContext c, string argument)
- {
- if (def == null)
- {
- extra.Add(argument);
- return false;
- }
- c.OptionValues.Add(argument);
- c.Option = def;
- c.Option.Invoke(c);
- return false;
- }
-
- private readonly Regex ValueOption = new Regex(
- @"^(?--|-|/)(?[^:=]+)((?[:=])(?.*))?$");
-
- protected bool GetOptionParts(string argument, out string flag, out string name, out string sep, out string value)
- {
- if (argument == null)
- throw new ArgumentNullException("argument");
-
- flag = name = sep = value = null;
- Match m = ValueOption.Match(argument);
- if (!m.Success)
- {
- return false;
- }
- flag = m.Groups["flag"].Value;
- name = m.Groups["name"].Value;
- if (m.Groups["sep"].Success && m.Groups["value"].Success)
- {
- sep = m.Groups["sep"].Value;
- value = m.Groups["value"].Value;
- }
- return true;
- }
-
- protected virtual bool Parse(string argument, OptionContext c)
- {
- if (c.Option != null)
- {
- ParseValue(argument, c);
- return true;
- }
-
- string f, n, s, v;
- if (!GetOptionParts(argument, out f, out n, out s, out v))
- return false;
-
- Option p;
- if (Contains(n))
- {
- p = this[n];
- c.OptionName = f + n;
- c.Option = p;
- switch (p.OptionValueType)
- {
- case OptionValueType.None:
- c.OptionValues.Add(n);
- c.Option.Invoke(c);
- break;
- case OptionValueType.Optional:
- case OptionValueType.Required:
- ParseValue(v, c);
- break;
- }
- return true;
- }
- // no match; is it a bool option?
- if (ParseBool(argument, n, c))
- return true;
- // is it a bundled option?
- if (ParseBundledValue(f, string.Concat(n + s + v), c))
- return true;
-
- return false;
- }
-
- private void ParseValue(string option, OptionContext c)
- {
- if (option != null)
- foreach (string o in c.Option.ValueSeparators != null
- ? option.Split(c.Option.ValueSeparators, c.Option.MaxValueCount - c.OptionValues.Count, StringSplitOptions.None)
- : new string[] { option })
- {
- c.OptionValues.Add(o);
- }
- if (c.OptionValues.Count == c.Option.MaxValueCount ||
- c.Option.OptionValueType == OptionValueType.Optional)
- c.Option.Invoke(c);
- else if (c.OptionValues.Count > c.Option.MaxValueCount)
- {
- throw new OptionException(localizer(string.Format(
- "Error: Found {0} option values when expecting {1}.",
- c.OptionValues.Count, c.Option.MaxValueCount)),
- c.OptionName);
- }
- }
-
- private bool ParseBool(string option, string n, OptionContext c)
- {
- Option p;
- string rn;
- if (n.Length >= 1 && (n[n.Length - 1] == '+' || n[n.Length - 1] == '-') &&
- Contains((rn = n.Substring(0, n.Length - 1))))
- {
- p = this[rn];
- string v = n[n.Length - 1] == '+' ? option : null;
- c.OptionName = option;
- c.Option = p;
- c.OptionValues.Add(v);
- p.Invoke(c);
- return true;
- }
- return false;
- }
-
- private bool ParseBundledValue(string f, string n, OptionContext c)
- {
- if (f != "-")
- return false;
- for (int i = 0; i < n.Length; ++i)
- {
- Option p;
- string opt = f + n[i].ToString();
- string rn = n[i].ToString();
- if (!Contains(rn))
- {
- if (i == 0)
- return false;
- throw new OptionException(string.Format(localizer(
- "Cannot bundle unregistered option '{0}'."), opt), opt);
- }
- p = this[rn];
- switch (p.OptionValueType)
- {
- case OptionValueType.None:
- Invoke(c, opt, n, p);
- break;
- case OptionValueType.Optional:
- case OptionValueType.Required:
- {
- string v = n.Substring(i + 1);
- c.Option = p;
- c.OptionName = opt;
- ParseValue(v.Length != 0 ? v : null, c);
- return true;
- }
- default:
- throw new InvalidOperationException("Unknown OptionValueType: " + p.OptionValueType);
- }
- }
- return true;
- }
-
- private static void Invoke(OptionContext c, string name, string value, Option option)
- {
- c.OptionName = name;
- c.Option = option;
- c.OptionValues.Add(value);
- option.Invoke(c);
- }
-
- private const int OptionWidth = 29;
- private const int Description_FirstWidth = 80 - OptionWidth;
- private const int Description_RemWidth = 80 - OptionWidth - 2;
-
- public void WriteOptionDescriptions(TextWriter o)
- {
- foreach (Option p in this)
- {
- int written = 0;
-
- if (p.Hidden)
- continue;
-
- Category c = p as Category;
- if (c != null)
- {
- WriteDescription(o, p.Description, "", 80, 80);
- continue;
- }
-
- if (!WriteOptionPrototype(o, p, ref written))
- continue;
-
- if (written < OptionWidth)
- o.Write(new string(' ', OptionWidth - written));
- else
- {
- o.WriteLine();
- o.Write(new string(' ', OptionWidth));
- }
-
- WriteDescription(o, p.Description, new string(' ', OptionWidth + 2),
- Description_FirstWidth, Description_RemWidth);
- }
-
- foreach (ArgumentSource s in sources)
- {
- string[] names = s.GetNames();
- if (names == null || names.Length == 0)
- continue;
-
- int written = 0;
-
- Write(o, ref written, " ");
- Write(o, ref written, names[0]);
- for (int i = 1; i < names.Length; ++i)
- {
- Write(o, ref written, ", ");
- Write(o, ref written, names[i]);
- }
-
- if (written < OptionWidth)
- o.Write(new string(' ', OptionWidth - written));
- else
- {
- o.WriteLine();
- o.Write(new string(' ', OptionWidth));
- }
-
- WriteDescription(o, s.Description, new string(' ', OptionWidth + 2),
- Description_FirstWidth, Description_RemWidth);
- }
- }
-
- void WriteDescription(TextWriter o, string value, string prefix, int firstWidth, int remWidth)
- {
- bool indent = false;
- foreach (string line in GetLines(localizer(GetDescription(value)), firstWidth, remWidth))
- {
- if (indent)
- o.Write(prefix);
- o.WriteLine(line);
- indent = true;
- }
- }
-
- bool WriteOptionPrototype(TextWriter o, Option p, ref int written)
- {
- string[] names = p.Names;
-
- int i = GetNextOptionIndex(names, 0);
- if (i == names.Length)
- return false;
-
- if (names[i].Length == 1)
- {
- Write(o, ref written, " -");
- Write(o, ref written, names[0]);
- }
- else
- {
- Write(o, ref written, " --");
- Write(o, ref written, names[0]);
- }
-
- for (i = GetNextOptionIndex(names, i + 1);
- i < names.Length; i = GetNextOptionIndex(names, i + 1))
- {
- Write(o, ref written, ", ");
- Write(o, ref written, names[i].Length == 1 ? "-" : "--");
- Write(o, ref written, names[i]);
- }
-
- if (p.OptionValueType == OptionValueType.Optional ||
- p.OptionValueType == OptionValueType.Required)
- {
- if (p.OptionValueType == OptionValueType.Optional)
- {
- Write(o, ref written, localizer("["));
- }
- Write(o, ref written, localizer("=" + GetArgumentName(0, p.MaxValueCount, p.Description)));
- string sep = p.ValueSeparators != null && p.ValueSeparators.Length > 0
- ? p.ValueSeparators[0]
- : " ";
- for (int c = 1; c < p.MaxValueCount; ++c)
- {
- Write(o, ref written, localizer(sep + GetArgumentName(c, p.MaxValueCount, p.Description)));
- }
- if (p.OptionValueType == OptionValueType.Optional)
- {
- Write(o, ref written, localizer("]"));
- }
- }
- return true;
- }
-
- static int GetNextOptionIndex(string[] names, int i)
- {
- while (i < names.Length && names[i] == "<>")
- {
- ++i;
- }
- return i;
- }
-
- static void Write(TextWriter o, ref int n, string s)
- {
- n += s.Length;
- o.Write(s);
- }
-
- private static string GetArgumentName(int index, int maxIndex, string description)
- {
- if (description == null)
- return maxIndex == 1 ? "VALUE" : "VALUE" + (index + 1);
- string[] nameStart;
- if (maxIndex == 1)
- nameStart = new string[] { "{0:", "{" };
- else
- nameStart = new string[] { "{" + index + ":" };
- for (int i = 0; i < nameStart.Length; ++i)
- {
- int start, j = 0;
- do
- {
- start = description.IndexOf(nameStart[i], j);
- } while (start >= 0 && j != 0 ? description[j++ - 1] == '{' : false);
- if (start == -1)
- continue;
- int end = description.IndexOf("}", start);
- if (end == -1)
- continue;
- return description.Substring(start + nameStart[i].Length, end - start - nameStart[i].Length);
- }
- return maxIndex == 1 ? "VALUE" : "VALUE" + (index + 1);
- }
-
- private static string GetDescription(string description)
- {
- if (description == null)
- return string.Empty;
- StringBuilder sb = new StringBuilder(description.Length);
- int start = -1;
- for (int i = 0; i < description.Length; ++i)
- {
- switch (description[i])
- {
- case '{':
- if (i == start)
- {
- sb.Append('{');
- start = -1;
- }
- else if (start < 0)
- start = i + 1;
- break;
- case '}':
- if (start < 0)
- {
- if ((i + 1) == description.Length || description[i + 1] != '}')
- throw new InvalidOperationException("Invalid option description: " + description);
- ++i;
- sb.Append("}");
- }
- else
- {
- sb.Append(description.Substring(start, i - start));
- start = -1;
- }
- break;
- case ':':
- if (start < 0)
- goto default;
- start = i + 1;
- break;
- default:
- if (start < 0)
- sb.Append(description[i]);
- break;
- }
- }
- return sb.ToString();
- }
-
- private static IEnumerable GetLines(string description, int firstWidth, int remWidth)
- {
- return StringCoda.WrappedLines(description, firstWidth, remWidth);
- }
- }
-}
-
diff --git a/src/BuildRetainer/Options.cs b/src/BuildRetainer/Options.cs
deleted file mode 100644
index ba3798ee64..0000000000
--- a/src/BuildRetainer/Options.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the License.txt file in the project root for more information.
-
-using System.Linq;
-
-namespace BuildRetainer
-{
- internal class Options
- {
- public string BuildQueueName { get; set; }
- public string ComponentName { get; set; }
- public string ClientId { get; set; }
- public string ClientSecret { get; set; }
- public bool IsValid => new[] { BuildQueueName, ComponentName }.All(s => !string.IsNullOrEmpty(s));
- }
-}
diff --git a/src/BuildRetainer/Program.cs b/src/BuildRetainer/Program.cs
deleted file mode 100644
index 22af130838..0000000000
--- a/src/BuildRetainer/Program.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the License.txt file in the project root for more information.
-
-using System;
-using System.Reflection;
-using Mono.Options;
-
-namespace BuildRetainer
-{
- class Program
- {
- static int Main(string[] args)
- {
- var exeName = Assembly.GetExecutingAssembly().GetName().Name;
- var options = new Options();
- var showHelp = false;
- var parameters = new OptionSet()
- {
- $"Usage: {exeName} [options]",
- "Ensure shipped builds are retained and un-shipped builds are marked to be cleaned up.",
- "",
- "Options:",
- { "BuildQueueName=", "The name of the build queue.", value => options.BuildQueueName = value },
- { "ComponentName=", "The name of the inserted component.", value => options.ComponentName = value },
- { "ClientId=", "The ID used to get Azure auth tokens.", value => options.ClientId = value },
- { "ClientSecret=", "The secret used to get Azure auth tokens.", value => options.ClientSecret = value },
- { "h|?|help", "Show this message and exit.", value => showHelp = value != null }
- };
-
- try
- {
- parameters.Parse(args);
- if (showHelp || !options.IsValid)
- {
- parameters.WriteOptionDescriptions(Console.Out);
- return options.IsValid ? 0 : 1;
- }
-
- var br = new BuildRetainer(options);
- br.Run();
- return 0;
- }
- catch (Exception e)
- {
- Console.WriteLine($"{exeName}: {e}");
- Console.WriteLine($"Try `{exeName} --help` for more information.");
- return 1;
- }
- }
- }
-}
diff --git a/src/BuildRetainer/RetainBuilds.ps1 b/src/BuildRetainer/RetainBuilds.ps1
deleted file mode 100644
index b1d308fee6..0000000000
--- a/src/BuildRetainer/RetainBuilds.ps1
+++ /dev/null
@@ -1,28 +0,0 @@
-param([string] $clientId,
- [string] $clientSecret)
-
-$Passed = $true
-function Run-BuildRetainer([string] $BuildQueueName, [string] $ComponentName) {
- & ".\BuildRetainer.exe" --BuildQueueName=$BuildQueueName --ComponentName=$ComponentName --ClientId=$clientId --ClientSecret=$clientSecret
- if ($LastExitCode -ne 0) {
- $Script:Passed = $false
- }
-}
-
-try {
- Run-BuildRetainer -BuildQueueName Roslyn-Signed -ComponentName Microsoft.CodeAnalysis.Compilers
- Run-BuildRetainer -BuildQueueName FSharp-Signed -ComponentName Microsoft.FSharp
- Run-BuildRetainer -BuildQueueName FSharp-Microbuild -ComponentName Microsoft.FSharp
- Run-BuildRetainer -BuildQueueName FSharp-Microbuild-Dev15-RC -ComponentName Microsoft.FSharp
- Run-BuildRetainer -BuildQueueName FSharp-Microbuild-Dev15-RTM -ComponentName Microsoft.FSharp
- Run-BuildRetainer -BuildQueueName TestImpact-Signed -ComponentName Microsoft.CodeAnalysis.LiveUnitTesting
- Run-BuildRetainer -BuildQueueName DotNet-Project-System -ComponentName Microsoft.VisualStudio.ProjectSystem.Managed
-
- if (-Not $Passed) {
- Write-Host "Build retainer has failed."
- Exit 1
- }
-} catch [Exception] {
- Write-Output $_.Exception|Format-List -Force
- Exit -1
-}
diff --git a/src/BuildRetainer/Settings.Designer.cs b/src/BuildRetainer/Settings.Designer.cs
deleted file mode 100644
index eed4c23c4b..0000000000
--- a/src/BuildRetainer/Settings.Designer.cs
+++ /dev/null
@@ -1,110 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the License.txt file in the project root for more information.
-
-namespace BuildRetainer {
-
-
- [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.0.1.0")]
- internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
-
- private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
-
- public static Settings Default {
- get {
- return defaultInstance;
- }
- }
-
- [global::System.Configuration.ApplicationScopedSettingAttribute()]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("vslsnap@microsoft.com")]
- public string UserName {
- get {
- return ((string)(this["UserName"]));
- }
- }
-
- [global::System.Configuration.ApplicationScopedSettingAttribute()]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("https://devdiv.visualstudio.com/DefaultCollection")]
- public string VSTSUrl {
- get {
- return ((string)(this["VSTSUrl"]));
- }
- }
-
- [global::System.Configuration.ApplicationScopedSettingAttribute()]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("DevDiv")]
- public string TFSProjectName {
- get {
- return ((string)(this["TFSProjectName"]));
- }
- }
-
- [global::System.Configuration.ApplicationScopedSettingAttribute()]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("VS")]
- public string RepositoryName {
- get {
- return ((string)(this["RepositoryName"]));
- }
- }
-
- [global::System.Configuration.ApplicationScopedSettingAttribute()]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("vslsnap-vso-auth-token")]
- public string VsoSecretName {
- get {
- return ((string)(this["VsoSecretName"]));
- }
- }
-
- [global::System.Configuration.ApplicationScopedSettingAttribute()]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("https://roslyninfra.vault.azure.net:443")]
- public string KeyVaultUrl {
- get {
- return ((string)(this["KeyVaultUrl"]));
- }
- }
-
- [global::System.Configuration.ApplicationScopedSettingAttribute()]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("1950a258-227b-4e31-a9cf-717495945fc2")]
- public string ApplicationId {
- get {
- return ((string)(this["ApplicationId"]));
- }
- }
-
- [global::System.Configuration.ApplicationScopedSettingAttribute()]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("build-retainer-cache")]
- public string BlobContainerName {
- get {
- return ((string)(this["BlobContainerName"]));
- }
- }
-
- [global::System.Configuration.ApplicationScopedSettingAttribute()]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("roslyninfra-blob-storage")]
- public string BlobStorageSecretName {
- get {
- return ((string)(this["BlobStorageSecretName"]));
- }
- }
-
- [global::System.Configuration.ApplicationScopedSettingAttribute()]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("roslyninfra")]
- public string BlobStorageAccountName {
- get {
- return ((string)(this["BlobStorageAccountName"]));
- }
- }
- }
-}
diff --git a/src/BuildRetainer/Settings.settings b/src/BuildRetainer/Settings.settings
deleted file mode 100644
index ce1cd62125..0000000000
--- a/src/BuildRetainer/Settings.settings
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
- vslsnap@microsoft.com
-
-
- https://devdiv.visualstudio.com/DefaultCollection
-
-
- DevDiv
-
-
- VS
-
-
- vslsnap-vso-auth-token
-
-
- https://roslyninfra.vault.azure.net:443
-
-
- 1950a258-227b-4e31-a9cf-717495945fc2
-
-
- build-retainer-cache
-
-
- roslyninfra-blob-storage
-
-
- roslyninfra
-
-
-
\ No newline at end of file
diff --git a/src/BuildRetainer/app.config b/src/BuildRetainer/app.config
deleted file mode 100644
index aa22d63d10..0000000000
--- a/src/BuildRetainer/app.config
+++ /dev/null
@@ -1,42 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- vslsnap@microsoft.com
-
-
- https://devdiv.visualstudio.com/DefaultCollection
-
-
- DevDiv
-
-
- VS
-
-
- vslsnap-vso-auth-token
-
-
- https://roslyninfra.vault.azure.net:443
-
-
- 1950a258-227b-4e31-a9cf-717495945fc2
-
-
- build-retainer-cache
-
-
- roslyninfra-blob-storage
-
-
- roslyninfra
-
-
-
-
\ No newline at end of file
diff --git a/src/VstsMergeTool/Initializer.cs b/src/VstsMergeTool/Initializer.cs
deleted file mode 100644
index 58f4e00fd9..0000000000
--- a/src/VstsMergeTool/Initializer.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the License.txt file in the project root for more information.
-using System;
-using Microsoft.VisualStudio.Services.Common;
-using Microsoft.TeamFoundation.SourceControl.WebApi;
-using Microsoft.TeamFoundation.Client;
-using System.Threading.Tasks;
-using System.Web.Configuration;
-using Microsoft.IdentityModel.Clients.ActiveDirectory;
-using Microsoft.Azure.KeyVault;
-
-namespace VstsMergeTool
-{
- public class Initializer
- {
- public VstsMergeTool MergeTool { get; }
-
- private TfsTeamProjectCollection ProjectCollection;
-
- private Settings settings = Settings.Default;
-
- public Initializer(string sourceBranch, string destBranch)
- {
- Console.WriteLine($"Auto Merging tool start on {DateTime.Now:MM-dd-yyyy-HH-mm-ss}");
- Console.WriteLine($"Source branch: {sourceBranch}, Target Branch: {destBranch}");
-
- string password = GetPassword(settings.VsoSecretName).Result;
- ProjectCollection = new TfsTeamProjectCollection(
- new Uri(settings.VSTSUrl),
- new VssBasicCredential(settings.UserName, password));
-
- try
- {
- ProjectCollection.Authenticate();
- }
- catch (Exception ex)
- {
- Console.WriteLine($"Could not authenticate with {settings.VSTSUrl}");
- Console.WriteLine(ex);
- }
-
- var gitClient = ProjectCollection.GetClient();
- MergeTool = new VstsMergeTool(gitClient, sourceBranch, destBranch);
- }
-
- private static async Task GetPassword(string secretName)
- {
- var kv = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(GetAccessToken));
- var secret = await kv.GetSecretAsync(Settings.Default.KeyVaultUrl, secretName);
- return secret.Value;
- }
-
- private static async Task GetAccessToken(string authority, string resource, string scope)
- {
- var context = new AuthenticationContext(authority);
- AuthenticationResult authResult;
- if (string.IsNullOrEmpty(WebConfigurationManager.AppSettings["ClientId"]))
- {
- // use default domain authentication
- authResult = await context.AcquireTokenAsync(resource, Settings.Default.ApplicationId, new UserCredential());
- }
- else
- {
- // use client authentication; "ClientId" and "ClientSecret" are only available when run as a web job
- var credentials = new ClientCredential(WebConfigurationManager.AppSettings["ClientId"], WebConfigurationManager.AppSettings["ClientSecret"]);
- authResult = await context.AcquireTokenAsync(resource, credentials);
- }
-
- return authResult.AccessToken;
- }
- }
-}
diff --git a/src/VstsMergeTool/Properties/AssemblyInfo.cs b/src/VstsMergeTool/Properties/AssemblyInfo.cs
deleted file mode 100644
index 8b0ca09673..0000000000
--- a/src/VstsMergeTool/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the License.txt file in the project root for more information.
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("VstsMergeTool")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyProduct("VstsMergeTool")]
-[assembly: AssemblyCopyright("Copyright ©Microsoft 2018")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("364b5651-6e52-4b05-af00-70c8bde5a341")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/src/VstsMergeTool/Settings.Designer.cs b/src/VstsMergeTool/Settings.Designer.cs
deleted file mode 100644
index 79822d7805..0000000000
--- a/src/VstsMergeTool/Settings.Designer.cs
+++ /dev/null
@@ -1,92 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the License.txt file in the project root for more information.
-
-namespace VstsMergeTool {
-
-
- [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.0.0.0")]
- internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
-
- private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
-
- public static Settings Default {
- get {
- return defaultInstance;
- }
- }
-
- [global::System.Configuration.ApplicationScopedSettingAttribute()]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("Devdiv")]
- public string AccountName {
- get {
- return ((string)(this["AccountName"]));
- }
- }
-
- [global::System.Configuration.ApplicationScopedSettingAttribute()]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("vslsnap@microsoft.com")]
- public string UserName {
- get {
- return ((string)(this["UserName"]));
- }
- }
-
- [global::System.Configuration.ApplicationScopedSettingAttribute()]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("VSUnitTesting")]
- public string RepositoryName {
- get {
- return ((string)(this["RepositoryName"]));
- }
- }
-
- [global::System.Configuration.ApplicationScopedSettingAttribute()]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("DevDiv")]
- public string TFSProjectName {
- get {
- return ((string)(this["TFSProjectName"]));
- }
- }
-
- [global::System.Configuration.ApplicationScopedSettingAttribute()]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("https://roslyninfra.vault.azure.net:443")]
- public string KeyVaultUrl {
- get {
- return ((string)(this["KeyVaultUrl"]));
- }
- }
-
- [global::System.Configuration.ApplicationScopedSettingAttribute()]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("vslsnap-vso-auth-token")]
- public string VsoSecretName {
- get {
- return ((string)(this["VsoSecretName"]));
- }
- }
-
- [global::System.Configuration.ApplicationScopedSettingAttribute()]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("1950a258-227b-4e31-a9cf-717495945fc2")]
- public string ApplicationId {
- get {
- return ((string)(this["ApplicationId"]));
- }
- }
-
- [global::System.Configuration.ApplicationScopedSettingAttribute()]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("https://devdiv.visualstudio.com/DefaultCollection")]
- public string VSTSUrl {
- get {
- return ((string)(this["VSTSUrl"]));
- }
- }
- }
-}
diff --git a/src/VstsMergeTool/Settings.settings b/src/VstsMergeTool/Settings.settings
deleted file mode 100644
index 4894454042..0000000000
--- a/src/VstsMergeTool/Settings.settings
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
- Devdiv
-
-
- vslsnap@microsoft.com
-
-
- VSUnitTesting
-
-
- DevDiv
-
-
- https://roslyninfra.vault.azure.net:443
-
-
- vslsnap-vso-auth-token
-
-
- 1950a258-227b-4e31-a9cf-717495945fc2
-
-
- https://devdiv.visualstudio.com/DefaultCollection
-
-
-
\ No newline at end of file
diff --git a/src/VstsMergeTool/VstsMergeTool.cs b/src/VstsMergeTool/VstsMergeTool.cs
deleted file mode 100644
index f39f7adce1..0000000000
--- a/src/VstsMergeTool/VstsMergeTool.cs
+++ /dev/null
@@ -1,246 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the License.txt file in the project root for more information.
-using Microsoft.TeamFoundation.SourceControl.WebApi;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace VstsMergeTool
-{
- public class VstsMergeTool
- {
- private const int Timeout = 1000 * 60;
-
- private readonly GitHttpClient gitHttpClient;
-
- private Settings Settings = Settings.Default;
-
- private readonly string SourceName;
-
- private readonly string DestName;
-
- private readonly string SourceBranch;
-
- private readonly string DestBranch;
-
- private readonly string DummyBranchName;
-
- private int AutoPullRequestId;
-
- private Guid RepositoryId;
-
- private CancellationTokenSource Cts;
-
- public VstsMergeTool(GitHttpClient gitHttpClient, string sourceBranch, string destBranch)
- {
- this.gitHttpClient = gitHttpClient;
-
- var source = sourceBranch.Split('/');
- SourceName = source[source.Length - 1];
-
- var dest = destBranch.Split('/');
- DestName = dest[dest.Length - 1];
-
- this.SourceBranch = sourceBranch.StartsWith("refs/heads/") ? sourceBranch : $"refs/heads/{sourceBranch}";
- this.DestBranch = destBranch.StartsWith("refs/heads/") ? destBranch : $"refs/heads/{destBranch}";
-
- this.DummyBranchName = $"refs/heads/merge/{SourceName}-to-{DestName}";
- this.Cts = new CancellationTokenSource();
- }
-
- public async Task<(bool isPrCreated, string message)> CreatePullRequest()
- {
- try
- {
- Cts.CancelAfter(Timeout);
- // Fetch the repository id according to repository name
- await GetRepositoryId(Settings.RepositoryName, Cts.Token);
-
- var branchInfo = await GetBranchInfoAsync(Cts.Token);
- var existingBranchNames = branchInfo.Select(b => b.Name);
-
- this.CheckBranchExists(existingBranchNames);
-
- // Check if there are existing dummybranch and open PR
- var isDummyBranchAndOpenPrExisting = await DoesDummyBranchAndOpenPrExist(existingBranchNames, Cts.Token);
-
- if (isDummyBranchAndOpenPrExisting)
- {
- return (false, "Previous auto merge is still in progress.");
- }
-
- if (!IsMergeRequired(branchInfo))
- {
- return (false, null);
- }
-
- // Create a dummy branch
- await CreateNewBranch(branchInfo, Cts.Token);
-
- // Create PR and get its id
- bool prCreated = await CreateNewPullRequest(DummyBranchName, Cts.Token);
-
- if (!prCreated)
- {
- return (false, "Fail to create new pull request");
- }
-
- Console.WriteLine("Pull Request is created");
-
- // TODO: 1. If there is no conflict, let source branch merge to dummy branch.
- // 2. If conflict existing, stop. When conflict is resolve, then merge.
- return (true, null);
- }
- catch (OperationCanceledException ex)
- {
- return (false, $"Timed out waiting for an operation: {ex.ToString()}");
- }
- catch (Exception ex)
- {
- // Gracefully exit.
- return (false, ex.ToString());
- }
- }
-
- private void CheckBranchExists(IEnumerable branchName)
- {
- if (!branchName.Contains(SourceBranch))
- {
- throw new ArgumentException($"{SourceBranch} does not exist.");
- }
-
- if (!branchName.Contains(DestBranch))
- {
- throw new ArgumentException($"{DestBranch} does not exist.");
- }
- }
-
- private async Task> GetBranchInfoAsync(CancellationToken token)
- {
- token.ThrowIfCancellationRequested();
-
- // Download the current Branch and pull Request information about this repo
- return await gitHttpClient.GetRefsAsync(
- project: Settings.TFSProjectName,
- repositoryId: RepositoryId,
- cancellationToken: token);
- }
-
- private async Task DoesDummyBranchAndOpenPrExist(IEnumerable branchNames, CancellationToken token)
- {
- token.ThrowIfCancellationRequested();
- if (branchNames.Contains(DummyBranchName))
- {
- // If the dummy branch exists, check if there is open PR exist
- var searchCriteria = new GitPullRequestSearchCriteria()
- {
- RepositoryId = this.RepositoryId,
- Status = PullRequestStatus.Active,
- TargetRefName = DestBranch,
- SourceRefName = DummyBranchName,
- };
-
- var response = await gitHttpClient.GetPullRequestsByProjectAsync(Settings.TFSProjectName, searchCriteria, cancellationToken: token);
- if (response.Count != 0)
- {
- // If there is an open PR, means the preious merge is not finished
- Console.WriteLine($"There are existing pull requests between {DummyBranchName} and {DestBranch}");
- return true;
- }
- else
- {
- // If there is no open PR, delete the dummy branch because we are going to create a new PR
- if (await TryRemoveBranch(DummyBranchName, token))
- {
- return false;
- }
- else
- {
- Console.WriteLine("Failed to delete old dummy branch.");
- return true;
- }
- }
- }
- else
- {
- return false;
- }
- }
-
- private async Task CreateNewPullRequest(string dummyBranchName, CancellationToken token)
- {
- token.ThrowIfCancellationRequested();
-
- var pullRequest = new GitPullRequest()
- {
- Title = $"AutoMerge PR from {SourceName} to {DestName}",
- SourceRefName = dummyBranchName,
- TargetRefName = DestBranch,
- };
-
- Console.WriteLine($"Creating a new Pull Request: {pullRequest.Title} on \"{dummyBranchName}\"");
-
- var response = await gitHttpClient.CreatePullRequestAsync(pullRequest, RepositoryId);
- Console.WriteLine($"Pull Request ID: {response.PullRequestId}, URL: {response.Url}");
- AutoPullRequestId = response.PullRequestId;
- return true;
- }
-
- private async Task CreateNewBranch(IEnumerable branchInfo, CancellationToken token)
- {
- token.ThrowIfCancellationRequested();
-
- Console.WriteLine($"Creating New Branch \"{DummyBranchName}\"");
- // Get the sha1 of the source branch
- var sourceBranchSha = branchInfo.Where(branch => string.Equals(branch.Name, SourceBranch)).Select(branch => branch.ObjectId).FirstOrDefault();
-
- var refUpdate = new List() { new GitRefUpdate() { IsLocked = false, OldObjectId = new string('0', 40), NewObjectId = sourceBranchSha, Name = DummyBranchName } };
-
- var response = await gitHttpClient.UpdateRefsAsync(refUpdate, RepositoryId);
- if (response.Where(res => !res.Success).Any())
- {
- throw new Exception("Fail to create a new branch");
- }
- }
-
- private bool IsMergeRequired(IEnumerable branchInfo)
- {
- var sourceBranchSha = branchInfo.Where(branch => string.Equals(branch.Name, SourceBranch)).Select(branch => branch.ObjectId).FirstOrDefault();
- var destBranchSha = branchInfo.Where(branch => string.Equals(branch.Name, DestBranch)).Select(branch => branch.ObjectId).FirstOrDefault();
-
- return !string.Equals(sourceBranchSha, destBranchSha);
- }
-
- private async Task GetRepositoryId(string repoName, CancellationToken token)
- {
- token.ThrowIfCancellationRequested();
- // Some request don't accept Repository name as parameter. Therefore, just use repository id.
- Console.WriteLine($"Trying to get {repoName}' id");
-
- var response = await gitHttpClient.GetRepositoriesAsync(Settings.TFSProjectName);
- this.RepositoryId = response.Where(repo => repo.Name == Settings.RepositoryName).First().Id;
- }
-
- private async Task TryRemoveBranch(string branchName, CancellationToken token)
- {
- token.ThrowIfCancellationRequested();
- var refDelete = new List() {
- new GitRefUpdate()
- {
- IsLocked = false,
- Name = branchName,
- OldObjectId = new string('0', 40),
- NewObjectId = new string('0', 40)
- }
- };
-
- Console.WriteLine($"Trying to delete {branchName}");
-
- var response = await gitHttpClient.UpdateRefsAsync(refDelete, RepositoryId);
- return !response.Where(res => !res.Success).Any();
- }
- }
-}
diff --git a/src/VstsMergeTool/VstsMergeTool.csproj b/src/VstsMergeTool/VstsMergeTool.csproj
deleted file mode 100644
index 16f975803a..0000000000
--- a/src/VstsMergeTool/VstsMergeTool.csproj
+++ /dev/null
@@ -1,51 +0,0 @@
-
-
-
-
-
- Library
- net46
- 7.1
-
-
-
- false
-
-
- true
-
-
-
- x64
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- True
- True
- Settings.settings
-
-
-
-
- SettingsSingleFileGenerator
- Settings.Designer.cs
-
-
-
-