From 7ba6e5498ad2c5342cb25ba5fdc31d2b346a0dad Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Thu, 21 Oct 2021 10:24:25 -0700 Subject: [PATCH] Remove unused keyvault-related projects (#1110) --- .azure-ci.yaml | 2 +- RoslynTools.sln | 46 +- .../AzureFunctionPackage.csproj | 77 - src/AzureFunctionPackage/CreateZipPackage.ps1 | 7 - .../Functions/Common/VstsPrConfig.xml | 5 - .../Functions/Common/auth.csx | 26 - .../Functions/Directory.Build.targets | 43 - .../Functions/VstsCreateMergePRs/Program.cs | 11 - .../VstsCreateMergePRs.csproj | 45 - .../VstsCreateMergePRs/function.json | 11 - .../Functions/VstsCreateMergePRs/project.json | 16 - .../Functions/VstsCreateMergePRs/run.csx | 61 - src/AzureFunctionPackage/Program.cs | 12 - src/AzureFunctionPackage/host.json | 3 - src/BuildCleanupTool/BuildCleanupTool.csproj | 18 - src/BuildCleanupTool/Mono.Options/Options.cs | 1435 ----------------- src/BuildCleanupTool/Program.cs | 203 --- src/BuildRetainer/BuildRetainer.cs | 426 ----- src/BuildRetainer/BuildRetainer.csproj | 32 - src/BuildRetainer/Mono.Options/Options.cs | 1435 ----------------- src/BuildRetainer/Options.cs | 17 - src/BuildRetainer/Program.cs | 52 - src/BuildRetainer/RetainBuilds.ps1 | 28 - src/BuildRetainer/Settings.Designer.cs | 110 -- src/BuildRetainer/Settings.settings | 36 - src/BuildRetainer/app.config | 42 - src/VstsMergeTool/Initializer.cs | 73 - src/VstsMergeTool/Properties/AssemblyInfo.cs | 38 - src/VstsMergeTool/Settings.Designer.cs | 92 -- src/VstsMergeTool/Settings.settings | 30 - src/VstsMergeTool/VstsMergeTool.cs | 246 --- src/VstsMergeTool/VstsMergeTool.csproj | 51 - 32 files changed, 2 insertions(+), 4727 deletions(-) delete mode 100644 src/AzureFunctionPackage/AzureFunctionPackage.csproj delete mode 100644 src/AzureFunctionPackage/CreateZipPackage.ps1 delete mode 100644 src/AzureFunctionPackage/Functions/Common/VstsPrConfig.xml delete mode 100644 src/AzureFunctionPackage/Functions/Common/auth.csx delete mode 100644 src/AzureFunctionPackage/Functions/Directory.Build.targets delete mode 100644 src/AzureFunctionPackage/Functions/VstsCreateMergePRs/Program.cs delete mode 100644 src/AzureFunctionPackage/Functions/VstsCreateMergePRs/VstsCreateMergePRs.csproj delete mode 100644 src/AzureFunctionPackage/Functions/VstsCreateMergePRs/function.json delete mode 100644 src/AzureFunctionPackage/Functions/VstsCreateMergePRs/project.json delete mode 100644 src/AzureFunctionPackage/Functions/VstsCreateMergePRs/run.csx delete mode 100644 src/AzureFunctionPackage/Program.cs delete mode 100644 src/AzureFunctionPackage/host.json delete mode 100644 src/BuildCleanupTool/BuildCleanupTool.csproj delete mode 100644 src/BuildCleanupTool/Mono.Options/Options.cs delete mode 100644 src/BuildCleanupTool/Program.cs delete mode 100644 src/BuildRetainer/BuildRetainer.cs delete mode 100644 src/BuildRetainer/BuildRetainer.csproj delete mode 100644 src/BuildRetainer/Mono.Options/Options.cs delete mode 100644 src/BuildRetainer/Options.cs delete mode 100644 src/BuildRetainer/Program.cs delete mode 100644 src/BuildRetainer/RetainBuilds.ps1 delete mode 100644 src/BuildRetainer/Settings.Designer.cs delete mode 100644 src/BuildRetainer/Settings.settings delete mode 100644 src/BuildRetainer/app.config delete mode 100644 src/VstsMergeTool/Initializer.cs delete mode 100644 src/VstsMergeTool/Properties/AssemblyInfo.cs delete mode 100644 src/VstsMergeTool/Settings.Designer.cs delete mode 100644 src/VstsMergeTool/Settings.settings delete mode 100644 src/VstsMergeTool/VstsMergeTool.cs delete mode 100644 src/VstsMergeTool/VstsMergeTool.csproj 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 - - - -