Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(931)

Delta Between Two Patch Sets: Tools/Google.Apis.Release/Program.cs

Issue 12767046: Issue 377: New build for releasing a new version (Closed) Base URL: https://google-api-dotnet-client.googlecode.com/hg/
Left Patch Set: Using this tool to release 1.5.0-beta Created 10 years, 7 months ago
Right Patch Set: david comments Created 10 years, 6 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « Tools/Google.Apis.Release/Google.Apis.Release.csproj ('k') | Tools/Google.Apis.Release/ProjectExtenstions.cs » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 using System; 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;
2 using System.Collections.Generic; 18 using System.Collections.Generic;
3 using System.Diagnostics; 19 using System.Diagnostics;
4 using System.IO; 20 using System.IO;
5 using System.Linq; 21 using System.Linq;
6 using System.Reflection; 22 using System.Reflection;
7 using System.Text; 23 using System.Text;
8 using System.Text.RegularExpressions; 24 using System.Text.RegularExpressions;
25 using Microsoft.Build.Evaluation;
26 using Microsoft.Build.Framework;
27 using Microsoft.Build.Logging;
9 28
10 using CommandLine; 29 using CommandLine;
11 using CommandLine.Text; 30 using CommandLine.Text;
12 using Ionic.Zip; 31 using Ionic.Zip;
13 using Microsoft.Build.Evaluation;
14 using Microsoft.Build.Framework;
15 using Microsoft.Build.Logging;
16 32
17 using Google.Apis.Release.Repositories; 33 using Google.Apis.Release.Repositories;
34 using Google.Apis.Release.Wiki;
18 using Google.Apis.Utils; 35 using Google.Apis.Utils;
19 using Google.Apis.Release.Wiki; 36 using Google.Apis.Utils.Trace;
20 37
21 namespace Google.Apis.Release 38 namespace Google.Apis.Release
22 { 39 {
40 /// <summary>The main program for creating a new Google.Apis release.</summa ry>
23 class Program 41 class Program
24 { 42 {
43 /// <summary>The options class which contains the different options to t his publish release utility.</summary>
25 public class Options 44 public class Options
26 { 45 {
27 #region HelpText 46 #region HelpText
28 47
29 const string VersionHelpText = "The version number of this release - <Major.Minor.Build> only."; 48 const string VersionHelpText = "The version number of this release - <Major.Minor.Build> only.";
30 const string OutputHelpText = "Define the output directory for this build. " + 49 const string OutputHelpText = "Define the output directory for this build. " +
31 "Notice that it's relative to current directory."; 50 "Notice that it's relative to current directory.";
32 const string StepHelpText = "Two options: '1' for building the core library \n" + 51 const string StepHelpText = "Two options: " +
33 "'2' for compiling samples, updating wiki and push to contrib th e new version \n" + 52 "'1' for building the core library. \n" +
34 "'3' for publishing on the local packages to NuGet"; 53 "'2' for compiling samples, updating wiki and push to contrib th e new version.";
35 const string IsBetaHelpText = "Is this release is beta?"; 54 const string IsBetaHelpText = "Is this release beta?";
36 const string NuGetApiKeyHelpText = "Define the NuGet API key to publ ish to NuGet main repository"; 55 const string NuGetApiKeyHelpText = "Define the NuGet API key to publ ish to NuGet main repository.";
37 56
38 [HelpOption] 57 [HelpOption]
39 public string GetHelp() 58 public string GetHelp()
40 { 59 {
41 return HelpText.AutoBuild(this, c => HelpText.DefaultParsingErro rsHandler(this, c)); 60 return HelpText.AutoBuild(this, c => HelpText.DefaultParsingErro rsHandler(this, c));
42 } 61 }
43 62
44 #endregion 63 #endregion
45 64
46 [Option('v', "version", Required = true, 65 [Option('v', "version", Required = true, HelpText = VersionHelpText) ]
47 HelpText = VersionHelpText)]
48 public string Version { get; set; } 66 public string Version { get; set; }
49 67
50 [Option('d', "dir", Required = true, HelpText = OutputHelpText)] 68 [Option('d', "dir", Required = true, HelpText = OutputHelpText)]
51 public string OutputDirectory { get; set; } 69 public string OutputDirectory { get; set; }
52 70
53 [Option('s', "step", Required = true, HelpText = StepHelpText)] 71 [Option('s', "step", Required = true, HelpText = StepHelpText)]
54 public int Step { get; set; } 72 public int Step { get; set; }
55 73
56 [Option('b', "beta", DefaultValue = true, HelpText = IsBetaHelpText) ] 74 [Option('b', "beta", DefaultValue = true, HelpText = IsBetaHelpText) ]
57 public bool IsBeta { get; set; } 75 public bool IsBeta { get; set; }
58 76
59 [Option('k', "nuget_key", HelpText = NuGetApiKeyHelpText)] 77 [Option('k', "nuget_key", HelpText = NuGetApiKeyHelpText)]
60 public string NuGetApiKey { get; set; } 78 public string NuGetApiKey { get; set; }
61 } 79 }
62 80
63 static readonly TraceSource TraceSource = new TraceSource("Google.Apis") ; 81 private static readonly TraceSource TraceSource = new TraceSource("Googl e.Apis");
64 82
65 /// <summary> Command line arguments. </summary> 83 /// <summary>Command line arguments.</summary>
66 private readonly Options options; 84 private readonly Options options;
67 85
68 private int MajorVersion { get; set; } 86 private int MajorVersion { get; set; }
69 private int MinorVersion { get; set; } 87 private int MinorVersion { get; set; }
70 private int BuildVersion { get; set; } 88 private int BuildVersion { get; set; }
71 89
72 private string Tag 90 private string Tag
73 { 91 {
74 get { return options.Version + (options.IsBeta ? "-beta" : ""); } 92 get { return options.Version + (options.IsBeta ? "-beta" : ""); }
75 } 93 }
76 94
77 /// <summary>The "default" repository.</summary> 95 /// <summary>Gets or sets the "default" repository.</summary>
78 private Hg DefaultRepository { get; set; } 96 private Hg DefaultRepository { get; set; }
79 97
80 /// <summary>The "samples" repository.</summary> 98 /// <summary>Gets or sets the "samples" repository.</summary>
81 private Hg SamplesRepository { get; set; } 99 private Hg SamplesRepository { get; set; }
82 100
83 /// <summary>The "wiki" repository.</summary> 101 /// <summary>Gets or sets the "wiki" repository.</summary>
84 private Hg WikiRepository { get; set; } 102 private Hg WikiRepository { get; set; }
85 103
86 /// <summary>The "contrib" repository.</summary> 104 /// <summary>Gets or sets the "contrib" repository.</summary>
87 private Hg ContribRepository { get; set; } 105 private Hg ContribRepository { get; set; }
88 106
107 /// <summary>Gets all four repositories.</summary>
89 private IEnumerable<Hg> AllRepositories 108 private IEnumerable<Hg> AllRepositories
90 { 109 {
91 get { return new List<Hg> { DefaultRepository, SamplesRepository, Wi kiRepository, ContribRepository }; } 110 get { return new List<Hg> { DefaultRepository, SamplesRepository, Wi kiRepository, ContribRepository }; }
92 } 111 }
93 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
94 static void Main(string[] args) 119 static void Main(string[] args)
95 { 120 {
121 bool valid = true;
122
96 var options = new Options(); 123 var options = new Options();
97 if (!CommandLine.Parser.Default.ParseArguments(args, options)) 124 if (!CommandLine.Parser.Default.ParseArguments(args, options))
98 { 125 {
99 Console.ReadKey(); 126 Console.ReadKey();
100 return; 127 return;
101 } 128 }
102 129
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
103 var match = Regex.Match(options.Version, @"^(\d+)\.(\d+)\.(\d)+$"); 136 var match = Regex.Match(options.Version, @"^(\d+)\.(\d+)\.(\d)+$");
104 if (!match.Success) 137 if (!match.Success)
105 { 138 {
106 TraceSource.TraceEvent(TraceEventType.Error, 139 TraceSource.TraceEvent(TraceEventType.Error,
107 "Invalid version Number. Version should be in <Major>.<Minor >.<Build> form."); 140 "Invalid version Number. Version should be in <Major>.<Minor >.<Build> form.");
108 } 141 valid = false;
109 142 }
110 var p = new Program(options) 143
144 var program = new Program(options)
111 { 145 {
112 MajorVersion = int.Parse(match.Groups[1].Value), 146 MajorVersion = int.Parse(match.Groups[1].Value),
113 MinorVersion = int.Parse(match.Groups[2].Value), 147 MinorVersion = int.Parse(match.Groups[2].Value),
114 BuildVersion = int.Parse(match.Groups[3].Value), 148 BuildVersion = int.Parse(match.Groups[3].Value),
115 }; 149 };
116 150
117 try 151 if (valid)
118 { 152 {
119 p.Run(); 153 try
120 } 154 {
121 catch (Exception ex) 155 program.Run();
122 { 156 }
123 TraceSource.TraceEvent(TraceEventType.Error, "Exception occurred while running. Exception is: {0}", 157 catch (Exception ex)
124 ex.Message); 158 {
159 TraceSource.TraceEvent(TraceEventType.Error, "Exception occu rred while running. Exception is: {0}",
160 ex.Message);
161 }
125 } 162 }
126 163
127 Console.WriteLine("Press any key to continue..."); 164 Console.WriteLine("Press any key to continue...");
128 Console.ReadKey(); 165 Console.ReadKey();
129 } 166 }
130 167
168 /// <summary>The main release logic for creating a new release of Google .Apis.</summary>
131 private void Run() 169 private void Run()
132 { 170 {
133 const string CloneUrl = "https://code.google.com/p/google-api-dotnet -client{0}/"; 171 DefaultRepository = new Hg(new Uri(string.Format(CloneUrlFormat, "") ), "default");
134 172
135 DefaultRepository = Hg.Get("default", string.Format(CloneUrl, "")); 173 // Step 1 is only for creating Google.Apis and Google.Apis.Authentic ation packages
136
137 if (options.Step == 1) 174 if (options.Step == 1)
138 { 175 {
139 if (BuildVersion != 0) 176 DoStep1();
140 { 177 }
141 DefaultRepository.Update(string.Format("{0}.{1}", MajorVersi on, MinorVersion)); 178 // Step 2 should be done after the NuGet publisher generated all the APIs and the samples repository was·
142 } 179 // updated with the new packages
143
144 if (!HasIncomingChanges(new List<Hg> { DefaultRepository }))
145 {
146 //if (BuildDefaultRepository())
147 {
148 CreateNuGetPackages();
149 }
150 }
151 }
152
153 else if (options.Step == 2) 180 else if (options.Step == 2)
154 { 181 {
155 Console.WriteLine(); 182 DoStep2();
156 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
157 Console.WriteLine("========================="); 248 Console.WriteLine("=========================");
158 Console.WriteLine("Prerequisites for Step 2:"); 249 Console.WriteLine("Commit, Tag and Push");
159 Console.WriteLine("You ran Step 1."); 250 Console.WriteLine("=========================");
160 Console.WriteLine("You upgrade the libraries in the samples repo sitory and pushed that change."); 251 if (!CanContinue())
252 {
253 return;
254 }
255
256 // commit
257 CommitAndTag();
258
259 // push
260 foreach (Hg repository in AllRepositories)
261 {
262 repository.Push();
263 }
264
265 // create branch
266 PrintCreateBranch();
267
268 // publish core components to NuGet
269 if (!string.IsNullOrEmpty(options.NuGetApiKey))
270 {
271 PublishPackagesToNuGet();
272 Console.WriteLine("Now... you should run the NuGet publisher to publish a new PCL "
273 + "for each generated Google API. Run: " +
274 "Google.Apis.NuGet.Publisher --all_apis true -m publishe r -k [NUGET_KEY]");
275 }
276 else
277 {
278 TraceSource.TraceEvent(TraceEventType.Error, "NuGet API key is empty!");
279 }
280 }
281 }
282
283 /// <summary>Asks the user if he wants to continue in the process.</summ ary>
284 /// <returns><c>true</c> if the user to press 'y' or 'yes' to continue</ returns>
285 private bool CanContinue()
286 {
287 var yesOptions = new[] { "y", "yes" };
288 var noOptions = new[] { "n", "no" };
289
290 string input;
291 do
292 {
161 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");
162 Console.WriteLine("========================="); 294 input = Console.ReadLine().ToLower();
163 var input = Console.ReadLine(); 295 } while (!yesOptions.Contains(input) && !noOptions.Contains(input));
164 var yesOptions = new[] { "y", "yes" }; 296
165 var noOptions = new[] { "n", "no" }; 297 return yesOptions.Contains(input);
166 while (!yesOptions.Contains(input) && !noOptions.Contains(input) ) 298 }
167 { 299
168 Console.WriteLine("please press 'y' | 'yes' | 'n' | 'no' onl y"); 300 /// <summary>Publishes the core packages to NuGet main repository.</summ ary>
169 input = Console.ReadLine();
170 }
171
172 if (yesOptions.Contains(input))
173 {
174 SamplesRepository = Hg.Get("samples", string.Format(CloneUrl , ".samples"));
175 WikiRepository = Hg.Get("wiki", string.Format(CloneUrl, ".wi ki"));
176 ContribRepository = Hg.Get("contrib", string.Format(CloneUrl , ".contrib"));
177
178 if (!HasIncomingChanges(new List<Hg> {·
179 DefaultRepository, SamplesRepository, WikiRepository, Co ntribRepository }))
180 {
181 BuildSamples();
182 var notes = BuildContribNewRelease();
183 UpdateWiki(notes);
184
185 AddRemoveFiles();
186
187 Console.WriteLine("=========================");
188 Console.WriteLine("Commit, Tag and Push");
189 Console.WriteLine("Press 'y' | 'yes' to continue, or 'n' | 'no' to stop");
190 Console.WriteLine("=========================");
191 input = Console.ReadLine();
192 while (!yesOptions.Contains(input) && !noOptions.Contain s(input))
193 {
194 Console.WriteLine("please press 'y' | 'yes' | 'n' | 'no' only");
195 input = Console.ReadLine();
196 }
197
198 if (yesOptions.Contains(input))
199 {
200 // commit
201 CommitAndTag();
202
203 // push
204 foreach (Hg repository in AllRepositories)
205 {
206 repository.Push();
207 }
208
209 // create branch
210 PrintCreateBranch();
211
212 // publish core components to NuGet
213 if (!string.IsNullOrEmpty(options.NuGetApiKey))
214 {
215 PublishPackagesToNuGet();
216 }
217 else
218 {
219 TraceSource.TraceEvent(TraceEventType.Error, "Nu Get API key is empty!");
220 }
221
222 }
223 }
224 }
225 }
226 else
227 {
228 TraceSource.TraceEvent(TraceEventType.Error, "Invalid step optio n!");
229 }
230 }
231
232 private void PublishPackagesToNuGet() 301 private void PublishPackagesToNuGet()
233 { 302 {
234 var apiNupkgPath = Path.Combine(NuGetUtils.LocalNuGetPackageFolder, 303 var apiNupkgPath = Path.Combine(NuGetUtilities.LocalNuGetPackageFold er,
235 string.Format("Google.Apis.{0}.nupkg", Tag)); 304 string.Format("Google.Apis.{0}.nupkg", Tag));
236 NuGetUtils.PublishToNuget(apiNupkgPath, options.NuGetApiKey); 305 NuGetUtilities.PublishToNuget(apiNupkgPath, options.NuGetApiKey);
237 306
238 var authenticationNupkgPath = Path.Combine(NuGetUtils.LocalNuGetPack ageFolder, 307 var authenticationNupkgPath = Path.Combine(NuGetUtilities.LocalNuGet PackageFolder,
239 string.Format("Google.Apis.Authentication.{0}.nupkg", Tag)); 308 string.Format("Google.Apis.Authentication.{0}.nupkg", Tag));
240 NuGetUtils.PublishToNuget(authenticationNupkgPath, options.NuGetApiK ey); 309 NuGetUtilities.PublishToNuget(authenticationNupkgPath, options.NuGet ApiKey);
241 } 310 }
242 311
243 private void AddRemoveFiles() 312 /// <summary>
244 { 313 /// Displays the user orders how to create a branch (only in case it's a new major or minor release.
245 foreach (var repository in AllRepositories) 314 /// </summary>
246 {
247 repository.AddUnversionedFiles();
248 repository.RemoveDeletedFiles();
249 }
250 }
251
252 /// <summary>Displays the user orders how to create a branch.</summary>
253 private void PrintCreateBranch() 315 private void PrintCreateBranch()
254 { 316 {
255 if (BuildVersion != 0) 317 if (BuildVersion != 0)
256 { 318 {
257 // No need to branch in that case 319 // No need to branch in that case
258 return; 320 return;
259 } 321 }
260 322
261 // TODO(peleyal): automate this as well 323 // TODO(peleyal): consider automate this as well
262 Console.WriteLine("You should create a new branch for this release n ow:"); 324 Console.WriteLine("You should create a new branch for this release n ow:");
263 Console.WriteLine("cd " + DefaultRepository.WorkingDirectory); 325 Console.WriteLine("cd " + DefaultRepository.WorkingDirectory);
264 var branchVersion = string.Format("{0}.{1}", MajorVersion, MinorVers ion); 326 var branchVersion = string.Format("{0}.{1}", MajorVersion, MinorVers ion);
265 Console.WriteLine("hg branch " + branchVersion); 327 Console.WriteLine("hg branch " + branchVersion);
266 Console.WriteLine(string.Format("hg commit -m create {0} branch", br anchVersion)); 328 Console.WriteLine(string.Format("hg commit -m create {0} branch", br anchVersion));
267 Console.WriteLine("hg push --new-branch"); 329 Console.WriteLine("hg push --new-branch");
268 } 330 }
269 331
332 /// <summary>Commits all changes in all repositories and tags the "defau lt" repository.</summary>
270 private void CommitAndTag() 333 private void CommitAndTag()
271 { 334 {
272 foreach (var repository in AllRepositories) 335 foreach (var repository in AllRepositories)
273 { 336 {
274 repository.AddUnversionedFiles();
275 repository.RemoveDeletedFiles();
276
277 TraceSource.TraceEvent(TraceEventType.Information, "{0} - Commit ting", repository.Name); 337 TraceSource.TraceEvent(TraceEventType.Information, "{0} - Commit ting", repository.Name);
278 338
279 bool committed = repository.Commit("Release " + Tag); 339 bool committed = repository.Commit("Release " + Tag);
280 340
341 // TODO(peleyal): think to remove this if from this function. I don't like a if inside a loop statement
281 if (repository.Equals(DefaultRepository) && committed) 342 if (repository.Equals(DefaultRepository) && committed)
282 { 343 {
283 try 344 try
284 { 345 {
285 repository.Tag(Tag, false); 346 repository.Tag(Tag, false);
286 TraceSource.TraceEvent(TraceEventType.Information, "{0} - Was tagged \"{1}\"", 347 TraceSource.TraceEvent(TraceEventType.Information, "{0} - Was tagged \"{1}\"",
287 repository.Name, Tag); 348 repository.Name, Tag);
288 } 349 }
289 catch (Exception ex) 350 catch (Exception ex)
290 { 351 {
291 TraceSource.TraceEvent(TraceEventType.Error, "{0} - Tagg ing Failed. Exception is: {1}", 352 TraceSource.TraceEvent(TraceEventType.Error, "{0} - Tagg ing Failed. Exception is: {1}",
292 repository.Name, ex.Message); 353 repository.Name, ex.Message);
293 } 354 }
294 } 355 }
295 356
296 TraceSource.TraceEvent(TraceEventType.Information, "{0} - Commit ted", repository.Name); 357 TraceSource.TraceEvent(TraceEventType.Information, "{0} - Commit ted", repository.Name);
297 } 358 }
298 } 359 }
299 360
361 /// <summary>Updates the "Downloads" wiki page with the new release note s.</summary>
300 private void UpdateWiki(string notes) 362 private void UpdateWiki(string notes)
301 { 363 {
302 TraceSource.TraceEvent(TraceEventType.Information, "Updating wiki do wnloads page"); 364 TraceSource.TraceEvent(TraceEventType.Information, "Updating wiki do wnloads page");
303 365
304 // TODO(peleyal): improve. Currently we count on that old release of X.Y.Z is X.Y-1.0 366 // TODO(peleyal): improve. Currently we count on that old release of X.Y.Z is X.Y-1.0
305 var oldVersion = string.Format("{0}.{1}.{2}", MajorVersion, MinorVer sion - 1, 0); 367 var oldVersion = string.Format("{0}.{1}.{2}", MajorVersion, MinorVer sion - 1, 0);
306 DownloadsPageUpdater.UpdateWiki(WikiRepository.WorkingDirectory, not es, oldVersion, options.Version); 368 DownloadsPageUpdater.UpdateWiki(WikiRepository.WorkingDirectory, not es, oldVersion, options.Version);
307 369
308 TraceSource.TraceEvent(TraceEventType.Information, "wiki downloads p age was updated"); 370 TraceSource.TraceEvent(TraceEventType.Information, "wiki downloads p age was updated");
309 } 371 }
310 372
311 private string BuildContribNewRelease() 373 /// <summary>Creates a new release in the "contrib" repository.</summary >
374 /// <returns>The release notes of this version</returns>
375 private string CreateContribNewRelease()
312 { 376 {
313 TraceSource.TraceEvent(TraceEventType.Information, "Building Contrib release"); 377 TraceSource.TraceEvent(TraceEventType.Information, "Building Contrib release");
314 378
315 string releaseDir = ContribRepository.Combine(Tag); 379 string releaseDir = ContribRepository.Combine(Tag);
316 380
317 // Clear existing directories. 381 // Clear existing directories.
318 DirectoryUtils.ClearOrCreateDirectory(releaseDir); 382 DirectoryUtilities.ClearOrCreateDirectory(releaseDir);
319 string genDir = Path.Combine(releaseDir, "Generated"); 383 string genDir = Path.Combine(releaseDir, "Generated");
320 Directory.CreateDirectory(genDir); 384 Directory.CreateDirectory(genDir);
321 385
322 #region [RELEASE_VERSION]/Generated/Bin 386 #region [RELEASE_VERSION]/Generated/Bin
323 387
324 string binDir = Path.Combine(genDir, "Bin"); 388 string binDir = Path.Combine(genDir, "Bin");
325 TraceSource.TraceEvent(TraceEventType.Information, "Generating \"{0} \" directory", 389 TraceSource.TraceEvent(TraceEventType.Information, "Generating \"{0} \" directory",
326 DirectoryUtils.GetRelativePath(binDir, ContribRepository.Working Directory)); 390 DirectoryUtilities.GetRelativePath(binDir, ContribRepository.Wor kingDirectory));
391
327 Directory.CreateDirectory(binDir); 392 Directory.CreateDirectory(binDir);
328 393 foreach (var project in ReleaseProjects)
329 { 394 {
330 foreach (var project in ReleaseProjects) 395 var releasePath = Path.Combine(project.DirectoryPath, "Bin", "Re lease");
331 { 396 foreach (var filePath in Directory.GetFiles(releasePath, "Google .Apis.*"))
332 var releasePath = Path.Combine(project.DirectoryPath, "Bin", "Release"); 397 {
333 foreach (var filePath in Directory.GetFiles(releasePath, "Go ogle.Apis.*")) 398 File.Copy(filePath,
334 { 399 Path.Combine(binDir, filePath.Substring(filePath.LastInd exOf("\\") + 1)), true);
335 File.Copy(filePath, 400 }
336 Path.Combine(binDir, filePath.Substring(filePath.Las tIndexOf("\\") + 1)), true); 401 }
337 } 402
338 } 403 // TODO(peleyal): Put also the nuspec and nupkg
339
340 // Put also the nuspec and nupkg
341 }
342 404
343 #endregion 405 #endregion
344 406
345 #region [RELEASE_VERSION]/ZipFiles 407 #region [RELEASE_VERSION]/ZipFiles
346 408
347 string zipFilesDir = Path.Combine(genDir, "ZipFiles"); 409 string zipFilesDir = Path.Combine(genDir, "ZipFiles");
348 TraceSource.TraceEvent(TraceEventType.Information, "Generating \"{0} \" directory", 410 TraceSource.TraceEvent(TraceEventType.Information, "Generating \"{0} \" directory",
349 DirectoryUtils.GetRelativePath(zipFilesDir, ContribRepository.Wo rkingDirectory)); 411 DirectoryUtilities.GetRelativePath(zipFilesDir, ContribRepositor y.WorkingDirectory));
350 412
351 Directory.CreateDirectory(zipFilesDir); 413 Directory.CreateDirectory(zipFilesDir);
352 { 414 foreach (var project in ReleaseProjects)
353 foreach (var project in ReleaseProjects) 415 {
354 { 416 project.Build("Clean");
355 project.Build("Clean"); 417 }
356 } 418
357 419 TraceSource.TraceEvent(TraceEventType.Information, "Release projects were cleaned");
358 TraceSource.TraceEvent(TraceEventType.Information, "Release proj ects were cleaned"); 420
359 421 // source.zip
360 // source.zip 422 var fileNameFormat = "google-api-dotnet-client-{0}.{1}.zip";
361 var fileNameFormat = "google-api-dotnet-client-{0}.{1}.zip"; 423 var sourceZipName = string.Format(fileNameFormat, Tag, "source");
362 var sourceZipName = string.Format(fileNameFormat, Tag, "source") ; 424 using (var zip = new ZipFile(Path.Combine(zipFilesDir, sourceZipName )))
363 using (var zip = new ZipFile(Path.Combine(zipFilesDir, sourceZip Name))) 425 {
364 { 426 zip.AddDirectory(Path.Combine(DefaultRepository.WorkingDirectory , "Src"), "Src");
365 zip.AddDirectory(Path.Combine(DefaultRepository.WorkingDirec tory, "Src"), "Src"); 427 zip.AddFile(Path.Combine(DefaultRepository.WorkingDirectory, "Go ogleApisClient.sln"), "");
366 zip.AddFile(Path.Combine(DefaultRepository.WorkingDirectory, "GoogleApisClient.sln"), ""); 428 zip.AddFile(Path.Combine(DefaultRepository.WorkingDirectory, "LI CENSE"), "");
367 zip.AddFile(Path.Combine(DefaultRepository.WorkingDirectory, "LICENSE"), ""); 429 zip.Save();
368 zip.Save(); 430 }
369 } 431 TraceSource.TraceEvent(TraceEventType.Information, "{0} was created" , sourceZipName);
370 TraceSource.TraceEvent(TraceEventType.Information, "{0} was crea ted", sourceZipName); 432
371 433 // binary.zip
372 // binary.zip 434 var binaryZipName = string.Format(fileNameFormat, Tag, "binary");
373 var binaryZipName = string.Format(fileNameFormat, Tag, "binary") ; 435 using (var zip = new ZipFile(Path.Combine(zipFilesDir, binaryZipName )))
374 using (var zip = new ZipFile(Path.Combine(zipFilesDir, binaryZip Name))) 436 {
375 { 437 Directory.GetFiles(binDir).ToList().ForEach(f => zip.AddFile(Pat h.Combine(binDir, f), ""));
376 Directory.GetFiles(binDir).ToList().ForEach(f => zip.AddFile (Path.Combine(binDir, f), "")); 438 zip.Save();
377 zip.Save(); 439 }
378 } 440 TraceSource.TraceEvent(TraceEventType.Information, "{0} was created" , binaryZipName);
379 TraceSource.TraceEvent(TraceEventType.Information, "{0} was crea ted", binaryZipName); 441
380 442
381 443 // samples.zip
382 // samples.zip 444 var samplesZipName = string.Format(fileNameFormat, Tag, "samples");
383 var samplesZipName = string.Format(fileNameFormat, Tag, "samples "); 445 using (var zip = new ZipFile(Path.Combine(zipFilesDir, samplesZipNam e)))
384 using (var zip = new ZipFile(Path.Combine(zipFilesDir, samplesZi pName))) 446 {
385 { 447 foreach (var d in Directory.GetDirectories(SamplesRepository.Wor kingDirectory))
386 foreach (var d in Directory.GetDirectories(SamplesRepository .WorkingDirectory)) 448 {
449 if (!d.EndsWith(".hg"))
387 { 450 {
388 if (!d.EndsWith(".hg")) 451 var directoryName = d.Substring(d.LastIndexOf("\\") + 1) ;
389 { 452 zip.AddDirectory(Path.Combine(SamplesRepository.WorkingD irectory, d), directoryName);
390 var directoryName = d.Substring(d.LastIndexOf("\\") + 1);
391 zip.AddDirectory(Path.Combine(SamplesRepository.Work ingDirectory, d), directoryName);
392 }
393 } 453 }
394 foreach (var f in Directory.GetFiles(SamplesRepository.Worki ngDirectory, "*.sln")) 454 }
395 { 455 foreach (var f in Directory.GetFiles(SamplesRepository.WorkingDi rectory, "*.sln"))
396 zip.AddFile(Path.Combine(SamplesRepository.WorkingDirect ory, f), ""); 456 {
397 } 457 zip.AddFile(Path.Combine(SamplesRepository.WorkingDirectory, f), "");
398 zip.Save(); 458 }
399 } 459 zip.Save();
400 460 }
401 TraceSource.TraceEvent(TraceEventType.Information, "{0} was crea ted", samplesZipName); 461
402 } 462 TraceSource.TraceEvent(TraceEventType.Information, "{0} was created" , samplesZipName);
403 463
404 #endregion 464 #endregion
405 465
406 #region [RELEASE_VERSION]/ReleaseNotes.txt 466 #region [RELEASE_VERSION]/ReleaseNotes.txt
407 467
408 var notes = CreateChangelog(); 468 var notes = GetChangelog();
409 TraceSource.TraceEvent(TraceEventType.Information, "Creating Release Notes file"); 469 TraceSource.TraceEvent(TraceEventType.Information, "Creating Release Notes file");
410 var noteFilePath = Path.Combine(genDir, "ReleaseNotes.txt"); 470 var noteFilePath = Path.Combine(genDir, "ReleaseNotes.txt");
411 File.WriteAllText(noteFilePath, notes); 471 File.WriteAllText(noteFilePath, notes);
412 472
413 #endregion 473 #endregion
414 474
415 // open the created change-log and read again the notes (in case the user had modified the file) 475 // open the created change-log and read again the notes (in case the user had modified the file)
416 Process.Start(noteFilePath).WaitForExit(); 476 Process.Start(noteFilePath).WaitForExit();
417 notes = File.ReadAllText(noteFilePath); 477 notes = File.ReadAllText(noteFilePath);
418 478
419 return notes; 479 return notes;
420 } 480 }
421 481
422 private string CreateChangelog() 482 /// <summary>
483 /// Returns the notes list of this release. It contains the change log o f all pushes to the "default"·
484 /// repository.
485 /// </summary>
486 private string GetChangelog()
423 { 487 {
424 StringBuilder log = new StringBuilder(); 488 StringBuilder log = new StringBuilder();
425 log.AppendLine("Google .NET Client Library"); 489 log.AppendLine("Google .NET Client Library");
426 log.AppendLine(string.Format("Stable Release '{0}'", Tag)); 490 log.AppendLine(string.Format("Stable Release '{0}'", Tag));
427 log.AppendLine(DateTime.UtcNow.ToLongDateString()); 491 log.AppendLine(DateTime.UtcNow.ToLongDateString());
428 log.AppendLine("==========================================="); 492 log.AppendLine("===========================================");
429 493
430 log.AppendLine().AppendLine("Changes:"); 494 log.AppendLine().AppendLine("Changes:");
431 foreach (string line in DefaultRepository.CreateChangelist()) 495 foreach (string line in DefaultRepository.CreateChangelist())
432 { 496 {
433 log.AppendLine(" " + line); 497 log.AppendLine(" " + line);
434 } 498 }
435 499
436 return log.ToString(); 500 return log.ToString();
437 } 501 }
438 502
503 /// <summary>Builds all projects in the "samples" repository.</summary>
439 private void BuildSamples() 504 private void BuildSamples()
440 { 505 {
441 // Build all the samples projects. 506 // build all the samples projects.
442 TraceSource.TraceEvent(TraceEventType.Information, "Building the sam ples"); 507 TraceSource.TraceEvent(TraceEventType.Information, "Building the sam ples");
443 foreach (string csproj in Directory.GetFiles(SamplesRepository.Worki ngDirectory, "*.csproj", 508 foreach (string csproj in Directory.GetFiles(SamplesRepository.Worki ngDirectory, "*.csproj",
444 SearchOption.AllDirectories)) 509 SearchOption.AllDirectories))
445 { 510 {
446 Project project = new Project(csproj); 511 Project project = new Project(csproj);
447 project.SetProperty("Configuration", "Release"); 512 project.SetProperty("Configuration", "Release");
448 TraceSource.TraceEvent(TraceEventType.Information, "Building {0} ", project.GetName()); 513 TraceSource.TraceEvent(TraceEventType.Information, "Building {0} ", project.GetName());
449 bool success = project.Build("Build", new[] { new ConsoleLogger( LoggerVerbosity.Quiet) }); 514 bool success = project.Build("Build", new[] { new ConsoleLogger( LoggerVerbosity.Quiet) });
450 if (!success) 515 if (!success)
451 { 516 {
452 TraceSource.TraceEvent(TraceEventType.Error, "Building {0} F AILED", project.GetName()); 517 TraceSource.TraceEvent(TraceEventType.Error, "Building {0} F AILED", project.GetName());
453 } 518 }
454 project.Build("Clean"); 519 project.Build("Clean");
455 TraceSource.TraceEvent(TraceEventType.Information, "Building {0} succeeded", project.GetName()); 520 TraceSource.TraceEvent(TraceEventType.Information, "Building {0} succeeded", project.GetName());
456 } 521 }
457 } 522 }
458 523
524 /// <summary>Returns <c>true</c> if one of the repositories has incoming changes.</summary>
459 private bool HasIncomingChanges(IEnumerable<Hg> repositories) 525 private bool HasIncomingChanges(IEnumerable<Hg> repositories)
460 { 526 {
461 foreach (var repository in repositories) 527 foreach (var repository in repositories)
462 { 528 {
463 if (repository.HasIncomingChanges) 529 if (repository.HasIncomingChanges)
464 { 530 {
465 TraceSource.TraceEvent(TraceEventType.Error, 531 TraceSource.TraceEvent(TraceEventType.Error,
466 "[{0}] has incoming changes. Run hg pull & update first! ", repository.Name); 532 "[{0}] has incoming changes. Run hg pull & update first! ", repository.Name);
467 return true; 533 return true;
468 } 534 }
469 } 535 }
470 return false; 536 return false;
471 } 537 }
472 538
473 539 /// <summary>Creates the Google.Apis and Google.Apis.Authentication NuGe t packages.</summary>
474 private void CreateNuGetPackages() 540 private void CreateCoreNuGetPackages()
475 { 541 {
476 // create a resource dir in the working folder 542 // create a resource dir in the working folder
477 var destDirectory = Path.Combine(Environment.CurrentDirectory, "Reso urces"); 543 var destDirectory = Path.Combine(Environment.CurrentDirectory, "Reso urces");
478 if (Directory.Exists(destDirectory)) 544 if (Directory.Exists(destDirectory))
479 { 545 {
480 Directory.Delete(destDirectory, true); 546 Directory.Delete(destDirectory, true);
481 } 547 }
482 548
483 FileInfo info = new FileInfo(Assembly.GetEntryAssembly().Location); 549 FileInfo info = new FileInfo(Assembly.GetEntryAssembly().Location);
484 DirectoryUtils.CopyDirectory(Path.Combine(info.Directory.FullName, " Resources"), destDirectory); 550 DirectoryUtilities.CopyDirectory(Path.Combine(info.Directory.FullNam e, "Resources"), destDirectory);
485 551
486 var newVersion = options.Version + "-beta"; 552 var newVersion = options.Version + "-beta";
487 553
554 // get the Google.Apis and Google.Apis.Authentication nuspec files a nd replace the version in it
488 var apiNuspec = Path.Combine(destDirectory, "Google.Apis.VERSION.nus pec"); 555 var apiNuspec = Path.Combine(destDirectory, "Google.Apis.VERSION.nus pec");
489 var newApiNuspec = apiNuspec.Replace("VERSION", newVersion); 556 var newApiNuspec = apiNuspec.Replace("VERSION", newVersion);
490 var authenticationNuspec = Path.Combine(destDirectory, "Google.Apis. Authentication.VERSION.nuspec"); 557 var authenticationNuspec = Path.Combine(destDirectory, "Google.Apis. Authentication.VERSION.nuspec");
491 var newAuthenticationNuspec = authenticationNuspec.Replace("VERSION" , newVersion); 558 var newAuthenticationNuspec = authenticationNuspec.Replace("VERSION" , newVersion);
492 559
493 File.Move(apiNuspec, newApiNuspec); 560 File.Move(apiNuspec, newApiNuspec);
494 File.Move(authenticationNuspec, newAuthenticationNuspec); 561 File.Move(authenticationNuspec, newAuthenticationNuspec);
495 562
496 var allLines = File.ReadAllText(newApiNuspec).Replace("VERSION", new Version); 563 var allLines = File.ReadAllText(newApiNuspec).Replace("VERSION", new Version);
497 File.WriteAllText(newApiNuspec, allLines); 564 File.WriteAllText(newApiNuspec, allLines);
498 565
499 allLines = File.ReadAllText(newAuthenticationNuspec).Replace("VERSIO N", newVersion); 566 allLines = File.ReadAllText(newAuthenticationNuspec).Replace("VERSIO N", newVersion);
500 File.WriteAllText(newAuthenticationNuspec, allLines); 567 File.WriteAllText(newAuthenticationNuspec, allLines);
501 568
502 NuGetUtils.CreateLocalNupkgFile(newApiNuspec, Environment.CurrentDir ectory); 569 NuGetUtilities.CreateLocalNupkgFile(newApiNuspec, Environment.Curren tDirectory);
503 NuGetUtils.CreateLocalNupkgFile(newAuthenticationNuspec, Environment .CurrentDirectory); 570 NuGetUtilities.CreateLocalNupkgFile(newAuthenticationNuspec, Environ ment.CurrentDirectory);
504 } 571 }
505 572
506 private IEnumerable<Project> releaseProjects; 573 private IEnumerable<Project> releaseProjects;
574 /// <summary>Gets the release projects of from the "default" repository. </summary>
507 private IEnumerable<Project> ReleaseProjects 575 private IEnumerable<Project> ReleaseProjects
508 { 576 {
509 get 577 get
510 { 578 {
511 if (releaseProjects != null) 579 if (releaseProjects != null)
512 { 580 {
513 return releaseProjects; 581 return releaseProjects;
514 } 582 }
515 583
516 var releasePaths = new[]· 584 var releasePaths = new[]·
517 { 585 {
518 DefaultRepository.Combine("Src", "GoogleApis", "GoogleApis.c sproj"), 586 DefaultRepository.Combine("Src", "GoogleApis", "GoogleApis.c sproj"),
519 DefaultRepository.Combine("Src", "GoogleApis.DotNet4", "Goog leApis.DotNet4.csproj"), 587 DefaultRepository.Combine("Src", "GoogleApis.DotNet4", "Goog leApis.DotNet4.csproj"),
520 DefaultRepository.Combine("Src", "GoogleApis.Authentication. OAuth2",· 588 DefaultRepository.Combine("Src", "GoogleApis.Authentication. OAuth2",·
521 "GoogleApis.Authentication.OAuth2.csproj") 589 "GoogleApis.Authentication.OAuth2.csproj")
522 }; 590 };
523 releaseProjects = (from path in releasePaths 591 return releaseProjects = (from path in releasePaths
524 select new Project(path)).ToList(); 592 select new Project(path)).ToList();
525 return releaseProjects; 593 }
526 } 594 }
527 } 595
528 596 /// <summary>Builds the "default" repository projects.</summary>
597 /// <returns><c>true</c> if the default repository was build successfull y</returns>
529 private bool BuildDefaultRepository() 598 private bool BuildDefaultRepository()
530 { 599 {
531 TraceSource.TraceEvent(TraceEventType.Information, "Building project s...."); 600 TraceSource.TraceEvent(TraceEventType.Information, "Building project s....");
532 601
533 var allProjects = new List<Project>(); 602 var allProjects = new List<Project>();
534 allProjects.AddRange(ReleaseProjects); 603 allProjects.AddRange(ReleaseProjects);
535 allProjects.Add(new Project(DefaultRepository.Combine("Src", "Google Apis.Tests", 604 allProjects.Add(new Project(DefaultRepository.Combine("Src", "Google Apis.Tests",
536 "GoogleApis.Tests.csproj"))); 605 "GoogleApis.Tests.csproj")));
537 allProjects.Add(new Project(DefaultRepository.Combine("Src", "Google Apis.Authentication.OAuth2.Tests", 606 allProjects.Add(new Project(DefaultRepository.Combine("Src", "Google Apis.Authentication.OAuth2.Tests",
538 "GoogleApis.Authentication.OAuth2.Tests.csproj"))); 607 "GoogleApis.Authentication.OAuth2.Tests.csproj")));
(...skipping 19 matching lines...) Expand all
558 627
559 if (!ReleaseProjects.Contains(project)) 628 if (!ReleaseProjects.Contains(project))
560 { 629 {
561 // TODO(peleyal): run unit tests for all test projects 630 // TODO(peleyal): run unit tests for all test projects
562 } 631 }
563 } 632 }
564 633
565 return true; 634 return true;
566 } 635 }
567 636
637 /// <summary>Constructs a new program with the given options.</summary>
568 public Program(Options options) 638 public Program(Options options)
569 { 639 {
570 this.options = options; 640 this.options = options;
571 641
572 string path = Path.GetFullPath(options.OutputDirectory); 642 string path = Path.GetFullPath(options.OutputDirectory);
573 if (!Directory.Exists(path)) 643 if (!Directory.Exists(path))
574 { 644 {
575 Directory.CreateDirectory(path); 645 Directory.CreateDirectory(path);
576 } 646 }
577 647
578 Environment.CurrentDirectory = path; 648 Environment.CurrentDirectory = path;
579 } 649 }
580 } 650 }
581 } 651 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b