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

Delta Between Two Patch Sets: Tools/Google.Apis.NuGet.Publisher/Google.Apis.NuGet.Publisher/NuGetApiPublisher.cs

Issue 12662047: Issue 376: Generate NuGet pacakges for generated APIs (Closed) Base URL: https://google-api-dotnet-client.googlecode.com/hg/
Left Patch Set: minor || Created 10 years, 7 months ago
Right Patch Set: David final comments Created 10 years, 7 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:
Right: Side by side diff | Download
LEFTRIGHT
(no file at all)
1 /*
2 Copyright 2013 Google Inc
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17 using System;
18 using System.Diagnostics;
19 using System.IO;
20 using System.Linq;
21 using System.Net;
22 using System.Text.RegularExpressions;
23 using System.Threading.Tasks;
24
25 using Microsoft.Build.Evaluation;
26 using Microsoft.Build.Framework;
27 using Microsoft.Build.Logging;
28 using NuGet;
29
30 using Google.Apis.NuGet.Publisher.Discovery;
31 using Google.Apis.Utils;
32
33 namespace Google.Apis.NuGet.Publisher
34 {
35 /// <summary>This publisher publishes Google API packages to NuGet main repo sitory.</summary>
36 public class NuGetApiPublisher
37 {
38 private static TraceSource TraceSource = new TraceSource("Google.Apis");
39
40 private readonly DiscoveryItem item;
41
42 /// <summary>Gets or sets the working directory which the source will be downloaded to.</summary>
43 public string BundleDirectory { get; set; }
44
45 /// <summary>Gets or sets the bundle URI. The API's bundle is going to b e downloaded from this URI.</summary>
46 public Uri BundleUri { get; set; }
47
48 /// <summary>Gets or sets the NuGet API key.</summary>
49 public string NuGetApiKey { get; set; }
50
51 /// <summary>Gets or sets the template directory which contains the '.nu get' directory and the necessary··
52 /// 'Microsoft.Bcl.Build.targets' file.</summary>
53 public string TemplateDirectory { get; set; }
54
55 /// <summary>The regex to extract the id version of the nuspec in the so urce folder.</summary>
56 private static readonly Regex IdPattern = new Regex(@"<id>(.*)</id>");
57
58 /// <summary>The regex to extract the version of the nuspec in the sourc e folder.</summary>
59 private static readonly Regex VersionPattern = new Regex(@"<version>(.*) </version>");
60
61 /// <summary>Constructs a new logic item.</summary>
62 public NuGetApiPublisher(DiscoveryItem item)
63 {
64 this.item = item;
65 }
66
67 /// <summary>This is the main logic, which does the following:
68 /// <list type="number">
69 /// <item><description>
70 /// Download the API's bundle from "https://google-api-client-libraries. appspot.com/"
71 /// </description></item>
72 /// <item><description>Extract the API's sources</description></item>
73 /// <item><description>Build the sources</description></item>
74 /// <item><description>Create a NuGet package</description></item>
75 /// <item><description>Publish the package to NuGet main repository</des cription></item>
76 /// </list>
77 /// </summary>
78 /// <remarks>Leave the <see cref="NuGetApiKey"/> empty to avoid publishi ng to NuGet main repository</remarks>
79 /// <returns>In case there is already a NuGet package with the same name and version, we won't build, create
80 /// a new package or publish to the main repository</returns>
81 public async Task Run()
82 {
83 TraceSource.TraceEvent(TraceEventType.Verbose, "{0}\t start working. ..", item);
84
85 string zipFile = await DownloadBundle();
86 string sourceFolder = ExtractSources(zipFile);
87 if (!string.IsNullOrEmpty(sourceFolder))
88 {
89 var buildDirectory = await Build(sourceFolder);
90 if (!string.IsNullOrEmpty(buildDirectory))
91 {
92 var packagePath = CreateLocalNupkgFile(buildDirectory);
93 if (!string.IsNullOrEmpty(NuGetApiKey))
94 {
95 NuGetUtilities.PublishToNuget(packagePath, NuGetApiKey);
96 }
97 }
98 Directory.Delete(buildDirectory, true);
99 }
100 }
101
102 /// <summary>Tests the main logic and does the following:
103 /// <list type="number">
104 /// <item><description>Build the source files which specified in the inp ut directory</description></item>
105 /// <item><description>Create a local NuGet package</description></item>
106 /// </list>
107 /// </summary>
108 public async Task Test(string directory)
109 {
110 TraceSource.TraceEvent(TraceEventType.Verbose, "{0}\t start working on ...", item);
111
112 var sourceFolder = directory + item;
113 if (!string.IsNullOrEmpty(sourceFolder))
114 {
115 var buildDirectory = await Build(sourceFolder);
116 CreateLocalNupkgFile(buildDirectory);
117 Directory.Delete(buildDirectory, true);
118 }
119 }
120
121 #region Download Sources
122
123 /// <summary>Downloads the API's bundle.</summary>
124 /// <returns>The path to the bundle file</returns>
125 private async Task<string> DownloadBundle()
126 {
127 var outputFile = string.Format(Path.Combine(BundleDirectory, item + ".zip"));
128
129 // Downloading the bundle
130 using (var client = new WebClient())
131 {
132 TraceSource.TraceEvent(TraceEventType.Verbose, "{0}\t Downloadin g \"{1}\"", item, BundleUri);
133 await client.DownloadFileTaskAsync(BundleUri, outputFile);
134 TraceSource.TraceEvent(TraceEventType.Information, "{0}\t \"{1}\ " was downloaded successfully", item,
135 BundleUri);
136
137 return outputFile;
138 }
139 }
140
141 /// <summary>
142 /// Extracts the sources. This method first extracts the bundle and then checks by the source zip if a NuGet·
143 /// package already exists for the specific API version.·
144 /// If not, the method extracts also the source zip to the returned fold er path.
145 /// </summary>
146 /// <param name="zipFile">The bundle zip file which contains the sources </param>
147 /// <returns>The path to the source folder. <c>null</c> if a NuGet packa ge already exists for this bundle·
148 /// version</returns>
149 private string ExtractSources(string zipFile)
150 {
151 TraceSource.TraceEvent(TraceEventType.Verbose, "{0}\t Extracting sou rces", item);
152
153 System.IO.Compression.ZipFile.ExtractToDirectory(zipFile, BundleDire ctory);
154 var apiFolder = Path.Combine(BundleDirectory, item.Name);
155
156 // gets the zip file which contains a "src.zip" suffix
157 var sourceZip = Directory.GetFiles(apiFolder).FirstOrDefault(f => f. EndsWith("src.zip"));
158 var sourceFolder = Path.Combine(BundleDirectory, "Source");
159 System.IO.Compression.ZipFile.ExtractToDirectory(sourceZip, sourceFo lder);
160
161 // gets the nuget id and version of the package
162 var nuspecFile = Directory.GetFiles(sourceFolder, "*.nuspec").Single ();
163 var content = File.ReadAllText(nuspecFile);
164 var id = IdPattern.Match(content).Groups[1].Value;
165 var version = VersionPattern.Match(content).Groups[1].Value;
166
167 // If a NuGet package already exists for this id and version - we do n't need to continue with the process
168 bool exists = NuGetUtilities.DoesNugetPackageExist(id, version);
169 if (exists)
170 {
171 TraceSource.TraceEvent(TraceEventType.Information, "{0}\t A NuGe t package already exists for {1}",
172 item, version);
173 return null;
174 }
175
176 TraceSource.TraceEvent(TraceEventType.Verbose, "{0}\t Extracting sou rces in \"{1}\"", item,
177 sourceFolder);
178
179 return sourceFolder;
180 }
181
182 #endregion
183
184 #region Build
185
186 /// <summary>
187 /// Builds the source folder. First it copies all the sources into the t emplate folder and then build the·
188 /// project file.
189 /// </summary>
190 /// <returns>The build directory</returns>
191 private Task<string> Build(string sourceFolder)
192 {
193 var buildDirectory = Path.Combine(TemplateDirectory, "Build");
194 if (Directory.Exists(buildDirectory))
195 {
196 Directory.Delete(buildDirectory, true);
197 }
198 DirectoryUtilities.CopyDirectory(sourceFolder, buildDirectory);
199
200 var projectFile = Directory.GetFiles(buildDirectory, "*.csproj").Sin gle();
201 TraceSource.TraceEvent(TraceEventType.Verbose, "{0}\t Building \"{1} \"", item, projectFile);
202
203 // create a MS project instance and configure it to build 'Release'
204 Project project = new Project(projectFile);
205 project.SetProperty("Configuration", "Release");
206
207 bool success = project.Build("Build", new[] { new ConsoleLogger(Logg erVerbosity.Quiet) });
208 if (success)
209 {
210 TraceSource.TraceEvent(TraceEventType.Information, "{0}\t \"{1}\ " was built successfully!", item,
211 projectFile);
212 }
213 else
214 {
215 TraceSource.TraceEvent(TraceEventType.Error, "{0}\t \"{1}\" ERRO R IN BUILDING THE PROJECT!", item,
216 projectFile);
217 buildDirectory = null;
218 }
219
220 TaskCompletionSource<string> tcs = new TaskCompletionSource<string>( );
221 tcs.SetResult(buildDirectory);
222 return tcs.Task;
223 }
224
225 #endregion
226
227 #region NuGet
228
229 /// <summary>Creates a local nupkg file.</summary>
230 /// <param name="buildDirectoryPath">Path to build directory which conta ins the dll, pdb , etc</param>
231 /// <returns>The path to the nupkg file</returns>
232 private string CreateLocalNupkgFile(string buildDirectoryPath)
233 {
234 TraceSource.TraceEvent(TraceEventType.Verbose, "{0}\t Start creating .nupkg file", item);
235 var nuspec = Directory.GetFiles(buildDirectoryPath, "*.nuspec").Sing le();
236 return NuGetUtilities.CreateLocalNupkgFile(nuspec, buildDirectoryPat h);
237 }
238
239 #endregion
240 }
241 }
LEFTRIGHT

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