LEFT | RIGHT |
1 using System.Diagnostics; | 1 /* |
| 2 Copyright 2013 Google Inc |
| 3 |
| 4 Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 you may not use this file except in compliance with the License. |
| 6 You may obtain a copy of the License at |
| 7 |
| 8 http://www.apache.org/licenses/LICENSE-2.0 |
| 9 |
| 10 Unless required by applicable law or agreed to in writing, software |
| 11 distributed under the License is distributed on an "AS IS" BASIS, |
| 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 See the License for the specific language governing permissions and |
| 14 limitations under the License. |
| 15 */ |
| 16 |
| 17 using System; |
| 18 using System.Collections.Generic; |
| 19 using System.Diagnostics; |
2 using System.IO; | 20 using System.IO; |
| 21 using System.Linq; |
3 using System.Reflection; | 22 using System.Reflection; |
4 using System.Threading.Tasks; | 23 using System.Threading.Tasks; |
5 | 24 |
| 25 using CommandLine; |
| 26 using CommandLine.Text; |
| 27 |
| 28 using Google.Apis.NuGet.Publisher.Discovery; |
| 29 using Google.Apis.Utils; |
| 30 |
6 namespace Google.Apis.NuGet.Publisher | 31 namespace Google.Apis.NuGet.Publisher |
7 { | 32 { |
| 33 /// <summary>The options class which contains the different options to this
utility.</summary> |
| 34 class Options |
| 35 { |
| 36 public const string ModeTest = "test"; |
| 37 public const string ModePublish = "publisher"; |
| 38 |
| 39 [Option('a', "all_apis", HelpText = "Define if NuGet publisher works on
all Google APIs")] |
| 40 public bool AllApis { get; set; } |
| 41 |
| 42 [Option('n', "api_name", HelpText = "Define the specific API to work on"
)] |
| 43 public string ApiName { get; set; } |
| 44 |
| 45 [Option('v', "api_version", HelpText = "Define the specific API version
to work on")] |
| 46 public string ApiVersion { get; set; } |
| 47 |
| 48 [Option('m', "mode", DefaultValue = "test", |
| 49 HelpText = "Indicate the mode of operation {" + ModeTest + "|" + Mod
ePublish + "}")] |
| 50 public string Mode { get; set; } |
| 51 |
| 52 [Option('k', "nuget_key", |
| 53 HelpText = @"Define the NuGet API key. If empty the publisher works
local on 'C:\LocalNuGetFeed'")] |
| 54 public string NuGetApiKey { get; set; } |
| 55 |
| 56 [Option('l', "library_version", |
| 57 HelpText = "Define the Google.Apis library which is used to download
the bundles (e.g. 1.5.0-beta)")] |
| 58 public string GoogleApisVersion { get; set; } |
| 59 |
| 60 [Option('d', "apis_directory", |
| 61 HelpText = "For testing purposes only. " + |
| 62 "It Defines the APIs directory which contains all the APIs we want t
o test.")] |
| 63 public string ApisDirectory { get; set; } |
| 64 |
| 65 [HelpOption] |
| 66 public string GetHelp() |
| 67 { |
| 68 return HelpText.AutoBuild(this, c => HelpText.DefaultParsingErrorsHa
ndler(this, c)); |
| 69 } |
| 70 } |
| 71 |
| 72 /// <summary> |
| 73 /// A Google APIs NuGet publisher which downloads the APIs latest bundles. F
or each API it checks if there a NuGet |
| 74 /// package doesn't exist for the client version and the API revision, and i
f so it builds a new NuGet package and |
| 75 /// publish it to NuGet main repository. |
| 76 /// </summary> |
| 77 /// <remarks> |
| 78 /// The Google APIs NuGet publisher uses a local folder "C:\LocalNuGetFeed"
to store all the NuGet packages |
| 79 /// locally. |
| 80 /// Notice also the different between bundle and package: |
| 81 /// A bundle is the zip file that contains the sources, and it's is download
ed from |
| 82 /// "https://google-api-client-libraries.appspot.com/" |
| 83 /// A package is the NuGet package we use to build a solution. We can store
NuGet packages locally (e.g. in |
| 84 /// "C:\LocalNuGetFeed") or use the main NuGet repository at "https://nuget.
org/api/v2/" |
| 85 /// </remarks> |
8 class Program | 86 class Program |
9 { | 87 { |
10 const string DiscoveryApiUrl = @"https://www.googleapis.com/discovery/v1
/apis"; | 88 private static TraceSource TraceSource = new TraceSource("Google.Apis"); |
11 | 89 |
12 const string OutputDirectory = @"C:\Temp\NuGetPublisher\"; | 90 /// <summary>The discovery URI to get all the public APIs.</summary> |
13 | 91 static readonly Uri DiscoveryApiUri = new Uri(@"https://www.googleapis.c
om/discovery/v1/apis"); |
14 const string DownloadUri = | 92 |
15 @"https://google-api-client-libraries.appspot.com/resources/api-libr
aries/download/stable/{0}/{1}/csharp?deps=0"; | 93 /// <summary>The download URI format to download a specific API format.
Two parameters are expected the API· |
16 | 94 /// name and its version.</summary> |
17 static readonly string TemplateDirectory; | 95 const string DownloadUriFormat = |
18 | 96 "https://google-api-client-libraries.appspot.com/download/library/{0
}/{1}/csharp?deps=0"; |
19 static Program() | 97 |
20 { | 98 /// <summary>The template directory which contains the '.nuget' director
y and the necessary·· |
21 var execDir = Assembly.GetEntryAssembly().Location; | 99 /// 'Microsoft.Bcl.Build.targets' file.</summary> |
| 100 readonly string TemplateDirectory; |
| 101 |
| 102 /// <summary>The directory that the bundle will be downloaded to.</summa
ry> |
| 103 readonly string DownloadBundleTempDirectory = Path.Combine(Path.GetTempP
ath(), "GoogleAPIsPublisher"); |
| 104 |
| 105 /// <summary>The program's options.</summary> |
| 106 readonly Options options; |
| 107 |
| 108 #region Main |
| 109 |
| 110 static void Main(string[] args) |
| 111 { |
| 112 var options = new Options(); |
| 113 if (!CommandLine.Parser.Default.ParseArguments(args, options)) |
| 114 { |
| 115 // TODO(peleyal): add explanation which option is missing. Curre
ntly the command line utility just |
| 116 // print the whole help without mention what is missing. |
| 117 } |
| 118 else if (!options.AllApis && (options.ApiName == null || options.Api
Version == null)) |
| 119 { |
| 120 Console.WriteLine("Please Set '--all_apis true' or the API name
and version, e.g. " + |
| 121 "'--api_name=drive --api_version=v2'"); |
| 122 } |
| 123 else if (!new[] { Options.ModePublish, Options.ModeTest }.Contains(o
ptions.Mode)) |
| 124 { |
| 125 Console.WriteLine("Mode should be '{0}' or '{1}'", Options.ModeT
est, Options.ModePublish); |
| 126 } |
| 127 else |
| 128 { |
| 129 |
| 130 try |
| 131 { |
| 132 new Program(options).Run().Wait(); |
| 133 } |
| 134 catch (AggregateException ex) |
| 135 { |
| 136 foreach (var inner in ex.InnerExceptions) |
| 137 { |
| 138 TraceSource.TraceEvent(TraceEventType.Error, "Exception
was thrown. {0}", inner.Message); |
| 139 } |
| 140 } |
| 141 } |
| 142 Console.ReadKey(); |
| 143 } |
| 144 |
| 145 #endregion |
| 146 |
| 147 Program(Options options) |
| 148 { |
| 149 this.options = options; |
22 // remove "Google.Apis.NuGet.Publisher\\bin\\{Debug|Release}\\Google
.Apis.NuGet.Publisher.exe" | 150 // remove "Google.Apis.NuGet.Publisher\\bin\\{Debug|Release}\\Google
.Apis.NuGet.Publisher.exe" |
23 for (int i = 0; i < 4; ++i) | 151 var fileInfo = new FileInfo(Assembly.GetEntryAssembly().Location); |
24 { | 152 TemplateDirectory = Path.Combine(fileInfo.Directory.Parent.Parent.Pa
rent.FullName, "Template"); |
25 execDir = execDir.Remove(execDir.LastIndexOf("\\")); | 153 } |
26 } | 154 |
27 TemplateDirectory = string.Format(@"{0}\Template\", execDir); | 155 Task Run() |
28 | 156 { |
29 } | 157 switch (options.Mode) |
30 | 158 { |
31 static void Main(string[] args) | 159 case Options.ModeTest: |
32 { | 160 return RunAsync("TEST", TestAsync); |
33 TestAsync().Wait(); | 161 case Options.ModePublish: |
34 } | 162 return RunAsync("PUBLISH", PublishAsync); |
35 | 163 default: |
36 static async Task MainAsync() | 164 throw new ArgumentException(string.Format("Mode should be {0
} or {1}", |
37 { | 165 Options.ModePublish, Options.ModeTest)); |
38 Trace.TraceInformation("=============== MAIN ==============="); | 166 } |
39 Trace.TraceInformation("Entering Google.Apis.Nuget.Publihser"); | 167 } |
40 | 168 |
41 var apis = await new DiscoveryService().GetApis(DiscoveryApiUrl); | 169 /// <summary>The main wrapper to run, gets a function to run which conta
ins the main logic.</summary> |
| 170 async Task RunAsync(string header, Func<IEnumerable<DiscoveryItem>, Task
> core) |
| 171 { |
| 172 TraceSource.TraceEvent(TraceEventType.Information, "===============
{0} ===============", header); |
| 173 TraceSource.TraceEvent(TraceEventType.Information, "Entering Google.
Apis.Nuget.Publihser"); |
| 174 |
| 175 IEnumerable<DiscoveryItem> apis; |
| 176 if (options.AllApis) |
| 177 { |
| 178 apis = await new DiscoveryService().GetApis(DiscoveryApiUri); |
| 179 } |
| 180 else |
| 181 { |
| 182 apis = new List<DiscoveryItem> { new DiscoveryItem |
| 183 { |
| 184 Name = options.ApiName.ToLower(), |
| 185 Version = options.ApiVersion.ToLower() |
| 186 }}; |
| 187 } |
| 188 |
| 189 if (Directory.Exists(DownloadBundleTempDirectory)) |
| 190 { |
| 191 Directory.Delete(DownloadBundleTempDirectory, true); |
| 192 } |
| 193 Directory.CreateDirectory(DownloadBundleTempDirectory); |
42 | 194 |
43 try | 195 try |
44 { | 196 { |
45 Directory.Delete(OutputDirectory, true); | 197 TraceSource.TraceEvent(TraceEventType.Information, "\"{0}\" fold
er was created", |
46 } | 198 DownloadBundleTempDirectory); |
47 catch (DirectoryNotFoundException) | 199 |
48 { | 200 await core(apis); |
49 // DO NOTHING | 201 |
50 } | 202 TraceSource.TraceEvent(TraceEventType.Information, 0, "Exiting G
oogle.Apis.Nuget.Publihser"); |
51 | 203 } |
52 Directory.CreateDirectory(OutputDirectory); | 204 finally |
53 | 205 { |
54 Trace.TraceInformation("\"{0}\" folder was created", OutputDirectory
); | 206 Directory.Delete(DownloadBundleTempDirectory, true); |
55 | 207 } |
56 foreach (var discoveryItem in apis) | 208 } |
57 { | 209 |
58 var workingDir = string.Format(@"{0}{1}-{2}\", OutputDirectory,
discoveryItem.Name, | 210 /// <summary>Publishes new APIs to NuGet main repository.</summary> |
59 discoveryItem.Version); | 211 async Task PublishAsync(IEnumerable<DiscoveryItem> apis) |
| 212 { |
| 213 // TODO(peleyal): validate NuGetApiKey |
| 214 foreach (var item in apis) |
| 215 { |
| 216 var workingDir = Path.Combine(DownloadBundleTempDirectory, |
| 217 item.Name + "-" + item.Version); |
60 Directory.CreateDirectory(workingDir); | 218 Directory.CreateDirectory(workingDir); |
61 var item = new ApiItem(discoveryItem) | 219 |
62 { | 220 var bundleUri = string.Format(DownloadUriFormat, item.Name, item
.Version); |
63 WorkingDirectory = workingDir, | 221 if (!string.IsNullOrEmpty(options.GoogleApisVersion)) |
64 DownloadUri = DownloadUri, | 222 { |
| 223 bundleUri = bundleUri + "&lv=" + options.GoogleApisVersion; |
| 224 } |
| 225 |
| 226 var publisher = new NuGetApiPublisher(item) |
| 227 { |
| 228 BundleDirectory = workingDir, |
| 229 BundleUri = new Uri(bundleUri), |
| 230 TemplateDirectory = TemplateDirectory, |
| 231 NuGetApiKey = options.NuGetApiKey, |
| 232 }; |
| 233 |
| 234 try |
| 235 { |
| 236 await publisher.Run(); |
| 237 } |
| 238 catch (Exception ex) |
| 239 { |
| 240 TraceSource.TraceEvent(TraceEventType.Error, "{0}\t Exceptio
n [{1}] occurred", item, ex.Message); |
| 241 } |
| 242 } |
| 243 } |
| 244 |
| 245 /// <summary> |
| 246 /// Tests the main logic behave as expected. <see cref="NuGetApiPublishe
r.Test"/> for more details. |
| 247 /// </summary> |
| 248 async Task TestAsync(IEnumerable<DiscoveryItem> apis) |
| 249 { |
| 250 foreach (var item in apis) |
| 251 { |
| 252 var publisher = new NuGetApiPublisher(item) |
| 253 { |
65 TemplateDirectory = TemplateDirectory, | 254 TemplateDirectory = TemplateDirectory, |
66 }; | 255 }; |
67 await item.Test(@"Z:\Shared\NuGet\apis\default\"); | 256 try |
68 } | 257 { |
69 | 258 await publisher.Test(options.ApisDirectory); |
70 Trace.TraceInformation("Exiting Google.Apis.Nuget.Publihser"); | 259 } |
71 } | 260 catch (Exception ex) |
72 | 261 { |
73 static async Task TestAsync() | 262 TraceSource.TraceEvent(TraceEventType.Error, "{0}\t Exceptio
n [{1}] occurred", item, ex.Message); |
74 { | 263 } |
75 Trace.TraceInformation("=============== TEST ==============="); | 264 } |
76 Trace.TraceInformation("Entering Google.Apis.Nuget.Publihser"); | |
77 | |
78 var apis = await new DiscoveryService().GetApis(DiscoveryApiUrl); | |
79 | |
80 if (Directory.Exists(OutputDirectory)) | |
81 { | |
82 Directory.Delete(OutputDirectory, true); | |
83 } | |
84 Directory.CreateDirectory(OutputDirectory); | |
85 | |
86 Trace.TraceInformation("\"{0}\" folder was created", OutputDirectory
); | |
87 | |
88 foreach (var discoveryItem in apis) | |
89 { | |
90 var item = new ApiItem(discoveryItem) | |
91 { | |
92 TemplateDirectory = TemplateDirectory, | |
93 }; | |
94 await item.Test(@"c:\NuGet\apis\default\"); | |
95 } | |
96 | |
97 Trace.TraceInformation("Exiting Google.Apis.Nuget.Publihser"); | |
98 } | 265 } |
99 } | 266 } |
100 } | 267 } |
LEFT | RIGHT |