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

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

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