Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 /* | 1 /* |
2 Copyright 2013 Google Inc | 2 Copyright 2013 Google Inc |
3 | 3 |
4 Licensed under the Apache License, Version 2.0 (the "License"); | 4 Licensed under the Apache License, Version 2.0 (the "License"); |
5 you may not use this file except in compliance with 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 | 6 You may obtain a copy of the License at |
7 | 7 |
8 http://www.apache.org/licenses/LICENSE-2.0 | 8 http://www.apache.org/licenses/LICENSE-2.0 |
9 | 9 |
10 Unless required by applicable law or agreed to in writing, software | 10 Unless required by applicable law or agreed to in writing, software |
(...skipping 13 matching lines...) Expand all Loading... | |
24 using System.Text.RegularExpressions; | 24 using System.Text.RegularExpressions; |
25 using Microsoft.Build.Evaluation; | 25 using Microsoft.Build.Evaluation; |
26 using Microsoft.Build.Framework; | 26 using Microsoft.Build.Framework; |
27 using Microsoft.Build.Logging; | 27 using Microsoft.Build.Logging; |
28 | 28 |
29 using CommandLine; | 29 using CommandLine; |
30 using CommandLine.Text; | 30 using CommandLine.Text; |
31 using Ionic.Zip; | 31 using Ionic.Zip; |
32 | 32 |
33 using Google.Apis.Release.Repositories; | 33 using Google.Apis.Release.Repositories; |
34 using Google.Apis.Release.Wiki; | |
34 using Google.Apis.Utils; | 35 using Google.Apis.Utils; |
35 using Google.Apis.Release.Wiki; | 36 using Google.Apis.Utils.Trace; |
36 | 37 |
37 namespace Google.Apis.Release | 38 namespace Google.Apis.Release |
38 { | 39 { |
39 /// <summary>The main program for creating a new Google.Apis release.</summa ry> | 40 /// <summary>The main program for creating a new Google.Apis release.</summa ry> |
40 class Program | 41 class Program |
41 { | 42 { |
42 /// <summary>The options class which contains the different options to t his publish release utility.</summary> | 43 /// <summary>The options class which contains the different options to t his publish release utility.</summary> |
43 public class Options | 44 public class Options |
44 { | 45 { |
45 #region HelpText | 46 #region HelpText |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
85 private int MajorVersion { get; set; } | 86 private int MajorVersion { get; set; } |
86 private int MinorVersion { get; set; } | 87 private int MinorVersion { get; set; } |
87 private int BuildVersion { get; set; } | 88 private int BuildVersion { get; set; } |
88 | 89 |
89 private string Tag | 90 private string Tag |
90 { | 91 { |
91 get { return options.Version (options.IsBeta ? "-beta" : ""); } | 92 get { return options.Version (options.IsBeta ? "-beta" : ""); } |
92 } | 93 } |
93 | 94 |
94 /// <summary>Gets or sets the "default" repository.</summary> | 95 /// <summary>Gets or sets the "default" repository.</summary> |
95 private Hg DefaultRepository { get; set; } | 96 private Hg DefaultRepository { get; set; } |
David waters
2013/09/19 16:22:32
If Hg has not changed since I last looked at it (
peleyal
2013/09/20 18:56:18
I changed it a little bit.
It does the job, and we
| |
96 | 97 |
97 /// <summary>Gets or sets the "samples" repository.</summary> | 98 /// <summary>Gets or sets the "samples" repository.</summary> |
98 private Hg SamplesRepository { get; set; } | 99 private Hg SamplesRepository { get; set; } |
99 | 100 |
100 /// <summary>Gets or sets the "wiki" repository.</summary> | 101 /// <summary>Gets or sets the "wiki" repository.</summary> |
101 private Hg WikiRepository { get; set; } | 102 private Hg WikiRepository { get; set; } |
102 | 103 |
103 /// <summary>Gets or sets the "contrib" repository.</summary> | 104 /// <summary>Gets or sets the "contrib" repository.</summary> |
104 private Hg ContribRepository { get; set; } | 105 private Hg ContribRepository { get; set; } |
105 | 106 |
106 /// <summary>Gets all four repositories.</summary> | 107 /// <summary>Gets all four repositories.</summary> |
107 private IEnumerable<Hg> AllRepositories | 108 private IEnumerable<Hg> AllRepositories |
108 { | 109 { |
109 get { return new List<Hg> { DefaultRepository, SamplesRepository, Wi kiRepository, ContribRepository }; } | 110 get { return new List<Hg> { DefaultRepository, SamplesRepository, Wi kiRepository, ContribRepository }; } |
110 } | 111 } |
111 | 112 |
113 /// <summary> | |
114 /// Clones URL format which expects one parameter of the repository name (the default repository should be· | |
115 /// empty). | |
116 /// </summary> | |
117 private const string CloneUrlFormat = "https://code.google.com/p/google- api-dotnet-client{0}/"; | |
118 | |
112 static void Main(string[] args) | 119 static void Main(string[] args) |
113 { | 120 { |
121 bool valid = true; | |
122 | |
114 var options = new Options(); | 123 var options = new Options(); |
115 if (!CommandLine.Parser.Default.ParseArguments(args, options)) | 124 if (!CommandLine.Parser.Default.ParseArguments(args, options)) |
116 { | 125 { |
117 Console.ReadKey(); | 126 Console.ReadKey(); |
118 return; | 127 return; |
119 } | 128 } |
120 | 129 |
David waters
2013/09/19 16:22:32
if(options.Step > 2 || < 1)
user.tell("Dude! got
peleyal
2013/09/20 18:56:18
Done.
| |
130 if (options.Step > 2 || options.Step < 1) | |
131 { | |
132 TraceSource.TraceEvent(TraceEventType.Error, "Invalid Step. Vali d step is '1' or '2'."); | |
133 valid = false; | |
134 } | |
135 | |
121 var match = Regex.Match(options.Version, @"^(\d )\.(\d )\.(\d) $"); | 136 var match = Regex.Match(options.Version, @"^(\d )\.(\d )\.(\d) $"); |
122 if (!match.Success) | 137 if (!match.Success) |
123 { | 138 { |
124 TraceSource.TraceEvent(TraceEventType.Error, | 139 TraceSource.TraceEvent(TraceEventType.Error, |
125 "Invalid version Number. Version should be in <Major>.<Minor >.<Build> form."); | 140 "Invalid version Number. Version should be in <Major>.<Minor >.<Build> form."); |
141 valid = false; | |
126 } | 142 } |
127 | 143 |
128 var program = new Program(options) | 144 var program = new Program(options) |
129 { | 145 { |
130 MajorVersion = int.Parse(match.Groups[1].Value), | 146 MajorVersion = int.Parse(match.Groups[1].Value), |
131 MinorVersion = int.Parse(match.Groups[2].Value), | 147 MinorVersion = int.Parse(match.Groups[2].Value), |
132 BuildVersion = int.Parse(match.Groups[3].Value), | 148 BuildVersion = int.Parse(match.Groups[3].Value), |
133 }; | 149 }; |
134 | 150 |
135 try | 151 if (valid) |
136 { | 152 { |
137 program.Run(); | 153 try |
138 } | 154 { |
139 catch (Exception ex) | 155 program.Run(); |
140 { | 156 } |
141 TraceSource.TraceEvent(TraceEventType.Error, "Exception occurred while running. Exception is: {0}", | 157 catch (Exception ex) |
142 ex.Message); | 158 { |
159 TraceSource.TraceEvent(TraceEventType.Error, "Exception occu rred while running. Exception is: {0}", | |
160 ex.Message); | |
161 } | |
143 } | 162 } |
144 | 163 |
145 Console.WriteLine("Press any key to continue..."); | 164 Console.WriteLine("Press any key to continue..."); |
146 Console.ReadKey(); | 165 Console.ReadKey(); |
147 } | 166 } |
148 | 167 |
149 /// <summary>The main release logic for creating a new release of Google .Apis.</summary> | 168 /// <summary>The main release logic for creating a new release of Google .Apis.</summary> |
150 private void Run() | 169 private void Run() |
151 { | 170 { |
152 const string CloneUrl = "https://code.google.com/p/google-api-dotnet -client{0}/"; | 171 DefaultRepository = new Hg(new Uri(string.Format(CloneUrlFormat, "") ), "default"); |
153 | |
154 DefaultRepository = new Hg(new Uri(string.Format(CloneUrl, "")), "de fault"); | |
155 | 172 |
156 // Step 1 is only for creating Google.Apis and Google.Apis.Authentic ation packages | 173 // Step 1 is only for creating Google.Apis and Google.Apis.Authentic ation packages |
157 if (options.Step == 1) | 174 if (options.Step == 1) |
David waters
2013/09/19 16:22:32
Consider
if(step 1)
{
doBaseStep(); // Or better
peleyal
2013/09/20 18:56:18
Done.
| |
158 { | 175 { |
159 if (BuildVersion != 0) | 176 DoStep1(); |
160 { | 177 } |
161 DefaultRepository.Update(string.Format("{0}.{1}", MajorVersi on, MinorVersion)); | |
162 } | |
163 | |
164 if (!HasIncomingChanges(new List<Hg> { DefaultRepository })) | |
David waters
2013/09/19 16:22:32
Do vararg parameters in c# allow passing in lists?
peleyal
2013/09/20 18:56:18
I hate vargas. I prefer enumerable. That's my styl
| |
165 { | |
166 if (BuildDefaultRepository()) | |
167 { | |
168 CreateNuGetPackages(); | |
David waters
2013/09/19 16:22:32
CreateCoreNuGetPackages ?
peleyal
2013/09/20 18:56:18
Done.
| |
169 // TODO(peleyal): release notes should be part of the pa ckage | |
170 } | |
David waters
2013/09/19 16:22:32
Good to have else clauses for both these if statme
peleyal
2013/09/20 18:56:18
Actually no necessary cause it will be printed by
| |
171 } | |
172 } | |
173 | |
174 // Step 2 should be done after the NuGet publisher generated all the APIs and the samples repository was· | 178 // Step 2 should be done after the NuGet publisher generated all the APIs and the samples repository was· |
175 // updated with the new packages | 179 // updated with the new packages |
176 else if (options.Step == 2) | 180 else if (options.Step == 2) |
177 { | 181 { |
178 Console.WriteLine(); | 182 DoStep2(); |
179 Console.WriteLine(); | 183 } |
184 } | |
185 | |
186 /// <summary>Creates Google.Apis and Google.Apis.Authentication packages .</summary> | |
187 private void DoStep1() | |
188 { | |
189 if (BuildVersion != 0) | |
190 { | |
191 DefaultRepository.Update(string.Format("{0}.{1}", MajorVersion, MinorVersion)); | |
192 } | |
193 | |
194 // if there are incoming changes those changes will be printed, othe rwise we can continue in the process | |
195 if (!HasIncomingChanges(new List<Hg> { DefaultRepository })) | |
196 { | |
197 // in case build fails the method will print its failures | |
198 if (BuildDefaultRepository()) | |
199 { | |
200 CreateCoreNuGetPackages(); | |
201 // TODO(peleyal): release notes should be part of the packag e | |
202 } | |
203 } | |
204 } | |
205 | |
206 /// <summary> | |
207 /// Doing the following: | |
208 /// <list type="number"> | |
209 /// <item><description>Builds samples</description></item> | |
210 /// <item><description>Creates a release notes</description></item> | |
211 /// <item><description>Update wiki download page</description></item> | |
212 /// <item><description>Create a new release in the contrib repository</d escription></item> | |
213 /// <item><description>Commits, Tags and Pushes</description></item> | |
214 /// </list> | |
215 /// </summary> | |
216 private void DoStep2() | |
217 { | |
218 Console.WriteLine(); | |
219 Console.WriteLine(); | |
220 Console.WriteLine("========================="); | |
221 Console.WriteLine("Prerequisites for Step 2:"); | |
222 Console.WriteLine("You ran Step 1."); | |
223 Console.WriteLine("You upgraded the Google.Apis NuGet packages for e ach sample in the samples " | |
224 "repository and pushed that change."); | |
225 Console.WriteLine("========================="); | |
226 if (!CanContinue()) | |
227 { | |
228 return; | |
229 } | |
230 | |
231 SamplesRepository = new Hg(new Uri(string.Format(CloneUrlFormat, ".s amples")), "samples"); | |
232 WikiRepository = new Hg(new Uri(string.Format(CloneUrlFormat, ".wiki ")), "wiki"); | |
233 ContribRepository = new Hg(new Uri(string.Format(CloneUrlFormat, ".c ontrib")), "contrib"); | |
234 | |
235 // if there are incoming changes those changes will be printed, othe rwise we can continue in the· | |
236 // process | |
237 if (!HasIncomingChanges(AllRepositories)) | |
238 { | |
239 BuildSamples(); | |
240 var notes = CreateContribNewRelease(); | |
241 UpdateWiki(notes); | |
242 | |
243 foreach (var repository in AllRepositories) | |
244 { | |
245 repository.AddRemoveFiles(); | |
246 } | |
247 | |
180 Console.WriteLine("========================="); | 248 Console.WriteLine("========================="); |
181 Console.WriteLine("Prerequisites for Step 2:"); | 249 Console.WriteLine("Commit, Tag and Push"); |
182 Console.WriteLine("You ran Step 1."); | |
183 Console.WriteLine("You upgraded the Google.Apis NuGet packages f or each sample in the samples " | |
184 "repository and pushed that change."); | |
185 Console.WriteLine("========================="); | 250 Console.WriteLine("========================="); |
186 if (CanContinue()) | 251 if (!CanContinue()) |
David waters
2013/09/19 16:22:32
Consider:I would reverse this if condition to redu
peleyal
2013/09/20 18:56:18
Done.
| |
187 { | 252 { |
188 SamplesRepository = new Hg(new Uri(string.Format(CloneUrl, " .samples")), "samples"); | 253 return; |
David waters
2013/09/19 16:22:32
Is constructing new Hg expensive?
If not it may be
peleyal
2013/09/20 18:56:18
it's actually not null.
because that's done before
| |
189 WikiRepository = new Hg(new Uri(string.Format(CloneUrl, ".wi ki")), "wiki"); | 254 } |
190 ContribRepository = new Hg(new Uri(string.Format(CloneUrl, " .contrib")), "contrib"); | 255 |
191 | 256 // commit |
192 // if there are incoming changes those changes will be print ed, otherwise we can continue in the· | 257 CommitAndTag(); |
193 // process | 258 |
194 if (!HasIncomingChanges(AllRepositories)) | 259 // push |
195 { | 260 foreach (Hg repository in AllRepositories) |
196 BuildSamples(); | 261 { |
197 var notes = CreateContribNewRelease(); | 262 repository.Push(); |
198 UpdateWiki(notes); | 263 } |
199 | 264 |
200 foreach (var repository in AllRepositories) | 265 // create branch |
201 { | 266 PrintCreateBranch(); |
202 repository.AddRemoveFiles(); | 267 |
203 } | 268 // publish core components to NuGet |
204 | 269 if (!string.IsNullOrEmpty(options.NuGetApiKey)) |
205 Console.WriteLine("========================="); | 270 { |
206 Console.WriteLine("Commit, Tag and Push"); | 271 PublishPackagesToNuGet(); |
207 Console.WriteLine("========================="); | 272 Console.WriteLine("Now... you should run the NuGet publisher to publish a new PCL " |
208 if (CanContinue()) | 273 "for each generated Google API. Run: " |
209 { | 274 "Google.Apis.NuGet.Publisher --all_apis true -m publishe r -k [NUGET_KEY]"); |
210 // commit | 275 } |
211 CommitAndTag(); | 276 else |
212 | 277 { |
213 // push | 278 TraceSource.TraceEvent(TraceEventType.Error, "NuGet API key is empty!"); |
214 foreach (Hg repository in AllRepositories) | 279 } |
215 { | |
216 repository.Push(); | |
217 } | |
218 | |
219 // create branch | |
220 PrintCreateBranch(); | |
221 | |
222 // publish core components to NuGet | |
223 if (!string.IsNullOrEmpty(options.NuGetApiKey)) | |
224 { | |
225 PublishPackagesToNuGet(); | |
226 Console.WriteLine("Now... you should run the NuG et publisher to publish a new PCL " | |
227 "for each generated Google API. Run: " | |
228 "Google.Apis.NuGet.Publisher --all_apis true -m publisher -k [NUGET_KEY]"); | |
229 } | |
230 else | |
231 { | |
232 TraceSource.TraceEvent(TraceEventType.Error, "Nu Get API key is empty!"); | |
233 } | |
234 } | |
235 } | |
236 } | |
237 } | |
238 else | |
239 { | |
240 TraceSource.TraceEvent(TraceEventType.Error, "Invalid step optio n!"); | |
241 } | 280 } |
242 } | 281 } |
243 | 282 |
244 /// <summary>Asks the user if he wants to continue in the process.</summ ary> | 283 /// <summary>Asks the user if he wants to continue in the process.</summ ary> |
245 /// <returns><c>true</c> if the user to press 'y' or 'yes' to continue</ returns> | 284 /// <returns><c>true</c> if the user to press 'y' or 'yes' to continue</ returns> |
246 private bool CanContinue() | 285 private bool CanContinue() |
247 { | 286 { |
248 var yesOptions = new[] { "y", "yes" }; | 287 var yesOptions = new[] { "y", "yes" }; |
249 var noOptions = new[] { "n", "no" }; | 288 var noOptions = new[] { "n", "no" }; |
250 | 289 |
251 string input; | 290 string input; |
252 do | 291 do |
253 { | 292 { |
254 Console.WriteLine("Press 'y' | 'yes' to continue, or 'n' | 'no' to stop"); | 293 Console.WriteLine("Press 'y' | 'yes' to continue, or 'n' | 'no' to stop"); |
255 input = Console.ReadLine(); | 294 input = Console.ReadLine().ToLower(); |
David waters
2013/09/19 16:22:32
consider:
input = Console.ReadLine().toLowerCase()
peleyal
2013/09/20 18:56:18
Done.
| |
256 } while (!yesOptions.Contains(input) && !noOptions.Contains(input)); | 295 } while (!yesOptions.Contains(input) && !noOptions.Contains(input)); |
257 | 296 |
258 return yesOptions.Contains(input); | 297 return yesOptions.Contains(input); |
259 } | 298 } |
260 | 299 |
261 /// <summary>Publishes the core packages to NuGet main repository.</summ ary> | 300 /// <summary>Publishes the core packages to NuGet main repository.</summ ary> |
262 private void PublishPackagesToNuGet() | 301 private void PublishPackagesToNuGet() |
263 { | 302 { |
264 var apiNupkgPath = Path.Combine(NuGetUtilities.LocalNuGetPackageFold er, | 303 var apiNupkgPath = Path.Combine(NuGetUtilities.LocalNuGetPackageFold er, |
265 string.Format("Google.Apis.{0}.nupkg", Tag)); | 304 string.Format("Google.Apis.{0}.nupkg", Tag)); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
337 { | 376 { |
338 TraceSource.TraceEvent(TraceEventType.Information, "Building Contrib release"); | 377 TraceSource.TraceEvent(TraceEventType.Information, "Building Contrib release"); |
339 | 378 |
340 string releaseDir = ContribRepository.Combine(Tag); | 379 string releaseDir = ContribRepository.Combine(Tag); |
341 | 380 |
342 // Clear existing directories. | 381 // Clear existing directories. |
343 DirectoryUtilities.ClearOrCreateDirectory(releaseDir); | 382 DirectoryUtilities.ClearOrCreateDirectory(releaseDir); |
344 string genDir = Path.Combine(releaseDir, "Generated"); | 383 string genDir = Path.Combine(releaseDir, "Generated"); |
345 Directory.CreateDirectory(genDir); | 384 Directory.CreateDirectory(genDir); |
346 | 385 |
347 #region [RELEASE_VERSION]/Generated/Bin | 386 #region [RELEASE_VERSION]/Generated/Bin |
David waters
2013/09/19 16:22:32
Consider:I would be inclinded to break these #regi
peleyal
2013/09/20 18:56:18
In general I agree with you, but because it's only
| |
348 | 387 |
349 string binDir = Path.Combine(genDir, "Bin"); | 388 string binDir = Path.Combine(genDir, "Bin"); |
350 TraceSource.TraceEvent(TraceEventType.Information, "Generating \"{0} \" directory", | 389 TraceSource.TraceEvent(TraceEventType.Information, "Generating \"{0} \" directory", |
351 DirectoryUtilities.GetRelativePath(binDir, ContribRepository.Wor kingDirectory)); | 390 DirectoryUtilities.GetRelativePath(binDir, ContribRepository.Wor kingDirectory)); |
352 | 391 |
353 Directory.CreateDirectory(binDir); | 392 Directory.CreateDirectory(binDir); |
354 foreach (var project in ReleaseProjects) | 393 foreach (var project in ReleaseProjects) |
355 { | 394 { |
356 var releasePath = Path.Combine(project.DirectoryPath, "Bin", "Re lease"); | 395 var releasePath = Path.Combine(project.DirectoryPath, "Bin", "Re lease"); |
357 foreach (var filePath in Directory.GetFiles(releasePath, "Google .Apis.*")) | 396 foreach (var filePath in Directory.GetFiles(releasePath, "Google .Apis.*")) |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
491 { | 530 { |
492 TraceSource.TraceEvent(TraceEventType.Error, | 531 TraceSource.TraceEvent(TraceEventType.Error, |
493 "[{0}] has incoming changes. Run hg pull & update first! ", repository.Name); | 532 "[{0}] has incoming changes. Run hg pull & update first! ", repository.Name); |
494 return true; | 533 return true; |
495 } | 534 } |
496 } | 535 } |
497 return false; | 536 return false; |
498 } | 537 } |
499 | 538 |
500 /// <summary>Creates the Google.Apis and Google.Apis.Authentication NuGe t packages.</summary> | 539 /// <summary>Creates the Google.Apis and Google.Apis.Authentication NuGe t packages.</summary> |
501 private void CreateNuGetPackages() | 540 private void CreateCoreNuGetPackages() |
502 { | 541 { |
503 // create a resource dir in the working folder | 542 // create a resource dir in the working folder |
504 var destDirectory = Path.Combine(Environment.CurrentDirectory, "Reso urces"); | 543 var destDirectory = Path.Combine(Environment.CurrentDirectory, "Reso urces"); |
505 if (Directory.Exists(destDirectory)) | 544 if (Directory.Exists(destDirectory)) |
506 { | 545 { |
507 Directory.Delete(destDirectory, true); | 546 Directory.Delete(destDirectory, true); |
508 } | 547 } |
509 | 548 |
510 FileInfo info = new FileInfo(Assembly.GetEntryAssembly().Location); | 549 FileInfo info = new FileInfo(Assembly.GetEntryAssembly().Location); |
511 DirectoryUtilities.CopyDirectory(Path.Combine(info.Directory.FullNam e, "Resources"), destDirectory); | 550 DirectoryUtilities.CopyDirectory(Path.Combine(info.Directory.FullNam e, "Resources"), destDirectory); |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
603 string path = Path.GetFullPath(options.OutputDirectory); | 642 string path = Path.GetFullPath(options.OutputDirectory); |
604 if (!Directory.Exists(path)) | 643 if (!Directory.Exists(path)) |
605 { | 644 { |
606 Directory.CreateDirectory(path); | 645 Directory.CreateDirectory(path); |
607 } | 646 } |
608 | 647 |
609 Environment.CurrentDirectory = path; | 648 Environment.CurrentDirectory = path; |
610 } | 649 } |
611 } | 650 } |
612 } | 651 } |
LEFT | RIGHT |