Index: Tools/BuildRelease/BuildRelease.csproj =================================================================== deleted file mode 100644 --- a/Tools/BuildRelease/BuildRelease.csproj +++ /dev/null @@ -1,73 +0,0 @@ - - - - Debug - x86 - 8.0.30703 - 2.0 - {0273723C-9B94-4A13-9635-4519633D9E0E} - Exe - Properties - BuildRelease - BuildRelease - v4.0 - 512 - - - - x86 - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - x86 - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - ..\Lib\Google.Apis.Samples.Helper.dll - - - - - - - - - - - - - - - - {585E1BD4-C989-4041-9AA2-14EEB13D8F15} - Google.Build.Tester - - - {A6E792C8-D5E7-40DD-9483-3901E70BF93F} - Google.Build.Utils - - - - - - - - \ No newline at end of file Index: Tools/BuildRelease/Program.cs =================================================================== deleted file mode 100644 --- a/Tools/BuildRelease/Program.cs +++ /dev/null @@ -1,663 +0,0 @@ -/* -Copyright 2011 Google Inc - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Text.RegularExpressions; - -using BuildRelease.Wiki; -using Google.Apis.Samples.Helper; -using Google.Build.Utils; -using Google.Build.Utils.Build; -using Google.Build.Utils.Repositories; - -namespace BuildRelease -{ - /// - /// Release Builder. - /// Will automatically check out all repositories, run unit tests and create a release. - /// Can be re-run if the build should fail - Run this tool again, with the same dir argument after fixing the - /// problem. - /// - public class Program - { - #region Command Line Arguments - public class CommandLineArguments - { - [Argument("version", ShortName = "v", - Description = "[Required] The version number of this release - only.")] - public string Version { get; set; } - - [Argument("local", ShortName = "l", - Description = "Uses the local repository instead of checking out a new one. Not releasable.")] - public bool UseLocalRepository { get; set; } - - [Argument("tag", ShortName = "t", - Description = "Use this as the tag suffix for this build.")] - public string Tag { get; set; } - - [Argument("dir", ShortName = "d", - Description = "Use this as the output directory for this build (relative to current directory). " + - "If not specified, dir will be set to current date.")] - public string OutputDirectory { get; set; } - - public override string ToString() - { - return string.Format("CommandLineArguments " + - "[UseLocalRepository: {0}; Tag: {1}; Dir: {2}; Version: {3}]", - UseLocalRepository, Tag, OutputDirectory, Version); - } - } - - /// Command line arguments. - public static CommandLineArguments Arguments { get; private set; } - - #endregion - - /// The "default" repository. - public static Hg Default { get; private set; } - - /// The "samples" repository. - public static Hg Samples { get; private set; } - - /// The "wiki" repository. - public static Hg Wiki { get; private set; } - - /// The "contrib" repository. - public static Hg Contrib { get; private set; } - - /// An array of all relevant mercurial repositories. - public static Hg[] AllRepositories { get; private set; } - - /// The name of the directory containing the working copy. - public static string WorkingCopy { get; private set; } - - private static int MajorVersion { get; set; } - private static int MinorVersion { get; set; } - private static int BuildVersion { get; set; } - - private static IEnumerable _excludeThirdParties = new[] - { - "Moq.dll", "Moq.LICENSE", "nunit.framework.dll", "nunit.framework.LICENSE" - }; - - /// Points to third party dependencies which will appear in the bundle. - public static IEnumerable ThirdPartyFiles - { - get - { - string dir = Default.Combine("ThirdParty"); - return from file in Directory.GetFiles(dir, "*") - where !_excludeThirdParties.Contains(Path.GetFileName(file)) - select file; - } - } - - /// - /// The directory containing all the generated services. - /// - public static string ServiceDir - { - get { return Samples.Combine("Services"); } - } - - [STAThread] - static void Main(string[] args) - { - // Try to enlarge the window. - try - { - Console.SetWindowSize(Console.LargestWindowWidth * 8 / 9, Console.LargestWindowHeight * 8 / 9); - } - catch (Exception) { } - - CommandLine.DisplayGoogleSampleHeader("Build Release"); - CommandLine.EnableExceptionHandling(); - - // Init arguments - if (!InitArguments(args)) - { - CommandLine.PressAnyKeyToExit(); - return; - } - - // Clone repositories - CheckoutRepositories(); - - // Clean up the default/ repository by removing cache-files - CleanDefaultRepository(); - - // Check for incoming changes - foreach (Hg repository in AllRepositories) - { - if (repository.HasIncomingChanges) - { - CommandLine.WriteError( - "Repository [{0}] has incoming changes. Run hg pull & update first!", repository.Name); - CommandLine.PressAnyKeyToExit(); - return; - } - } - - // Build projects - FileVersionInfo apiVersion; - Project[] allProjects; - Project[] baseLibraries = BuildProjects(out apiVersion, out allProjects); - - // Create tag - string tag = GetTagName(apiVersion); - - // Update samples - UpdateSamples(baseLibraries); - - // Update contrib - string notes = CreateChangelog(tag); - string zipDir; - notes = BuildContribRelease(tag, notes, baseLibraries, allProjects, out zipDir); - - // Update wiki - UpdateWiki(notes, zipDir); - - CommandLine.WriteLine("{{white}} ======================================="); - CommandLine.WriteResult("Version: ", apiVersion.ProductVersion); - CommandLine.WriteLine(); - - if (Arguments.UseLocalRepository) - { - CommandLine.WriteAction("Local build done."); - CommandLine.PressAnyKeyToExit(); - return; - } - - // Ask the user whether he wants to continue the release. - string res = "no"; - CommandLine.WriteLine(" {{gray}}In the next step all changes will be committed, tagged and pushed."); - CommandLine.WriteLine(" {{gray}}Only continue when you are sure that you don't have to make " + - "any new changes."); - CommandLine.RequestUserInput("Do you want to continue with the release? Type YES.", ref res); - CommandLine.WriteLine(); - - if (res != "YES") - { - Console.WriteLine("Done - NO CODE was committed, tagged or pushed"); - CommandLine.PressAnyKeyToExit(); - return; - } - - // Commit - CommitAndTagRelease(tag); - - // Push - PushChanges(); - - // Create branch - PrintCreateBranch(); - - CommandLine.PressAnyKeyToExit(); - } - - /// Prints the user orders how to create a branch. - private static void PrintCreateBranch() - { - if (BuildVersion != 0) - { - // No need to branch in that case - return; - } - - // TODO(peleyal): automate this as well - CommandLine.WriteAction("You should create a new branch for this release now:"); - CommandLine.WriteAction("cd " + Default.WorkingDirectory); - var branchVersion = string.Format("{0}.{1}", MajorVersion, MinorVersion); - CommandLine.WriteAction("hg branch " + branchVersion); - CommandLine.WriteAction(string.Format("hg commit -m create {0} branch", branchVersion)); - CommandLine.WriteAction("hg push --new-branch"); - } - - /// - /// Inits the Arguments for this release. - /// Returns true if all arguments are valid. - /// - private static bool InitArguments(string[] args) - { - // TODO(peleyal): Add default value option on Argument (and then add those values to the definition above) - Arguments = new CommandLineArguments() - { - Tag = "beta", - UseLocalRepository = false - }; - - // Parse command line arguments. - CommandLineFlags.ParseArguments(Arguments, args); - if (string.IsNullOrEmpty(Arguments.Version)) - { - CommandLine.WriteError("Version number can't be null"); - return false; - } - - var match = Regex.Match(Arguments.Version, @"^(\d+)\.(\d+)\.(\d)+$"); - if (!match.Success) - { - CommandLine.WriteError("Invalid version Number. Version should be in .. form."); - return false; - } - - MajorVersion = int.Parse(match.Groups[1].Value); - MinorVersion = int.Parse(match.Groups[2].Value); - BuildVersion = int.Parse(match.Groups[3].Value); - - // Create the name of the local working copy. - if (String.IsNullOrEmpty(Arguments.OutputDirectory)) - { - Arguments.OutputDirectory = DateTime.UtcNow.ToString("yyyy-MM-dd-hh-mm-ss"); - } - - string fullPath = Path.GetFullPath(Arguments.OutputDirectory); - if (!Directory.Exists(fullPath)) - { - Directory.CreateDirectory(fullPath); - } - - Environment.CurrentDirectory = WorkingCopy = fullPath; - CommandLine.WriteLine(Arguments.ToString()); - - return true; - } - - /// Cleans the default repository from user files ('resharper', '.user', etc.). - private static void CleanDefaultRepository() - { - string toDelete = Default.Combine("_ReSharper.GoogleApisClient"); - if (Directory.Exists(toDelete)) - { - Directory.Delete(toDelete, true); - } - foreach (string pattern in new[] { "*.dotcover", "*.user", "*.suo" }) - { - foreach (string file in Directory.GetFiles(Default.WorkingDirectory, pattern)) - { - File.Delete(file); - } - } - } - - /// Checks out all repositories. - private static void CheckoutRepositories() - { - CommandLine.WriteLine("{{white}} ======================================="); - CommandLine.WriteLine("{{white}} Checking out repositories"); - CommandLine.WriteLine("{{white}} ======================================="); - const string URL = "https://code.google.com/p/google-api-dotnet-client{0}/"; - - if (Arguments.UseLocalRepository) - { - CommandLine.WriteAction("Using local Default repository. This won't release!"); - Default = Hg.Get("../../../../../", string.Format(URL, "")); - } - else - { - Default = Hg.Get("default", string.Format(URL, "")); - if (BuildVersion != 0) - { - Default.Update(string.Format("{0}.{1}", MajorVersion, MinorVersion)); - } - } - - Samples = Hg.Get("samples", string.Format(URL, ".samples")); - Wiki = Hg.Get("wiki", string.Format(URL, ".wiki")); - Contrib = Hg.Get("contrib", string.Format(URL, ".contrib")); - AllRepositories = new[] { Default, Wiki, Contrib, Samples }; - - CommandLine.WriteLine(); - } - - /// - /// Builds projects. - /// In addition runs UnitTest for testing projects. - /// - private static Project[] BuildProjects(out FileVersionInfo apiVersion, out Project[] allProjects) - { - CommandLine.WriteLine("{{white}} ======================================="); - CommandLine.WriteLine("{{white}} Building the Projects"); - CommandLine.WriteLine("{{white}} ======================================="); - - var projects = new List(); - Project baseApi = new Project(Default.Combine("Src", "GoogleApis", "GoogleApis.csproj")); - - Project fullProfileApi = new Project(Default.Combine("Src", "GoogleApis.FullProfile", - "GoogleApis.FullProfile.csproj")); - - Project oauth2 = new Project(Default.Combine("Src", "GoogleApis.Authentication.OAuth2", - "GoogleApis.Authentication.OAuth2.csproj")); - - var releaseProjects = new[] { baseApi, fullProfileApi, oauth2 }; - projects.AddRange(releaseProjects); - projects.Add(new Project(Default.Combine("Src", "GoogleApis.Tests.Utility", - "GoogleApis.Tests.Utility.csproj"))); - projects.Add(new Project(Default.Combine("Src", "GoogleApis.Tests", "GoogleApis.Tests.csproj"))); - projects.Add(new Project(Default.Combine("Src", "GoogleApis.Authentication.OAuth2.Tests", - "GoogleApis.Authentication.OAuth2.Tests.csproj"))); - - foreach (Project proj in projects) - { - proj.ReplaceVersion(Arguments.Version); - proj.RunBuildTask(); - if (!releaseProjects.Contains(proj)) // If this assembly may contain tests, then run them. - { - RunUnitTest(proj.BinaryFile); - } - } - - CommandLine.WriteLine(); - apiVersion = FileVersionInfo.GetVersionInfo(baseApi.BinaryFile); - allProjects = projects.ToArray(); - return releaseProjects; - } - - /// - /// Runs the unit tester on the specified assembly. - /// - /// Called from extern assemblies. - public static void RunUnitTest(string assembly) - { - // Run the unit tester. - try - { - new Runner(Google.Build.Tester.Program.BinPath, assembly).Run(); - } - catch (ExternalException ex) - { - CommandLine.WriteError(" {0} tests failed.", ex.ErrorCode < 0 ? "Loading" : ex.ErrorCode.ToString()); - if (!CommandLine.RequestUserChoice("Do you want to continue anyway?")) - { - throw; - } - } - } - - /// Gets tag name by the given release version. - private static string GetTagName(FileVersionInfo releaseVersion) - { - CommandLine.WriteLine("{{white}} ======================================="); - CommandLine.WriteLine("{{white}} Creating Tag for the release"); - CommandLine.WriteLine("{{white}} ======================================="); - - if (Arguments.UseLocalRepository) - { - return "date-version-local"; - } - - string tag = Arguments.Version; - if (!string.IsNullOrEmpty(Arguments.Tag)) - { - tag += "-" + Arguments.Tag; - } - - CommandLine.WriteResult("Tag", tag); - CommandLine.WriteLine(); - return tag; - } - - /// Returns all changelist notes for this release. - private static string CreateChangelog(string tag) - { - StringBuilder log = new StringBuilder(); - log.AppendLine("Google .NET Client Library"); - log.AppendLine(string.Format("Stable Release '{0}'", tag)); - log.AppendLine(DateTime.UtcNow.ToLongDateString()); - log.AppendLine("==========================================="); - - log.AppendLine(); - log.AppendLine("Changes:"); - foreach (string line in Default.CreateChangelist()) - { - log.AppendLine(" " + line); - } - - return log.ToString(); - } - - /// Udates the samples repository. - private static void UpdateSamples(IEnumerable releaseProjects) - { - CommandLine.WriteLine("{{white}} ======================================="); - CommandLine.WriteLine("{{white}} Updating Samples"); - CommandLine.WriteLine("{{white}} ======================================="); - - // Update all the dependencies. - string libDir = Samples.Combine("Lib"); - DirUtils.ClearDir(libDir); - - foreach (Project p in releaseProjects) - { - p.CopyTo(libDir); - } - - string thirdpartyDir = Samples.Combine("Lib", "ThirdParty"); - Directory.CreateDirectory(thirdpartyDir); - foreach (string file in ThirdPartyFiles) - { - DirUtils.CopyFile(file, thirdpartyDir); - } - - DirUtils.ClearDir(ServiceDir); - - // Generate all strongly typed services. - Console.WriteLine("Update the samples repository Services library \"{0}\" with the new generated services", - ServiceDir); - Console.WriteLine("Press any key to continue..."); - Console.ReadKey(); - - // Build all the samples projects. - CommandLine.WriteAction("Building samples..."); - foreach (string csproj in - Directory.GetFiles(Samples.WorkingDirectory, "*.csproj", SearchOption.AllDirectories)) - { - Project project = new Project(csproj); - project.RunBuildTask(); - project.Clean(); - } - CommandLine.WriteLine(); - } - - /// - /// Builds the Releases in the Contrib repository. - /// Depends on: - /// - Compiled BaseLibrary - /// - Updated Sample repository - /// - Existing release tag name - /// - /// Edited changelog. - private static string BuildContribRelease(string tag, - string changelog, - IEnumerable baseLibrary, - IEnumerable allProjects, - out string zipDir) - { - CommandLine.WriteLine("{{white}} ======================================="); - CommandLine.WriteLine("{{white}} Building Contrib-Release"); - CommandLine.WriteLine("{{white}} ======================================="); - - string releaseDir = Contrib.Combine(tag); - string currentDir = Contrib.Combine("Current"); - - // Clear existing directories. - DirUtils.ClearOrCreateDir(releaseDir); - // TODO(peleyal): remove currentDir eventually (after at least one or two releases) - DirUtils.ClearOrCreateDir(currentDir); - - // Create the release - string genDir = Path.Combine(currentDir, "Generated"); - Directory.CreateDirectory(genDir); - - #region Current/Generated/Bin - string binDir = Path.Combine(genDir, "Bin"); - CommandLine.WriteAction("Generating dir: " + DirUtils.GetRelativePath(binDir, Contrib.WorkingDirectory)); - Directory.CreateDirectory(binDir); - { - // Copy all third party dlls into this directory. - foreach (string file in ThirdPartyFiles) - { - DirUtils.CopyFile(file, binDir); - } - - // Copy all release dlls to this directory. - foreach (Project project in baseLibrary) - { - project.CopyTo(binDir); - } - } - #endregion - - #region Current/ZipFiles - string zipFilesDir = Path.Combine(genDir, "ZipFiles"); - CommandLine.WriteAction("Generating dir: " + - DirUtils.GetRelativePath(zipFilesDir, Contrib.WorkingDirectory)); - Directory.CreateDirectory(zipFilesDir); - { - // clean all projects - foreach (Project project in allProjects) - { - project.Clean(); - } - - // Source.zip - using (Zip zip = new Zip(Path.Combine(zipFilesDir, "Source.zip"))) - { - zip.AddDirectory(Default.WorkingDirectory, ""); - zip.RemoveDirectory(".hg"); - zip.RemoveFile(".hgtags"); - zip.RemoveFile(".hgignore"); - } - - // Binary.zip - using (Zip zip = new Zip(Path.Combine(zipFilesDir, "Binary.zip"))) - { - zip.AddDirectory(binDir, ""); - } - - // Samples.zip - using (Zip zip = new Zip(Path.Combine(zipFilesDir, "Samples.zip"))) - { - zip.AddDirectory(Samples.WorkingDirectory, ""); - zip.RemoveDirectory(".hg"); - zip.RemoveFile(".hgtags"); - zip.RemoveFile(".hgignore"); - } - } - #endregion - - #region Current/ReleaseNotes.txt - CommandLine.WriteAction("Writing file..."); - string changelogFile = Path.Combine(currentDir, "ReleaseNotes.txt"); - using (var writer = new StreamWriter(changelogFile, false)) - { - writer.WriteLine(changelog); - } - #endregion - - // Open the created changelog. - CommandLine.WriteAction("Showing result..."); - Process.Start(changelogFile).WaitForExit(); - - // Copy the content to the release directory. - DirUtils.CopyFiles(currentDir, releaseDir); - - // Rename the zips in the named release. - // Example: Binary.zip -> google-api-dotnet-client-1.0.0-beta.Binary.zip - string fileFormat = "google-api-dotnet-client-" + tag + ".{0}"; - zipDir = zipFilesDir.Replace(currentDir, releaseDir); - foreach (string file in Directory.GetFiles(zipDir, "*.zip")) - { - string dir = Path.GetDirectoryName(file); - string newFile = string.Format(fileFormat, Path.GetFileName(file).ToLower()); - File.Move(file, Path.Combine(dir, newFile)); - } - - CommandLine.WriteLine(); - return File.ReadAllText(changelogFile); - } - - /// Updates wiki Downloads page. - private static void UpdateWiki(string releaseNotes, string zipDir) - { - CommandLine.WriteLine("{{white}} ======================================="); - CommandLine.WriteLine("{{white}} Updating the Wiki"); - CommandLine.WriteLine("{{white}} ======================================="); - - new DownloadsPage(releaseNotes, zipDir).UpdateWiki(Wiki.WorkingDirectory); - - CommandLine.WriteLine(); - } - - /// Commits and Tags this release with the given tag - private static void CommitAndTagRelease(string tag) - { - CommandLine.WriteLine("{{white}} ======================================="); - CommandLine.WriteLine("{{white}} Tagging the release"); - CommandLine.WriteLine("{{white}} ======================================="); - - foreach (Hg repository in AllRepositories) - { - repository.AddUnversionedFiles(); - repository.RemoveDeletedFiles(); - bool madeCommit = repository.Commit("Release " + tag); - if (repository == Default || madeCommit) - { - try - { - repository.Tag(tag, false); - } - catch (Exception ex) - { - CommandLine.WriteError("Tagging Failed with message {0}", ex.Message); - string response = "yes"; - CommandLine.RequestUserInput("Do you want to force the label?", ref response); - if (response.ToLower() == "yes") - { - repository.Tag(tag, true); - } - else - { - throw; - } - } - } - } - CommandLine.WriteLine(); - } - - /// Pushes the changes in all repositories. - private static void PushChanges() - { - CommandLine.WriteLine("{{white}} ======================================="); - CommandLine.WriteLine("{{white}} Pushing changes"); - CommandLine.WriteLine("{{white}} ======================================="); - - foreach (Hg repository in AllRepositories) - { - repository.Push(); - } - - CommandLine.WriteLine(); - } - } -} Index: Tools/BuildRelease/Properties/AssemblyInfo.cs =================================================================== deleted file mode 100644 --- a/Tools/BuildRelease/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("BuildRelease")] -[assembly: AssemblyDescription("Google .NET Client API Release Builder")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Google Inc.")] -[assembly: AssemblyProduct("BuildRelease")] -[assembly: AssemblyCopyright("Copyright © Google Inc 2011")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("de63c3d0-88f4-4f5d-a0ff-957572eaf85b")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.1.*")] Index: Tools/BuildRelease/Wiki/DownloadsPage.cs =================================================================== deleted file mode 100644 --- a/Tools/BuildRelease/Wiki/DownloadsPage.cs +++ /dev/null @@ -1,104 +0,0 @@ -/* -Copyright 2013 Google Inc - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -using System; -using System.IO; -using System.Linq; -using System.Text.RegularExpressions; - -using Google.Apis.Samples.Helper; -using Google.Build.Utils.Text; - -namespace BuildRelease.Wiki -{ - /// Updator for the Downloads wiki page. - public class DownloadsPage - { - private const string StableStartTag = "GENERATED_STABLE_BEGIN"; - private const string StableEndTag = "GENERATED_STABLE_END"; - private const string DownloadsStartTag = "GENERATED_DOWNLOADS_BEGIN"; - private const string DownloadsEndTag = "GENERATED_DOWNLOADS_END"; - - private static readonly Regex LinkRegex = new Regex(@"\[([^ \]]*/)\S+ ([^\]]+)]", RegexOptions.Compiled); - - /// The Samples repository used for generating the list of samples. - public string ReleaseNotes { get; private set; } - - /// The directory containing the release .zip files. - public string ZipDir { get; private set; } - - /// The Name of this release. - public string ReleaseName { get; private set; } - - public DownloadsPage(string releaseNotes, string zipDir) - { - ReleaseNotes = releaseNotes; - ZipDir = zipDir; - ReleaseName = Path.GetFileName(Path.GetDirectoryName(Path.GetDirectoryName(zipDir))); - } - - /// Generates the Releases Notes section. - private string GenerateNotes() - { - return "{{{" + Environment.NewLine + ReleaseNotes + Environment.NewLine + "}}}"; - } - - /// - /// Replaces the download links references for binaries, source and samples to the current version number. - /// - /// The text block containing the wiki links. - /// Replaced & updated text. - private string ReplaceLinks(string input) - { - const string format = - "[http://contrib.google-api-dotnet-client.googlecode.com/hg/{0}/Generated/ZipFiles/{1} {2}]"; - return LinkRegex.Replace(input, (match) => string.Format(format, - ReleaseName, - GetFileName(match.Groups[2].ToString()), - match.Groups[2].ToString())); - } - - /// - /// Retrieves the filename of the release for the specified title/keyword. - /// Example: - /// 'Binary Release' results in 'google-api-dotnet-client-1.0.0.Binary.zip' - /// - private string GetFileName(string title) - { - string keyword = title.Split(' ')[0]; - return Path.GetFileName(Directory.GetFiles(ZipDir, "*" + keyword + "*").Single()); - } - - /// Modifies the existing Downloads wiki file by replacing the "generated" section. - private void InsertIntoFile(string file) - { - string content = File.ReadAllText(file); - content = TextUtils.InsertIntoText(content, StableStartTag, StableEndTag, GenerateNotes()); - content = TextUtils.ReplaceInText(content, DownloadsStartTag, DownloadsEndTag, ReplaceLinks); - File.WriteAllText(file, content); - } - - /// Updates the Wiki. - public void UpdateWiki(string workingDirectory) - { - if (ReleaseNotes != null) - { - CommandLine.WriteAction("Updating 'Downloads.wiki' ..."); - InsertIntoFile(Path.Combine(workingDirectory, "Downloads.wiki")); - } - } - } -} Index: Tools/BuildRelease/app.config =================================================================== deleted file mode 100644 --- a/Tools/BuildRelease/app.config +++ /dev/null @@ -1,3 +0,0 @@ - - - Index: Tools/Google.Apis.NuGet.Publisher/Google.Apis.NuGet.Publisher.csproj =================================================================== --- a/Tools/Google.Apis.NuGet.Publisher/Google.Apis.NuGet.Publisher.csproj +++ b/Tools/Google.Apis.NuGet.Publisher/Google.Apis.NuGet.Publisher.csproj @@ -63,10 +63,7 @@ - - - @@ -84,6 +81,12 @@ + + + {cbc99a4a-e3d0-4609-b704-7b2bf583fc30} + Google.Apis.Utils + + + \ No newline at end of file Index: Tools/Google.Apis.Release/Program.cs =================================================================== new file mode 100644 --- /dev/null +++ b/Tools/Google.Apis.Release/Program.cs @@ -0,0 +1,651 @@ +/* +Copyright 2013 Google Inc + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using Microsoft.Build.Evaluation; +using Microsoft.Build.Framework; +using Microsoft.Build.Logging; + +using CommandLine; +using CommandLine.Text; +using Ionic.Zip; + +using Google.Apis.Release.Repositories; +using Google.Apis.Release.Wiki; +using Google.Apis.Utils; +using Google.Apis.Utils.Trace; + +namespace Google.Apis.Release +{ + /// The main program for creating a new Google.Apis release. + class Program + { + /// The options class which contains the different options to this publish release utility. + public class Options + { + #region HelpText + + const string VersionHelpText = "The version number of this release - only."; + const string OutputHelpText = "Define the output directory for this build. " + + "Notice that it's relative to current directory."; + const string StepHelpText = "Two options: " + + "'1' for building the core library. \n" + + "'2' for compiling samples, updating wiki and push to contrib the new version."; + const string IsBetaHelpText = "Is this release beta?"; + const string NuGetApiKeyHelpText = "Define the NuGet API key to publish to NuGet main repository."; + + [HelpOption] + public string GetHelp() + { + return HelpText.AutoBuild(this, c => HelpText.DefaultParsingErrorsHandler(this, c)); + } + + #endregion + + [Option('v', "version", Required = true, HelpText = VersionHelpText)] + public string Version { get; set; } + + [Option('d', "dir", Required = true, HelpText = OutputHelpText)] + public string OutputDirectory { get; set; } + + [Option('s', "step", Required = true, HelpText = StepHelpText)] + public int Step { get; set; } + + [Option('b', "beta", DefaultValue = true, HelpText = IsBetaHelpText)] + public bool IsBeta { get; set; } + + [Option('k', "nuget_key", HelpText = NuGetApiKeyHelpText)] + public string NuGetApiKey { get; set; } + } + + private static readonly TraceSource TraceSource = new TraceSource("Google.Apis"); + + /// Command line arguments. + private readonly Options options; + + private int MajorVersion { get; set; } + private int MinorVersion { get; set; } + private int BuildVersion { get; set; } + + private string Tag + { + get { return options.Version + (options.IsBeta ? "-beta" : ""); } + } + + /// Gets or sets the "default" repository. + private Hg DefaultRepository { get; set; } + + /// Gets or sets the "samples" repository. + private Hg SamplesRepository { get; set; } + + /// Gets or sets the "wiki" repository. + private Hg WikiRepository { get; set; } + + /// Gets or sets the "contrib" repository. + private Hg ContribRepository { get; set; } + + /// Gets all four repositories. + private IEnumerable AllRepositories + { + get { return new List { DefaultRepository, SamplesRepository, WikiRepository, ContribRepository }; } + } + + /// + /// Clones URL format which expects one parameter of the repository name (the default repository should be + /// empty). + /// + private const string CloneUrlFormat = "https://code.google.com/p/google-api-dotnet-client{0}/"; + + static void Main(string[] args) + { + bool valid = true; + + var options = new Options(); + if (!CommandLine.Parser.Default.ParseArguments(args, options)) + { + Console.ReadKey(); + return; + } + + if (options.Step > 2 || options.Step < 1) + { + TraceSource.TraceEvent(TraceEventType.Error, "Invalid Step. Valid step is '1' or '2'."); + valid = false; + } + + var match = Regex.Match(options.Version, @"^(\d+)\.(\d+)\.(\d)+$"); + if (!match.Success) + { + TraceSource.TraceEvent(TraceEventType.Error, + "Invalid version Number. Version should be in .. form."); + valid = false; + } + + var program = new Program(options) + { + MajorVersion = int.Parse(match.Groups[1].Value), + MinorVersion = int.Parse(match.Groups[2].Value), + BuildVersion = int.Parse(match.Groups[3].Value), + }; + + if (valid) + { + try + { + program.Run(); + } + catch (Exception ex) + { + TraceSource.TraceEvent(TraceEventType.Error, "Exception occurred while running. Exception is: {0}", + ex.Message); + } + } + + Console.WriteLine("Press any key to continue..."); + Console.ReadKey(); + } + + /// The main release logic for creating a new release of Google.Apis. + private void Run() + { + DefaultRepository = new Hg(new Uri(string.Format(CloneUrlFormat, "")), "default"); + + // Step 1 is only for creating Google.Apis and Google.Apis.Authentication packages + if (options.Step == 1) + { + DoStep1(); + } + // Step 2 should be done after the NuGet publisher generated all the APIs and the samples repository was + // updated with the new packages + else if (options.Step == 2) + { + DoStep2(); + } + } + + /// Creates Google.Apis and Google.Apis.Authentication packages. + private void DoStep1() + { + if (BuildVersion != 0) + { + DefaultRepository.Update(string.Format("{0}.{1}", MajorVersion, MinorVersion)); + } + + // if there are incoming changes those changes will be printed, otherwise we can continue in the process + if (!HasIncomingChanges(new List { DefaultRepository })) + { + // in case build fails the method will print its failures + if (BuildDefaultRepository()) + { + CreateCoreNuGetPackages(); + // TODO(peleyal): release notes should be part of the package + } + } + } + + /// + /// Doing the following: + /// + /// Builds samples + /// Creates a release notes + /// Update wiki download page + /// Create a new release in the contrib repository + /// Commits, Tags and Pushes + /// + /// + private void DoStep2() + { + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine("========================="); + Console.WriteLine("Prerequisites for Step 2:"); + Console.WriteLine("You ran Step 1."); + Console.WriteLine("You upgraded the Google.Apis NuGet packages for each sample in the samples " + + "repository and pushed that change."); + Console.WriteLine("========================="); + if (!CanContinue()) + { + return; + } + + SamplesRepository = new Hg(new Uri(string.Format(CloneUrlFormat, ".samples")), "samples"); + WikiRepository = new Hg(new Uri(string.Format(CloneUrlFormat, ".wiki")), "wiki"); + ContribRepository = new Hg(new Uri(string.Format(CloneUrlFormat, ".contrib")), "contrib"); + + // if there are incoming changes those changes will be printed, otherwise we can continue in the + // process + if (!HasIncomingChanges(AllRepositories)) + { + BuildSamples(); + var notes = CreateContribNewRelease(); + UpdateWiki(notes); + + foreach (var repository in AllRepositories) + { + repository.AddRemoveFiles(); + } + + Console.WriteLine("========================="); + Console.WriteLine("Commit, Tag and Push"); + Console.WriteLine("========================="); + if (!CanContinue()) + { + return; + } + + // commit + CommitAndTag(); + + // push + foreach (Hg repository in AllRepositories) + { + repository.Push(); + } + + // create branch + PrintCreateBranch(); + + // publish core components to NuGet + if (!string.IsNullOrEmpty(options.NuGetApiKey)) + { + PublishPackagesToNuGet(); + Console.WriteLine("Now... you should run the NuGet publisher to publish a new PCL " + + "for each generated Google API. Run: " + + "Google.Apis.NuGet.Publisher --all_apis true -m publisher -k [NUGET_KEY]"); + } + else + { + TraceSource.TraceEvent(TraceEventType.Error, "NuGet API key is empty!"); + } + } + } + + /// Asks the user if he wants to continue in the process. + /// true if the user to press 'y' or 'yes' to continue + private bool CanContinue() + { + var yesOptions = new[] { "y", "yes" }; + var noOptions = new[] { "n", "no" }; + + string input; + do + { + Console.WriteLine("Press 'y' | 'yes' to continue, or 'n' | 'no' to stop"); + input = Console.ReadLine().ToLower(); + } while (!yesOptions.Contains(input) && !noOptions.Contains(input)); + + return yesOptions.Contains(input); + } + + /// Publishes the core packages to NuGet main repository. + private void PublishPackagesToNuGet() + { + var apiNupkgPath = Path.Combine(NuGetUtilities.LocalNuGetPackageFolder, + string.Format("Google.Apis.{0}.nupkg", Tag)); + NuGetUtilities.PublishToNuget(apiNupkgPath, options.NuGetApiKey); + + var authenticationNupkgPath = Path.Combine(NuGetUtilities.LocalNuGetPackageFolder, + string.Format("Google.Apis.Authentication.{0}.nupkg", Tag)); + NuGetUtilities.PublishToNuget(authenticationNupkgPath, options.NuGetApiKey); + } + + /// + /// Displays the user orders how to create a branch (only in case it's a new major or minor release. + /// + private void PrintCreateBranch() + { + if (BuildVersion != 0) + { + // No need to branch in that case + return; + } + + // TODO(peleyal): consider automate this as well + Console.WriteLine("You should create a new branch for this release now:"); + Console.WriteLine("cd " + DefaultRepository.WorkingDirectory); + var branchVersion = string.Format("{0}.{1}", MajorVersion, MinorVersion); + Console.WriteLine("hg branch " + branchVersion); + Console.WriteLine(string.Format("hg commit -m create {0} branch", branchVersion)); + Console.WriteLine("hg push --new-branch"); + } + + /// Commits all changes in all repositories and tags the "default" repository. + private void CommitAndTag() + { + foreach (var repository in AllRepositories) + { + TraceSource.TraceEvent(TraceEventType.Information, "{0} - Committing", repository.Name); + + bool committed = repository.Commit("Release " + Tag); + + // TODO(peleyal): think to remove this if from this function. I don't like a if inside a loop statement + if (repository.Equals(DefaultRepository) && committed) + { + try + { + repository.Tag(Tag, false); + TraceSource.TraceEvent(TraceEventType.Information, "{0} - Was tagged \"{1}\"", + repository.Name, Tag); + } + catch (Exception ex) + { + TraceSource.TraceEvent(TraceEventType.Error, "{0} - Tagging Failed. Exception is: {1}", + repository.Name, ex.Message); + } + } + + TraceSource.TraceEvent(TraceEventType.Information, "{0} - Committed", repository.Name); + } + } + + /// Updates the "Downloads" wiki page with the new release notes. + private void UpdateWiki(string notes) + { + TraceSource.TraceEvent(TraceEventType.Information, "Updating wiki downloads page"); + + // TODO(peleyal): improve. Currently we count on that old release of X.Y.Z is X.Y-1.0 + var oldVersion = string.Format("{0}.{1}.{2}", MajorVersion, MinorVersion - 1, 0); + DownloadsPageUpdater.UpdateWiki(WikiRepository.WorkingDirectory, notes, oldVersion, options.Version); + + TraceSource.TraceEvent(TraceEventType.Information, "wiki downloads page was updated"); + } + + /// Creates a new release in the "contrib" repository. + /// The release notes of this version + private string CreateContribNewRelease() + { + TraceSource.TraceEvent(TraceEventType.Information, "Building Contrib release"); + + string releaseDir = ContribRepository.Combine(Tag); + + // Clear existing directories. + DirectoryUtilities.ClearOrCreateDirectory(releaseDir); + string genDir = Path.Combine(releaseDir, "Generated"); + Directory.CreateDirectory(genDir); + + #region [RELEASE_VERSION]/Generated/Bin + + string binDir = Path.Combine(genDir, "Bin"); + TraceSource.TraceEvent(TraceEventType.Information, "Generating \"{0}\" directory", + DirectoryUtilities.GetRelativePath(binDir, ContribRepository.WorkingDirectory)); + + Directory.CreateDirectory(binDir); + foreach (var project in ReleaseProjects) + { + var releasePath = Path.Combine(project.DirectoryPath, "Bin", "Release"); + foreach (var filePath in Directory.GetFiles(releasePath, "Google.Apis.*")) + { + File.Copy(filePath, + Path.Combine(binDir, filePath.Substring(filePath.LastIndexOf("\\") + 1)), true); + } + } + + // TODO(peleyal): Put also the nuspec and nupkg + + #endregion + + #region [RELEASE_VERSION]/ZipFiles + + string zipFilesDir = Path.Combine(genDir, "ZipFiles"); + TraceSource.TraceEvent(TraceEventType.Information, "Generating \"{0}\" directory", + DirectoryUtilities.GetRelativePath(zipFilesDir, ContribRepository.WorkingDirectory)); + + Directory.CreateDirectory(zipFilesDir); + foreach (var project in ReleaseProjects) + { + project.Build("Clean"); + } + + TraceSource.TraceEvent(TraceEventType.Information, "Release projects were cleaned"); + + // source.zip + var fileNameFormat = "google-api-dotnet-client-{0}.{1}.zip"; + var sourceZipName = string.Format(fileNameFormat, Tag, "source"); + using (var zip = new ZipFile(Path.Combine(zipFilesDir, sourceZipName))) + { + zip.AddDirectory(Path.Combine(DefaultRepository.WorkingDirectory, "Src"), "Src"); + zip.AddFile(Path.Combine(DefaultRepository.WorkingDirectory, "GoogleApisClient.sln"), ""); + zip.AddFile(Path.Combine(DefaultRepository.WorkingDirectory, "LICENSE"), ""); + zip.Save(); + } + TraceSource.TraceEvent(TraceEventType.Information, "{0} was created", sourceZipName); + + // binary.zip + var binaryZipName = string.Format(fileNameFormat, Tag, "binary"); + using (var zip = new ZipFile(Path.Combine(zipFilesDir, binaryZipName))) + { + Directory.GetFiles(binDir).ToList().ForEach(f => zip.AddFile(Path.Combine(binDir, f), "")); + zip.Save(); + } + TraceSource.TraceEvent(TraceEventType.Information, "{0} was created", binaryZipName); + + + // samples.zip + var samplesZipName = string.Format(fileNameFormat, Tag, "samples"); + using (var zip = new ZipFile(Path.Combine(zipFilesDir, samplesZipName))) + { + foreach (var d in Directory.GetDirectories(SamplesRepository.WorkingDirectory)) + { + if (!d.EndsWith(".hg")) + { + var directoryName = d.Substring(d.LastIndexOf("\\") + 1); + zip.AddDirectory(Path.Combine(SamplesRepository.WorkingDirectory, d), directoryName); + } + } + foreach (var f in Directory.GetFiles(SamplesRepository.WorkingDirectory, "*.sln")) + { + zip.AddFile(Path.Combine(SamplesRepository.WorkingDirectory, f), ""); + } + zip.Save(); + } + + TraceSource.TraceEvent(TraceEventType.Information, "{0} was created", samplesZipName); + + #endregion + + #region [RELEASE_VERSION]/ReleaseNotes.txt + + var notes = GetChangelog(); + TraceSource.TraceEvent(TraceEventType.Information, "Creating ReleaseNotes file"); + var noteFilePath = Path.Combine(genDir, "ReleaseNotes.txt"); + File.WriteAllText(noteFilePath, notes); + + #endregion + + // open the created change-log and read again the notes (in case the user had modified the file) + Process.Start(noteFilePath).WaitForExit(); + notes = File.ReadAllText(noteFilePath); + + return notes; + } + + /// + /// Returns the notes list of this release. It contains the change log of all pushes to the "default" + /// repository. + /// + private string GetChangelog() + { + StringBuilder log = new StringBuilder(); + log.AppendLine("Google .NET Client Library"); + log.AppendLine(string.Format("Stable Release '{0}'", Tag)); + log.AppendLine(DateTime.UtcNow.ToLongDateString()); + log.AppendLine("==========================================="); + + log.AppendLine().AppendLine("Changes:"); + foreach (string line in DefaultRepository.CreateChangelist()) + { + log.AppendLine(" " + line); + } + + return log.ToString(); + } + + /// Builds all projects in the "samples" repository. + private void BuildSamples() + { + // build all the samples projects. + TraceSource.TraceEvent(TraceEventType.Information, "Building the samples"); + foreach (string csproj in Directory.GetFiles(SamplesRepository.WorkingDirectory, "*.csproj", + SearchOption.AllDirectories)) + { + Project project = new Project(csproj); + project.SetProperty("Configuration", "Release"); + TraceSource.TraceEvent(TraceEventType.Information, "Building {0}", project.GetName()); + bool success = project.Build("Build", new[] { new ConsoleLogger(LoggerVerbosity.Quiet) }); + if (!success) + { + TraceSource.TraceEvent(TraceEventType.Error, "Building {0} FAILED", project.GetName()); + } + project.Build("Clean"); + TraceSource.TraceEvent(TraceEventType.Information, "Building {0} succeeded", project.GetName()); + } + } + + /// Returns true if one of the repositories has incoming changes. + private bool HasIncomingChanges(IEnumerable repositories) + { + foreach (var repository in repositories) + { + if (repository.HasIncomingChanges) + { + TraceSource.TraceEvent(TraceEventType.Error, + "[{0}] has incoming changes. Run hg pull & update first!", repository.Name); + return true; + } + } + return false; + } + + /// Creates the Google.Apis and Google.Apis.Authentication NuGet packages. + private void CreateCoreNuGetPackages() + { + // create a resource dir in the working folder + var destDirectory = Path.Combine(Environment.CurrentDirectory, "Resources"); + if (Directory.Exists(destDirectory)) + { + Directory.Delete(destDirectory, true); + } + + FileInfo info = new FileInfo(Assembly.GetEntryAssembly().Location); + DirectoryUtilities.CopyDirectory(Path.Combine(info.Directory.FullName, "Resources"), destDirectory); + + var newVersion = options.Version + "-beta"; + + // get the Google.Apis and Google.Apis.Authentication nuspec files and replace the version in it + var apiNuspec = Path.Combine(destDirectory, "Google.Apis.VERSION.nuspec"); + var newApiNuspec = apiNuspec.Replace("VERSION", newVersion); + var authenticationNuspec = Path.Combine(destDirectory, "Google.Apis.Authentication.VERSION.nuspec"); + var newAuthenticationNuspec = authenticationNuspec.Replace("VERSION", newVersion); + + File.Move(apiNuspec, newApiNuspec); + File.Move(authenticationNuspec, newAuthenticationNuspec); + + var allLines = File.ReadAllText(newApiNuspec).Replace("VERSION", newVersion); + File.WriteAllText(newApiNuspec, allLines); + + allLines = File.ReadAllText(newAuthenticationNuspec).Replace("VERSION", newVersion); + File.WriteAllText(newAuthenticationNuspec, allLines); + + NuGetUtilities.CreateLocalNupkgFile(newApiNuspec, Environment.CurrentDirectory); + NuGetUtilities.CreateLocalNupkgFile(newAuthenticationNuspec, Environment.CurrentDirectory); + } + + private IEnumerable releaseProjects; + /// Gets the release projects of from the "default" repository. + private IEnumerable ReleaseProjects + { + get + { + if (releaseProjects != null) + { + return releaseProjects; + } + + var releasePaths = new[] + { + DefaultRepository.Combine("Src", "GoogleApis", "GoogleApis.csproj"), + DefaultRepository.Combine("Src", "GoogleApis.DotNet4", "GoogleApis.DotNet4.csproj"), + DefaultRepository.Combine("Src", "GoogleApis.Authentication.OAuth2", + "GoogleApis.Authentication.OAuth2.csproj") + }; + return releaseProjects = (from path in releasePaths + select new Project(path)).ToList(); + } + } + + /// Builds the "default" repository projects. + /// true if the default repository was build successfully + private bool BuildDefaultRepository() + { + TraceSource.TraceEvent(TraceEventType.Information, "Building projects...."); + + var allProjects = new List(); + allProjects.AddRange(ReleaseProjects); + allProjects.Add(new Project(DefaultRepository.Combine("Src", "GoogleApis.Tests", + "GoogleApis.Tests.csproj"))); + allProjects.Add(new Project(DefaultRepository.Combine("Src", "GoogleApis.Authentication.OAuth2.Tests", + "GoogleApis.Authentication.OAuth2.Tests.csproj"))); + + foreach (var project in allProjects) + { + var name = project.GetName(); + TraceSource.TraceEvent(TraceEventType.Information, "Replacing version for {0}", name); + project.ReplaceVersion(options.Version); + project.SetProperty("Configuration", "Release"); + TraceSource.TraceEvent(TraceEventType.Information, "Building {0}", name); + bool success = project.Build("Build", new[] { new ConsoleLogger(LoggerVerbosity.Quiet) }); + + if (success) + { + TraceSource.TraceEvent(TraceEventType.Information, "Building {0} succeeded!", name); + } + else + { + TraceSource.TraceEvent(TraceEventType.Error, "Building {0} failed!", name); + return false; + } + + if (!ReleaseProjects.Contains(project)) + { + // TODO(peleyal): run unit tests for all test projects + } + } + + return true; + } + + /// Constructs a new program with the given options. + public Program(Options options) + { + this.options = options; + + string path = Path.GetFullPath(options.OutputDirectory); + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path); + } + + Environment.CurrentDirectory = path; + } + } +} Index: Tools/Google.Apis.Release/ProjectExtenstions.cs =================================================================== new file mode 100644 --- /dev/null +++ b/Tools/Google.Apis.Release/ProjectExtenstions.cs @@ -0,0 +1,85 @@ +/* +Copyright 2013 Google Inc + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; + +using Microsoft.Build.Evaluation; + +using Google.Apis.Utils; +using Google.Apis.Utils.Trace; + +namespace Google.Apis.Release +{ + /// + /// Extension methods for the Project class. + /// Add support in getting the short name of the project and also in replacing the current library version with + /// the new version (). + /// + internal static class ProjectExtenstions + { + static readonly TraceSource TraceSource = new TraceSource("Google.Apis"); + + /// Gets the name of the project. + public static string GetName(this Project project) + { + return project.DirectoryPath.Substring(project.DirectoryPath.LastIndexOf(Path.DirectorySeparatorChar) + 1); + } + + /// Replaces Assembly version number with the given one. + public static void ReplaceVersion(this Project project, string newVersion) + { + const string ASSEMBLY_INFO_PREFIX = "[assembly: AssemblyVersion(\""; + + // no need to increase version + if (newVersion == null) + return; + + var assemblyInfoFile = System.IO.Path.Combine(project.DirectoryPath, "Properties", "AssemblyInfo.cs"); + + try + { + // read all lines and replace the current version with the given newVersion + var allLines = File.ReadAllLines(assemblyInfoFile).Select( + l => + { + // if the line contains assembly information, replace old version with new version + if (l.StartsWith(ASSEMBLY_INFO_PREFIX)) + return ReplaceVersionInLine(l, ASSEMBLY_INFO_PREFIX, newVersion); + else + return l; + }); + File.WriteAllLines(assemblyInfoFile, allLines); + } + catch (Exception ex) + { + TraceSource.TraceEvent(TraceEventType.Error, "Exception occurred while replacing version", ex.Message); + } + } + + /// Returns the assembly information line with the new version. + private static string ReplaceVersionInLine(string line, string assemblyVersionPrefix, string newVersion) + { + var startVersion = assemblyVersionPrefix.Length; + // '.*' ends the old version number (e.g 1.2.* or 1.2.0.*) + var endVersion = line.IndexOf(".*", startVersion); + var oldVersion = line.Substring(startVersion, endVersion - startVersion); + return line.Replace(assemblyVersionPrefix + oldVersion, assemblyVersionPrefix + newVersion); + } + } +} Index: Tools/Google.Apis.Release/Properties/AssemblyInfo.cs =================================================================== new file mode 100644 --- /dev/null +++ b/Tools/Google.Apis.Release/Properties/AssemblyInfo.cs @@ -0,0 +1,52 @@ +/* +Copyright 2013 Google Inc + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Google.Apis.Release")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Google Inc")] +[assembly: AssemblyProduct("Google.Apis.Release")] +[assembly: AssemblyCopyright("Copyright © Google Inc 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("872013b6-ebe2-4c44-b6bb-1b92f318f463")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.5.0.*")] +[assembly: AssemblyFileVersion("1.0.0.0")] Index: Tools/Google.Apis.Release/Repositories/Hg.cs =================================================================== rename from Tools/Google.Build.Utils/Repositories/Hg.cs rename to Tools/Google.Apis.Release/Repositories/Hg.cs --- a/Tools/Google.Build.Utils/Repositories/Hg.cs +++ b/Tools/Google.Apis.Release/Repositories/Hg.cs @@ -22,33 +22,26 @@ using System.Runtime.InteropServices; using System.Text.RegularExpressions; -using Google.Apis.Samples.Helper; +using Google.Apis.Utils; +using Google.Apis.Utils.Trace; -namespace Google.Build.Utils.Repositories +namespace Google.Apis.Release.Repositories { - /// - /// Mercurial interfacing class - /// + /// Mercurial repository interface class. public sealed class Hg : IDisposable { - /// - /// Name of the repository. - /// + static readonly TraceSource TraceSource = new TraceSource("Google.Apis"); + + /// Gets the name of the repository.summary> public string Name { get; private set; } - /// - /// The URI of the repositoty - /// + /// Gets the URI of the repository public Uri RepositoryUri { get; private set; } - /// - /// The local working directory. - /// + /// Gets the local working directory. public string WorkingDirectory { get; private set; } - /// - /// True if this working copy has pending changes. - /// + /// Gets indication if repository has pending changes. public bool HasUncommitedChanges { get @@ -58,9 +51,7 @@ } } - /// - /// True if there are unpulled, incoming changes. - /// + /// Gets indication if there are incoming changes. public bool HasIncomingChanges { get @@ -77,16 +68,14 @@ } } - /// - /// True if this working copy has unpushed changes. - /// + /// Gets indication if the working copy has un-pushed changes. public bool HasUnpushedChanges { get { try { - string[] changes = RunListeningHg("outgoing {0} {1}", "-l", "1"); + string[] changes = RunListeningHg(string.Format("outgoing {0} {1}", "-l", "1")); return changes.Length >= 4; } catch (ExternalException) @@ -99,12 +88,13 @@ } } - private Hg(Uri repositoryUri) - : this(repositoryUri, Path.Combine(Path.GetTempPath(), Path.GetRandomFileName())) - { - - } - private Hg(Uri repositoryUri, string localDir) + /// + /// Constructs a new repository. It creates a new repository if the folder doesn't exists, otherwise it gets + /// the current status of the repository. + /// + /// The URI of this repository + /// The local directory which contains the repository files + public Hg(Uri repositoryUri, string localDir) { RepositoryUri = repositoryUri; WorkingDirectory = Path.GetFullPath(localDir); @@ -112,19 +102,18 @@ if (!Directory.Exists(WorkingDirectory)) { + TraceSource.TraceEvent(TraceEventType.Information, "[{0}] Fetching {1}", Name, repositoryUri); Directory.CreateDirectory(WorkingDirectory); - this.CloneFrom(repositoryUri); + RunHg(string.Format("clone {0} {1}", repositoryUri.ToString(), WorkingDirectory)); } else { - CommandLine.WriteAction("Using existing repository for " + Name + " at " + WorkingDirectory + " .."); + TraceSource.TraceEvent(TraceEventType.Information, "[{0}] Using an existing repository", Name); RunHg("status"); } } - /// - /// Commits the pending changes. - /// + /// Commits the pending changes. /// Description of the changes/the commit. /// Whether a commit was made/possible. public bool Commit(string message) @@ -136,54 +125,30 @@ RunHg("status -m -a -r"); - CommandLine.WriteAction("Commiting changes of " + Name + " .."); - RunHg("commit -m \"{0}\"", message); + TraceSource.TraceEvent(TraceEventType.Information, "[{0}] Committing changes", Name); + RunHg(string.Format("commit -m \"{0}\"", message)); return true; } - /// - /// Adds a tag to the last revision. - /// + /// Adds a tag to the last revision. /// The tag to add. /// - /// If set to true will overwrite existing labels of this name see "hg help tag" and its - /// --force parameter. + /// If set to true will overwrite existing labels of this name see "hg help tag" and its --force parameter. /// public void Tag(string tagName, bool force = false) { - CommandLine.WriteAction("Tagging " + Name + " with " + tagName + ".."); + TraceSource.TraceEvent(TraceEventType.Information, "[{0}] Tagging with {1}", Name, tagName); string options = (force ? "-f " : ""); - RunHg("tag {0}\"{1}\"", options, tagName); + RunHg(string.Format("tag {0}\"{1}\"", options, tagName)); } - /// - /// Adds all unversioned files to the current commit. - /// - public void AddUnversionedFiles() + /// Adds all unversioned files and remove all versioned files. + public void AddRemoveFiles() { - RunHg("add"); + RunHg("addremove"); } - /// - /// Marks all versioned files which have been deleted as removed. - /// - public void RemoveDeletedFiles() - { - var missingFiles = RunListeningHg("status -d") - .Where(l => l.StartsWith("! ")) - .Select(l => "\"" + l.Substring("! ".Length) + "\""); - - string files = String.Join(" ", missingFiles); - if (!string.IsNullOrEmpty(files)) - { - CommandLine.WriteAction("Removing files: " + files); - RunHg("remove {0}", files); - } - } - - /// - /// Pushes all commited changes to the server. - /// + /// Pushes all committed changes to the server. public void Push() { if (!HasUnpushedChanges) @@ -191,99 +156,63 @@ return; } - CommandLine.WriteAction("Pushing " + Name + " .."); - RunShellHg("push"); + TraceSource.TraceEvent(TraceEventType.Information, "Pushing {0}", Name); + RunHg("push"); } - /// Updates the repository by the branch name. - /// + /// Updates the repository by the branch name. public void Update(string branchName) { - CommandLine.WriteAction("Updating branch to " + branchName); - RunShellHg("update " + branchName); + TraceSource.TraceEvent(TraceEventType.Information, "[{0}] Updating branch to {1}", Name, branchName); + RunHg("update " + branchName); } - /// - /// Pulls and updates this clone. - /// - public void PullUpdate() - { - RunShellHg("hg pull"); - RunShellHg("hg update"); - } - - /// - /// Outputs the diff to the default output stream. - /// - public void ShowDiff() - { - RunShellHg("diff"); - } - - /// - /// Creates the combined path of the specified directories. - /// + /// Creates the combined path of the specified directories. public string Combine(params string[] dirs) { return dirs.Aggregate(WorkingDirectory, Path.Combine); } - /// - /// Creates a change list by listing all changes made since the last release. - /// + /// Creates a change list by listing all changes made since the last release. public IEnumerable CreateChangelist() { Regex tagRegex = new Regex("Added tag [0-9A-Za-z.-]+ for changeset [^b]+", RegexOptions.Compiled); string branch = RunListeningHg("branch").Single(); - return RunListeningHg("log --template \"{{rev}}: {{desc}}\\r\\n\" -b {0}", branch) + return RunListeningHg(string.Format("log --template \"{{rev}}: {{desc}}\\r\\n\" -b {0}", branch)) .TakeWhile(line => !tagRegex.IsMatch(line)); } - private void CloneFrom(Uri uri) + /// Runs a HG command. In addition it prints errors and messages to trace. + private void RunHg(string command) { - CommandLine.WriteAction("Fetching " + uri + " .."); - RunHg("clone {0} {1}", uri.ToString(), WorkingDirectory); + RunHg(command, + error => + { + if (!string.IsNullOrEmpty(error)) + { + TraceSource.TraceEvent(TraceEventType.Error, "[{0}] {1}", Name, error); + } + }, + msg => + { + if (!string.IsNullOrEmpty(msg)) + { + TraceSource.TraceEvent(TraceEventType.Information, "[{0}] hg {1}", Name, msg); + } + }); } - private void RunShellHg(string command, params string[] args) - { - RunHg(command, null, null, args); - } - - private void RunHg(string command, params string[] args) - { - RunHg( - command, error => - { - if (!string.IsNullOrEmpty(error)) - { - CommandLine.WriteError(error); - } - }, msg => - { - if (!string.IsNullOrEmpty(msg)) - { - CommandLine.WriteResult("hg", msg); - } - }, args); - } - - private string[] RunListeningHg(string command, params string[] args) - { - var msgs = new List(); - RunHg(command, msgs.Add, msgs.Add, args); - return msgs.ToArray(); - } - - private void RunHg(string command, Action errors, Action msgs, params string[] args) + /// + /// Run a HG command which the specific callback for errors or messages returned from the command. + /// + private void RunHg(string command, Action errorCallback = null, Action messageCallback = null) { var process = new Process(); - string commandLine = string.Format(command, args); - process.StartInfo = new ProcessStartInfo("hg", commandLine); + process.StartInfo = new ProcessStartInfo("hg", command); process.StartInfo.WorkingDirectory = WorkingDirectory; - if (errors != null || msgs != null) + if (errorCallback != null || messageCallback != null) { process.StartInfo.RedirectStandardError = true; process.StartInfo.RedirectStandardOutput = true; @@ -292,31 +221,31 @@ } process.Start(); - - if (errors != null) + if (errorCallback != null) { process.ErrorDataReceived += (sender, msg) => - { - if (msg.Data != null) - { - errors(msg.Data); - } - }; + { + if (msg.Data != null) + { + errorCallback(msg.Data); + } + }; process.BeginErrorReadLine(); } - if (msgs != null) + if (messageCallback != null) { process.OutputDataReceived += (sender, msg) => - { - if (msg.Data != null) - { - msgs(msg.Data); - } - }; + { + if (msg.Data != null) + { + messageCallback(msg.Data); + } + }; process.BeginOutputReadLine(); } process.WaitForExit(); + if (process.ExitCode != 0) { string cmdLine = process.StartInfo.FileName + " " + process.StartInfo.Arguments; @@ -324,27 +253,17 @@ } } - /// - /// Clones a new Mercurial repository. - /// - public static Hg Clone(string repository) + /// Runs a HG command and returns all its errors and messages output. + private string[] RunListeningHg(string command) { - return new Hg(new Uri(repository)); - } - - /// - /// Reuses the existing local repository, or creates a new clone of it does not exist. - /// - /// The local Mercurial repository. - /// The remote URL. - public static Hg Get(string localDir, string repository) - { - return new Hg(new Uri(repository), localDir); + var msgs = new List(); + RunHg(command, msgs.Add, msgs.Add); + return msgs.ToArray(); } public void Dispose() { - CommandLine.WriteAction("Cleaning up " + Name + " .."); + TraceSource.TraceEvent(TraceEventType.Information, "[{0}] Cleaning up", Name); Directory.Delete(WorkingDirectory, true); } } Index: Tools/Google.Apis.Release/Resources/Google.Apis.Authentication.VERSION.nuspec =================================================================== new file mode 100644 --- /dev/null +++ b/Tools/Google.Apis.Release/Resources/Google.Apis.Authentication.VERSION.nuspec @@ -0,0 +1,29 @@ + + + + Google.Apis.Authentication + VERSION + Google APIs OAuth2 Client Library + Google Inc. + peleyal + http://www.apache.org/licenses/LICENSE-2.0 + https://code.google.com/p/google-api-dotnet-client/ + false + + The Google APIs Client Library is a runtime client for working with Google Services. + This pakcage includes component for making authenticated calls using the OAuth2 spec. + + Google + + + + + + + + + + + + + \ No newline at end of file Index: Tools/Google.Apis.Release/Resources/Google.Apis.VERSION.nuspec =================================================================== new file mode 100644 --- /dev/null +++ b/Tools/Google.Apis.Release/Resources/Google.Apis.VERSION.nuspec @@ -0,0 +1,59 @@ + + + + Google.Apis + VERSION + Google APIs Client Library + Google Inc. + peleyal + http://www.apache.org/licenses/LICENSE-2.0 + https://code.google.com/p/google-api-dotnet-client/ + false + + The Google APIs Client Library is a runtime client for working with Google Services. + The library supports service requests, media upload and download, etc. + + Supported Platforms: + + - Windows Store apps + + - Windows Phone 7.5 and 8 + + - Silverlight 4 and 5 + + - Portable Class Libraries + + Google + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file Index: Tools/Google.Apis.Release/Resources/License.txt =================================================================== new file mode 100644 --- /dev/null +++ b/Tools/Google.Apis.Release/Resources/License.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. Index: Tools/Google.Apis.Release/Wiki/DownloadsPageUpdater.cs =================================================================== new file mode 100644 --- /dev/null +++ b/Tools/Google.Apis.Release/Wiki/DownloadsPageUpdater.cs @@ -0,0 +1,85 @@ +/* +Copyright 2013 Google Inc + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +using System; +using System.IO; + +namespace Google.Apis.Release.Wiki +{ + /// + /// Updates the Downloads wiki page (https://code.google.com/p/google-api-dotnet-client/wiki/Downloads). + /// + public static class DownloadsPageUpdater + { + private const string StableStartTag = "GENERATED_STABLE_BEGIN"; + private const string StableEndTag = "GENERATED_STABLE_END"; + + /// Updates the Wiki. + public static void UpdateWiki(string workingDirectory, string notes, string oldVersion, string newVersion) + { + if (string.IsNullOrEmpty(workingDirectory)) throw new ArgumentNullException("workingDirectory"); + if (string.IsNullOrEmpty(notes)) throw new ArgumentNullException("notes"); + if (string.IsNullOrEmpty(oldVersion)) throw new ArgumentNullException("oldVersion"); + if (string.IsNullOrEmpty(newVersion)) throw new ArgumentNullException("newVersion"); + + + var filePath = Path.Combine(workingDirectory, "Downloads.wiki"); + string content = File.ReadAllText(filePath); + + // update notes. Replace all text from StableStartTag to StableEndTag + var generatedNotes = "{{{" + Environment.NewLine + notes + Environment.NewLine + "}}}"; + content = ReplacePart(content, StableStartTag, StableEndTag, oldText => generatedNotes); + + // update links + content = content.Replace(oldVersion, newVersion); + File.WriteAllText(filePath, content); + } + + /// + /// Returns a new string with the content of the source and a new text based on replaceFuncbetween + /// startPartTag to endPartTag. + /// + /// The source content + /// The start part tag + /// The end part tag + /// The replacement function from the old text to new text + private static string ReplacePart(string source, string startPartTag, string endPartTag, + Func replaceFunc) + { + // find the start tag + int startIndex = source.IndexOf(startPartTag); + if (startIndex < 0) + { + throw new ArgumentException("Start Tag not found: " + startPartTag); + } + startIndex += startPartTag.Length; + + // find the end tag + int endIndex = source.IndexOf(endPartTag, startIndex); + if (endIndex < 0) + { + throw new ArgumentException("End Tag not found: " + endPartTag); + } + + var oldText = source.Substring(startIndex, endIndex - startIndex).Trim('\r', '\n'); + var newText = replaceFunc(oldText); + + // replace the text + return source.Substring(0, startIndex) + Environment.NewLine + + newText + Environment.NewLine + source.Substring(endIndex); + } + } +} Index: Tools/Google.Apis.Release/packages.config =================================================================== new file mode 100644 --- /dev/null +++ b/Tools/Google.Apis.Release/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file Index: Tools/Google.Apis.Utils/DirectoryUtilities.cs =================================================================== rename from Tools/Google.Apis.NuGet.Publisher/DirectoryUtilities.cs rename to Tools/Google.Apis.Utils/DirectoryUtilities.cs --- a/Tools/Google.Apis.NuGet.Publisher/DirectoryUtilities.cs +++ b/Tools/Google.Apis.Utils/DirectoryUtilities.cs @@ -18,6 +18,8 @@ using System.IO; using System.Linq; +using Google.Apis.Utils.Trace; + namespace Google.Apis.Utils { /// Directory utilities which support copying, clearing and other operations on directories. @@ -28,7 +30,7 @@ /// Copies a directory recursively to a new one. /// Source directory /// Destination directory - internal static void CopyDirectory(string sourceDir, string destDir) + public static void CopyDirectory(string sourceDir, string destDir) { DirectoryInfo dir = new DirectoryInfo(sourceDir); if (!dir.Exists) Index: Tools/Google.Apis.Utils/Google.Apis.Utils.csproj =================================================================== new file mode 100644 --- /dev/null +++ b/Tools/Google.Apis.Utils/Google.Apis.Utils.csproj @@ -0,0 +1,70 @@ + + + + + Debug + AnyCPU + {CBC99A4A-E3D0-4609-B704-7B2BF583FC30} + Library + Properties + Google.Apis.Utils + Google.Apis.Utils + v4.5 + 512 + ..\ + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Microsoft.Web.Xdt.1.0.0\lib\net40\Microsoft.Web.XmlTransform.dll + + + False + ..\packages\Nuget.Core.2.6.0.1\lib\net40-Client\NuGet.Core.dll + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file Index: Tools/Google.Apis.Utils/NuGetUtilities.cs =================================================================== rename from Tools/Google.Apis.NuGet.Publisher/NuGetUtilities.cs rename to Tools/Google.Apis.Utils/NuGetUtilities.cs --- a/Tools/Google.Apis.NuGet.Publisher/NuGetUtilities.cs +++ b/Tools/Google.Apis.Utils/NuGetUtilities.cs @@ -21,6 +21,8 @@ using NuGet; +using Google.Apis.Utils.Trace; + namespace Google.Apis.Utils { /// Index: Tools/Google.Apis.Utils/Properties/AssemblyInfo.cs =================================================================== new file mode 100644 --- /dev/null +++ b/Tools/Google.Apis.Utils/Properties/AssemblyInfo.cs @@ -0,0 +1,52 @@ +/* +Copyright 2013 Google Inc + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Google.Apis.Utils")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Google Inc")] +[assembly: AssemblyProduct("Google.Apis.Utils")] +[assembly: AssemblyCopyright("Copyright © Google Inc 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("c8895269-c8e5-4222-8171-6ff4aa597f5d")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.5.0.*")] +[assembly: AssemblyFileVersion("1.0.0.0")] Index: Tools/Google.Apis.Utils/Trace/TraceExtensions.cs =================================================================== new file mode 100644 --- /dev/null +++ b/Tools/Google.Apis.Utils/Trace/TraceExtensions.cs @@ -0,0 +1,31 @@ +/* +Copyright 2013 Google Inc + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +using System.Diagnostics; +using System.Threading; + +namespace Google.Apis.Utils.Trace +{ + /// Extension methods to . + public static class Extensions + { + /// Traces the event using the current thread id. + public static void TraceEvent(this TraceSource trace, TraceEventType type, string msg, params object[] args) + { + trace.TraceEvent(type, Thread.CurrentThread.ManagedThreadId, msg, args); + } + } +} Index: Tools/Google.Apis.Utils/packages.config =================================================================== new file mode 100644 --- /dev/null +++ b/Tools/Google.Apis.Utils/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file Index: Tools/Google.Build.Tester/Google.Build.Tester.csproj =================================================================== deleted file mode 100644 --- a/Tools/Google.Build.Tester/Google.Build.Tester.csproj +++ /dev/null @@ -1,68 +0,0 @@ - - - - Debug - x86 - 8.0.30703 - 2.0 - {585E1BD4-C989-4041-9AA2-14EEB13D8F15} - Exe - Properties - Google.Build.Tester - Google.Build.Tester - v4.0 - 512 - - - - x86 - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - x86 - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - ..\Lib\nunit.core.dll - - - False - ..\Lib\nunit.core.interfaces.dll - - - - - - - - - - - - - - - - - - - - \ No newline at end of file Index: Tools/Google.Build.Tester/Program.cs =================================================================== deleted file mode 100644 --- a/Tools/Google.Build.Tester/Program.cs +++ /dev/null @@ -1,65 +0,0 @@ -/* -Copyright 2011 Google Inc - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -using System; -using System.Diagnostics; -using System.IO; -using System.Reflection; -using System.Security.Policy; - -namespace Google.Build.Tester -{ - /// - /// A simple unit tester. - /// - public class Program - { - /// - /// Path to the Unit tester binary. - /// - public static string BinPath - { - get { return new Uri(typeof(Program).Assembly.CodeBase).LocalPath; } - } - - internal static void Main(string[] args) - { - // Check the parameter. - string assembly = String.Join(" ", args); - if (!File.Exists(assembly)) - { - Console.Error.WriteLine("Assembly not found: "+assembly); - Environment.Exit(-1); - } - - // Run the unit tester. - try - { - Environment.ExitCode = UnitTester.Run(assembly); - } - catch (ReflectionTypeLoadException ex) - { - Console.Error.WriteLine("Failed to load types:"); - foreach (Exception e in ex.LoaderExceptions) - { - Console.Error.WriteLine(); - Console.Error.WriteLine(" " + e.Message); - } - Environment.Exit(-2); - } - } - } -} Index: Tools/Google.Build.Tester/Properties/AssemblyInfo.cs =================================================================== deleted file mode 100644 --- a/Tools/Google.Build.Tester/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Google.Build.Tester")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Microsoft")] -[assembly: AssemblyProduct("Google.Build.Tester")] -[assembly: AssemblyCopyright("Copyright © Microsoft 2011")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("50a7a87d-265d-4c52-9937-457ef4228d8d")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.1.*")] Index: Tools/Google.Build.Tester/UnitTester.cs =================================================================== deleted file mode 100644 --- a/Tools/Google.Build.Tester/UnitTester.cs +++ /dev/null @@ -1,225 +0,0 @@ -/* -Copyright 2011 Google Inc - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using NUnit.Core; -using NUnit.Core.Filters; - -namespace Google.Build.Tester -{ - /// - /// A simple unit tester class. - /// - [Serializable] - public class UnitTester : EventListener, IDisposable - { - static UnitTester() - { - CoreExtensions.Host.InitializeService(); - } - - private readonly RemoteTestRunner runner; - private readonly AppDomain domain; - private Results resultsSandbox; - private List messagesSandbox; - - [Serializable] - public class Results - { - /// - /// The total numbers of tests run. - /// - public int Total { get { return Passed + Failed; } } - - /// - /// Passed unit tests. - /// - public int Passed { get; set; } - - /// - /// Failed unit tests. - /// - public int Failed { get; set; } - - [Serializable] - public struct Message - { - public bool IsError; - public string Text; - } - - /// - /// Messages - /// - public Message[] Messages { get; set; } - } - - /// - /// Creates a unit tester for the specified assembly. - /// - /// Number of failed unit tests. - public static int Run(string testAssembly) - { - string tempFolder = Path.Combine(Path.GetTempPath(), "UnitTest" + testAssembly.GetHashCode()); - while (Directory.Exists(tempFolder)) - { - tempFolder += "_"; - } - - Directory.CreateDirectory(tempFolder); - try - { - // Copy over all assemblies. - Utils.CopyFiles(Path.GetDirectoryName(testAssembly), tempFolder); - - // Copy over the nunit dlls. - foreach (string dll in (from a in AppDomain.CurrentDomain.GetAssemblies() - where a.GetName().Name.StartsWith("nunit.") || a == typeof(UnitTester).Assembly - select new Uri(a.CodeBase).LocalPath)) - { - File.Copy(dll, Path.Combine(tempFolder, Path.GetFileName(dll))); - } - - // Create and run the unit tester - using (UnitTester tester = new UnitTester(Path.Combine(tempFolder, Path.GetFileName(testAssembly)))) - { - Results results = tester.Run(); - foreach (var msg in results.Messages) - { - (msg.IsError ? Console.Error : Console.Out).WriteLine(msg.Text); - } - if (results.Total > 0) - { - Console.WriteLine("PASSED: " + results.Passed); - - if (results.Failed > 0) - { - Console.Error.WriteLine("FAILED: " + results.Failed); - } - } - return results.Failed; - } - } - finally - { - Directory.Delete(tempFolder, true); - } - } - - private UnitTester(string testAssembly) - { - var testPackage = new TestPackage(Path.GetFileNameWithoutExtension(testAssembly)); - testPackage.Assemblies.Add(testAssembly); - - // Create a new appdomain with the appropriate working directory. - // This is required so that we don't accidentially load the wrong dependencies. - var setup = new AppDomainSetup(); - setup.ApplicationBase = Path.GetDirectoryName(testAssembly); - domain = AppDomain.CreateDomain("TestDomain", null, setup); - - runner = RemoteTestRunner.CreateInstance(domain, 0); - runner.Load(testPackage); - } - - /// - /// Runs all unit tests on this assembly. - /// - /// Number of failed tests. - public Results Run() - { - runner.Run(this); - return domain.GetData("Results") as Results; - } - - private void Log(bool error, string msg, params object[] args) - { - messagesSandbox.Add(new Results.Message() { IsError = error, Text = string.Format(msg, args) }); - } - - public void RunStarted(string name, int testCount) - { - resultsSandbox = new Results(); - resultsSandbox.Passed = 0; - resultsSandbox.Failed = 0; - messagesSandbox = new List(); - - if (testCount == 0) - { - Log(false, "Assembly does not contain any unit tests."); - } - else - { - Log(false, "Running {0} tests for [{1}] ...", testCount, name); - } - Console.Out.Flush(); - } - - public void RunFinished(TestResult result) - { - resultsSandbox.Messages = messagesSandbox.ToArray(); - AppDomain.CurrentDomain.SetData("Results", resultsSandbox); - } - - public void RunFinished(Exception exception) - { - Console.Error.WriteLine(exception.ToString()); - Console.Out.Flush(); - } - - public void TestStarted(TestName testName) - { - Log(false, " Testing '{0}'", testName.FullName); - Console.Out.Flush(); - } - - public void TestFinished(TestResult result) - { - if (!result.IsSuccess) - { - Log(true, " [{0}]: FAILED!", result.Name); - foreach (string line in result.Message.Split(new[]{Environment.NewLine}, 0)) - { - Log(true," {0}", line); - } - resultsSandbox.Failed++; - } - else - { - resultsSandbox.Passed++; - } - } - - public void SuiteStarted(TestName testName) {} - - public void SuiteFinished(TestResult result) {} - - public void UnhandledException(Exception exception) - { - Log(true, " Exception: "+exception.Message); - } - - public void TestOutput(TestOutput testOutput) { } - - public void Dispose() - { - runner.Dispose(); - AppDomain.Unload(domain); - } - } -} Index: Tools/Google.Build.Tester/Utils.cs =================================================================== deleted file mode 100644 --- a/Tools/Google.Build.Tester/Utils.cs +++ /dev/null @@ -1,61 +0,0 @@ -/* -Copyright 2011 Google Inc - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -using System.IO; - -namespace Google.Build.Tester -{ - /// - /// Utility class. - /// - internal class Utils - { - /// - /// Copies all files and directories from the source to the destination. - /// - public static void CopyFiles(string source, string dest) - { - foreach (var file in Directory.GetFiles(source, "*", SearchOption.AllDirectories)) - { - string fileDest = Path.Combine(dest, GetRelativePath(file, source)); - string dir = Path.GetDirectoryName(fileDest); - - if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) - { - Directory.CreateDirectory(dir); - } - - File.Copy(file, fileDest, true); - } - } - - /// - /// Retrieves the relative path from the parent to the child. - /// - public static string GetRelativePath(string child, string parent) - { - string absoluteChild = Path.GetFullPath(child); - string absoluteParent = Path.GetFullPath(parent); - - if (!absoluteChild.StartsWith(absoluteParent + Path.DirectorySeparatorChar)) - { - return absoluteChild; // Nothing in common. - } - - return absoluteChild.Substring(absoluteParent.Length + 1); - } - } -} Index: Tools/Google.Build.Tester/app.config =================================================================== deleted file mode 100644 --- a/Tools/Google.Build.Tester/app.config +++ /dev/null @@ -1,3 +0,0 @@ - - - Index: Tools/Google.Build.Utils/Build/Project.cs =================================================================== deleted file mode 100644 --- a/Tools/Google.Build.Utils/Build/Project.cs +++ /dev/null @@ -1,252 +0,0 @@ -/* -Copyright 2011 Google Inc - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using Google.Apis.Samples.Helper; -using Microsoft.Build.Evaluation; -using Microsoft.Build.Framework; -using ConsoleLogger = Microsoft.Build.BuildEngine.ConsoleLogger; - -namespace Google.Build.Utils.Build -{ - /// - /// Represents a buildable project. - /// - public class Project - { - /// - /// The working directory in which the project file resides. - /// - public string WorkingDirectory { get; private set; } - - /// - /// The .csproj project file. - /// - public string ProjectFile { get; private set; } - - /// - /// The Configuration to build. Default: "Release" - /// - public string Configuration - { - get { return internalProject.GetProperty("Configuration").EvaluatedValue; } - set { internalProject.SetProperty("Configuration", value); } - } - - /// - /// Path to the generated binary file. - /// - public string BinaryFile - { - get { return internalProject.GetPropertyValue("TargetPath"); } - } - - /// - /// The simple name of this project. - /// - public string Name - { - get { return internalProject.GetPropertyValue("ProjectName"); } - } - - /// - /// Returns the paths to all generated output files. - /// - public string[] OutputFiles - { - get - { - string[] extensions = new[] { ".pdb", ".xml" }; - string binary = BinaryFile; - - // Generate the list of output files. - var result = new List(); - result.Add(BinaryFile); - result.AddRange(extensions.Select(ext => Path.ChangeExtension(binary, ext)).Where(File.Exists)); - return result.ToArray(); - } - } - - private readonly Microsoft.Build.Evaluation.Project internalProject; - - public Project(string projectFile) - { - if (!File.Exists(projectFile)) - { - throw new FileNotFoundException("The specified project file cannot be found.", projectFile); - } - ProjectFile = projectFile; - WorkingDirectory = Path.GetDirectoryName(projectFile); - internalProject = (from p in ProjectCollection.GlobalProjectCollection.LoadedProjects - where p.FullPath == Path.GetFullPath(projectFile) - select p).SingleOrDefault() ?? new Microsoft.Build.Evaluation.Project(ProjectFile); - Configuration = "Release"; - } - - private void Build(string target) - { - if (!internalProject.Build(target)) - { - // If the build fails, re-run this build with a logger attached. - internalProject.Build(target, new[] { new ConsoleLogger(LoggerVerbosity.Quiet) }); - Process.Start(WorkingDirectory); - throw new ApplicationException("Build of project [" + this + ":" + target + "] failed!"); - } - } - - /// - /// Cleans the project. - /// - public void Clean() - { - Log("Cleaning ..."); - Build("Clean"); - } - - /// - /// Compiles the project. - /// - public void Compile() - { - Log("Compiling ..."); - Build("Build"); - - if (!File.Exists(BinaryFile)) - { - throw new ApplicationException( - "Build was successful, but target binary file does not exist: " + BinaryFile); - } - } - - /// - /// Copies the resulting binaries to the specified directory. - /// - public void CopyTo(string dir) - { - Log("Copying output to " + Path.GetFileName(dir) + " ..."); - - if (!Directory.Exists(dir)) - { - Directory.CreateDirectory(dir); - } - - // Copy all output files into the target directory - foreach (string file in OutputFiles) - { - string fileName = Path.GetFileName(file); - Log(" * " + fileName); - File.Copy(file, Path.Combine(dir, fileName), true); - } - } - - /// - /// Copies the resulting binaries and dependencies to the specified directory. - /// - public void CopyAllFilesTo(string dir) - { - Log("Copying output to " + Path.GetFileName(dir) + " ..."); - - if (!Directory.Exists(dir)) - { - Directory.CreateDirectory(dir); - } - - // Copy all output files into the target directory - string buildDir = Path.GetDirectoryName(BinaryFile); - foreach (string file in Directory.GetFiles(buildDir, "*.*", SearchOption.TopDirectoryOnly)) - { - switch (Path.GetExtension(file).ToLower()) - { - case ".dll": - case ".exe": - case ".pdb": - case ".xml": - break; // Copy all assemblies and relevant information into the target directory. - - default: - continue; // Unsupported. - } - - string fileName = Path.GetFileName(file); - Log(" * " + fileName); - File.Copy(file, Path.Combine(dir, fileName), true); - } - } - - /// Cleans and Compiles the project. - public void RunBuildTask() - { - CommandLine.WriteAction("Running [" + Name + "] build task.."); - Clean(); - Compile(); - } - - public override string ToString() - { - return Path.GetFileNameWithoutExtension(ProjectFile); - } - - private void Log(string msg) - { - CommandLine.WriteLine("{{green}} " + msg, this); - } - - /// Replaces Assembly version numner with the given one. - public void ReplaceVersion(string newVersion) - { - // no need to increase version - if (newVersion == null) - return; - - var ASSEMBLY_INFO_PREFIX = "[assembly: AssemblyVersion(\""; - var assemblyInfoFile = System.IO.Path.Combine(WorkingDirectory, "Properties", "AssemblyInfo.cs"); - - try - { - // read all lines and replace the current version with the given newVersion - var allLines = File.ReadAllLines(assemblyInfoFile).Select( - l => - { - // if the line contains assembly information, replace old version with new version - if (l.StartsWith(ASSEMBLY_INFO_PREFIX)) - return ReplaceVersionInLine(l, ASSEMBLY_INFO_PREFIX, newVersion); - else - return l; - }); - File.WriteAllLines(assemblyInfoFile, allLines); - } - catch (Exception ex) - { - // TODO(peleyal): remove before commiting - CommandLine.WriteLine(ex.Message); - } - } - - /// Returns the assembly infromation line with the new version. - private string ReplaceVersionInLine(string line, string assemblyVersionPrefix, string newVersion) - { - var startVersion = assemblyVersionPrefix.Length; - // '.*' ends the old version number (e.g 1.2.* \ 1.3.0.*) - var endVersion = line.IndexOf(".*", startVersion); - var oldVersion = line.Substring(startVersion, endVersion - startVersion); - return line.Replace(assemblyVersionPrefix + oldVersion, assemblyVersionPrefix + newVersion); - } - } -} Index: Tools/Google.Build.Utils/DirUtils.cs =================================================================== deleted file mode 100644 --- a/Tools/Google.Build.Utils/DirUtils.cs +++ /dev/null @@ -1,110 +0,0 @@ -/* -Copyright 2011 Google Inc - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -using System.IO; -using Google.Apis.Samples.Helper; - -namespace Google.Build.Utils -{ - /// - /// Directory helper utils. - /// - public static class DirUtils - { - /// - /// Removes all files and subdirectories of the specified directory. - /// - public static void ClearDir(string dir) - { - CommandLine.WriteAction("Clearing '" + Path.GetFileName(dir) + "' ..."); - Directory.Delete(dir, true); - Directory.CreateDirectory(dir); - } - - /// - /// Clears or creates the specified directory. - /// - public static void ClearOrCreateDir(string dir) - { - if (Directory.Exists(dir)) - { - ClearDir(dir); - } - else - { - Directory.CreateDirectory(dir); - CommandLine.WriteAction("Creating '"+Path.GetFileName(dir)+"' ..."); - } - } - - /// - /// Retrieves the relative path from the parent to the child. - /// - public static string GetRelativePath(string child, string parent) - { - string absoluteChild = Path.GetFullPath(child); - string absoluteParent = Path.GetFullPath(parent); - - if (!absoluteChild.StartsWith(absoluteParent + Path.DirectorySeparatorChar)) - { - return absoluteChild; // Nothing in common. - } - - return absoluteChild.Substring(absoluteParent.Length + 1); - } - - /// - /// Copies a single file to the specified destination. - /// - /// The source file. - /// The destination folder. - public static void CopyFile(string sourceFile, string destFolder) - { - CommandLine.WriteAction( - "Copying '" + Path.GetFileName(sourceFile) + "' to '" + Path.GetFileName(destFolder) + "/' ..."); - - if (!Directory.Exists(destFolder)) - { - Directory.CreateDirectory(destFolder); - } - - string destFile = Path.Combine(destFolder, Path.GetFileName(sourceFile)); - File.Copy(sourceFile, destFile, true); - } - - /// - /// Copies all files and directories from the source to the destination. - /// - public static void CopyFiles(string source, string dest) - { - CommandLine.WriteAction( - "Copying '" + Path.GetFileName(source) + "' to '" + Path.GetFileName(dest) + "' ..."); - - foreach (var file in Directory.GetFiles(source, "*", SearchOption.AllDirectories)) - { - string fileDest = Path.Combine(dest, GetRelativePath(file, source)); - string dir = Path.GetDirectoryName(fileDest); - - if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) - { - Directory.CreateDirectory(dir); - } - - File.Copy(file, fileDest, true); - } - } - } -} Index: Tools/Google.Build.Utils/Extensions.cs =================================================================== deleted file mode 100644 --- a/Tools/Google.Build.Utils/Extensions.cs +++ /dev/null @@ -1,45 +0,0 @@ -/* -Copyright 2011 Google Inc - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -using System; -using System.IO; -using System.Linq; -using System.Reflection; - -/// -/// Class providing extension methods to existing classes. -/// -public static class Extensions -{ - /// - /// Returns the path to the codebase of this assembly. - /// - public static string GetCodebasePath(this Assembly assembly) - { - // Convert the file:// specification into a local path. - Uri codebase = new Uri(assembly.CodeBase); - - // Get the real filename (.dll instead of .DLL). - return GetCorrectCasedFile(codebase.LocalPath); - } - - private static string GetCorrectCasedFile(string file) - { - // There is apparently no better way to do this on windows - return Directory.GetFiles(Path.GetDirectoryName(file), Path.GetFileName(file)).Single(); - } -} - Index: Tools/Google.Build.Utils/Google.Build.Utils.csproj =================================================================== deleted file mode 100644 --- a/Tools/Google.Build.Utils/Google.Build.Utils.csproj +++ /dev/null @@ -1,76 +0,0 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {A6E792C8-D5E7-40DD-9483-3901E70BF93F} - Library - Properties - Google.Build.Utils - Google.Build.Utils - v4.0 - 512 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - ..\Lib\Google.Apis.Samples.Helper.dll - - - ..\Lib\Ionic.Zip.dll - - - - - - ..\Lib\nunit.core.dll - - - ..\Lib\nunit.core.interfaces.dll - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file Index: Tools/Google.Build.Utils/Properties/AssemblyInfo.cs =================================================================== deleted file mode 100644 --- a/Tools/Google.Build.Utils/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Google.Build.Utils")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Microsoft")] -[assembly: AssemblyProduct("Google.Build.Utils")] -[assembly: AssemblyCopyright("Copyright © Microsoft 2011")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("44e852a3-7a68-42b1-b122-f0c726cee216")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.1.*")] Index: Tools/Google.Build.Utils/Runner.cs =================================================================== deleted file mode 100644 --- a/Tools/Google.Build.Utils/Runner.cs +++ /dev/null @@ -1,140 +0,0 @@ -/* -Copyright 2011 Google Inc - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices; -using System.Threading; -using Google.Apis.Samples.Helper; - -namespace Google.Build.Utils -{ - /// - /// Process Runner. - /// - public class Runner - { - /// - /// The command or application to run. - /// - public string Command { get; private set; } - - /// - /// The arguments which are passed to the application. - /// - public string Arguments { get; private set; } - - /// - /// The working directory of the application. - /// - public string WorkingDirectory { get; set; } - - public Runner(string command, params string[] args) - { - Command = command; - Arguments = args.Select(arg => "\"" + arg + "\"").Aggregate((a, b) => a + " " + b); - } - - /// - /// Runs the process in a seperate shell window. - /// - public void RunShell() - { - RunInternal(setup => {}, process => {}); - } - - /// - /// Runs the process and redirects the output into the current Console. - /// - public void Run() - { - string fileName = Path.GetFileNameWithoutExtension(Command); - object sync = new object(); - RunInternal((isError, msg) => - { - lock (sync) - { - if (isError) - { - msg = "{red}" + msg; - } - CommandLine.WriteResult(fileName, msg); - } - }); - } - - /// - /// Runs the process and returns the output. - /// - /// All messages of the process. - public string[] RunAndListen() - { - var msgs = new List(); - RunInternal((isError, msg) => msgs.Add(msg)); - return msgs.ToArray(); - } - - private void RunInternal(Action msg) - { - Action msgHandler = (isError, data) => - { - if (data.Data != null) - { - msg(isError, data.Data); - } - }; - - RunInternal( - info => - { - info.RedirectStandardError = true; - info.RedirectStandardOutput = true; - info.CreateNoWindow = true; - info.UseShellExecute = false; - }, process => - { - process.ErrorDataReceived += (sender, data) => msgHandler(true, data); - process.OutputDataReceived += (sender, data) => msgHandler(false, data); - process.BeginErrorReadLine(); - process.BeginOutputReadLine(); - }); - } - - private void RunInternal(Action setupProcess, Action afterStart) - { - // Setup the process. - var startInfo = new ProcessStartInfo(Command, Arguments); - startInfo.WorkingDirectory = WorkingDirectory; - setupProcess(startInfo); - - // Launch the process. - Process process = Process.Start(startInfo); - afterStart(process); - - // Wait for exit. - process.WaitForExit(); - Thread.Sleep(0); - if (process.ExitCode != 0) - { - string cmdLine = process.StartInfo.FileName + " " + process.StartInfo.Arguments; - throw new ExternalException("The process '" + cmdLine + "' exited with errors.", process.ExitCode); - } - } - } -} Index: Tools/Google.Build.Utils/Text/Template.cs =================================================================== deleted file mode 100644 --- a/Tools/Google.Build.Utils/Text/Template.cs +++ /dev/null @@ -1,72 +0,0 @@ -/* -Copyright 2011 Google Inc - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Google.Build.Utils.Text -{ - /// - /// Template helper class - /// - public class Template : List - { - public Template(string data) - { - AddRange(data.Split(new[] { Environment.NewLine }, StringSplitOptions.None)); - } - public Template() {} - - protected virtual string NewLine { get { return Environment.NewLine; } } - - /// - /// Returns the formatted result of this template/ - /// - public string ToString(Entries values) - { - string result = ToString(); - foreach (KeyValuePair value in values) - { - result = result.Replace("{" + value.Key + "}", value.Value == null ? "" : value.Value.ToString()); - } - return result; - } - public override string ToString() - { - return this.Aggregate((a, b) => a + NewLine + b); - } - } - - /// - /// Class containing the key-value entries of a template. - /// - public class Entries : Dictionary - { - /// - /// Adds the formatted string to this template. - /// - public void Add(string key, string format, params object[] values) - { - if (values.Length == 0 || string.IsNullOrEmpty(format)) - { - Add(key, (object) format); - return; - } - Add(key, (object)string.Format(format, values)); - } - } -} Index: Tools/Google.Build.Utils/Text/TextUtils.cs =================================================================== deleted file mode 100644 --- a/Tools/Google.Build.Utils/Text/TextUtils.cs +++ /dev/null @@ -1,139 +0,0 @@ -/* -Copyright 2011 Google Inc - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -using System; -using System.IO; - -namespace Google.Build.Utils.Text -{ - /// - /// Text helper utility. - /// - public static class TextUtils - { - /// - /// Inserts the specified content in the place between the start and end tag, which can be found in the - /// specified source text. - /// - /// Text which contains the tags. - /// The tag marking the start of the replacement area. - /// The tag marking the end of the replacement area. - /// The content to insert into the replacement area. - /// [..] {startTag} content {endTag} [..] - public static string InsertIntoText(string sourceText, string startTag, string endTag, string content) - { - return ReplaceInText(sourceText, startTag, endTag, old => content); - } - - /// - /// Replaces the text within the given tags using the specified replace function. - /// - /// The text containing the tags. - /// The tag marking the start of the replacement area. - /// The tag marking the end of the replacement area. - /// The function used to replace the tag content. - /// The resulting text. - public static string ReplaceInText(string sourceText, - string startTag, - string endTag, - Func replace) - { - // Find the start tag. - int startIndex = sourceText.IndexOf(startTag); - if (startIndex < 0) - { - throw new ArgumentException("Start Tag not found: " + startTag); - } - startIndex += startTag.Length; - - // Find the end tag. - int endIndex = sourceText.IndexOf(endTag, startIndex); - if (endIndex < 0) - { - throw new ArgumentException("End Tag not found: " + endTag); - } - - // Replace the text - string oldText = sourceText.Substring(startIndex, endIndex - startIndex).Trim('\r', '\n'); - string newText = replace(oldText); - return sourceText.Substring(0, startIndex) + Environment.NewLine + - newText + Environment.NewLine + - sourceText.Substring(endIndex); - } - - /// - /// Replaces the text within the given tags using the specified replace function. - /// - /// The file to replace the text in. - /// The tag marking the start of the replacement area. - /// The tag marking the end of the replacement area. - /// The function used to replace the tag content. - public static void ReplaceInFile(string file, string startTag, string endTag, Func replace) - { - File.WriteAllText(file, ReplaceInText(File.ReadAllText(file), startTag, endTag, replace)); - } - - /// - /// Inserts the specified content in the place between the start and end tag, which can be found in the - /// specified source text. - /// - /// The file containing the tags. - /// The tag marking the start of the replacement area. - /// The tag marking the end of the replacement area. - /// The content to insert into the replacement area. - /// [..] {startTag} content {endTag} [..] - public static void InsertIntoFile(string file, string startTag, string endTag, string content) - { - File.WriteAllText(file, InsertIntoText(File.ReadAllText(file), startTag, endTag, content)); - } - - /// - /// Transforms the first letter of the string into uppercase. - /// - public static string ToUpperFirstChar(this string str) - { - if (string.IsNullOrEmpty(str)) - { - return str; - } - return Char.ToUpper(str[0]) + str.Substring(1); - } - - /// - /// Finishes the specified string with the specified character. - /// - /// The sentence to end. - /// The character with which this sentence should end. - public static string MakeSentence(this string str, char endChar) - { - string trimmed = str.TrimEnd(' ', '\r', '\n'); - - if (trimmed.EndsWith(endChar.ToString())) - { - return str; - } - return trimmed + endChar + str.Substring(trimmed.Length); - } - - /// - /// Joins the two specified lines into a common string. - /// - public static string JoinLines(string a, string b) - { - return a + Environment.NewLine + b; - } - } -} Index: Tools/Google.Build.Utils/Zip.cs =================================================================== deleted file mode 100644 --- a/Tools/Google.Build.Utils/Zip.cs +++ /dev/null @@ -1,95 +0,0 @@ -/* -Copyright 2011 Google Inc - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Google.Apis.Samples.Helper; -using Ionic.Zip; - -namespace Google.Build.Utils -{ - /// - /// Zip support class. - /// - public class Zip : IDisposable - { - private readonly ZipFile zipFile; - - public Zip(string file) - { - CommandLine.WriteAction("Creating zip: "+Path.GetFileName(file)); - zipFile = new ZipFile(file); - } - - /// - /// Adds the specified file to the zip archive under "zipDir". - /// - public void AddFile(string file, string zipDir) - { - CommandLine.WriteResult("Adding File", Path.Combine(zipDir, Path.GetFileName(file))); - zipFile.AddFile(file, zipDir); - } - - /// - /// Adds the specified folder to the zip archive as "zipDir". - /// - public void AddDirectory(string dir, string zipDir) - { - CommandLine.WriteResult("Adding Directory", Path.GetFileName(dir) + " -> " + zipDir); - zipFile.AddDirectory(dir, zipDir); - } - - /// - /// Removes the specified entry from this zip if it existed in the first place. - /// - /// True if an entry was removed. - public bool RemoveFile(string entry) - { - if (!zipFile.ContainsEntry(entry)) - { - return false; - } - zipFile.RemoveEntry(entry); - return true; - } - - /// - /// Removes the specified directory from this zip. - /// - /// True if the directory existed before. - public bool RemoveDirectory(string entry) - { - if (!entry.EndsWith("/")) - { - entry = entry + "/"; - } - List toRemove = (from file in zipFile - where file.FileName.StartsWith(entry) - select file).ToList(); - zipFile.RemoveEntries(toRemove); - return toRemove.Count > 0; - } - - public void Dispose() - { - CommandLine.WriteAction("Saving zip..."); - zipFile.Save(); - zipFile.Dispose(); - } - } -} Index: Tools/Lib/Google.Apis.Samples.Helper.dll =================================================================== deleted file mode 100644 Binary file Tools/Lib/Google.Apis.Samples.Helper.dll has changed Index: Tools/Lib/Ionic.Zip.dll =================================================================== deleted file mode 100644 Binary file Tools/Lib/Ionic.Zip.dll has changed Index: Tools/Lib/nunit.core.dll =================================================================== deleted file mode 100644 Binary file Tools/Lib/nunit.core.dll has changed Index: Tools/Lib/nunit.core.interfaces.dll =================================================================== deleted file mode 100644 Binary file Tools/Lib/nunit.core.interfaces.dll has changed Index: Tools/Tools.sln =================================================================== --- a/Tools/Tools.sln +++ b/Tools/Tools.sln @@ -1,12 +1,6 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2012 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Build.Utils", "Google.Build.Utils\Google.Build.Utils.csproj", "{A6E792C8-D5E7-40DD-9483-3901E70BF93F}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BuildRelease", "BuildRelease\BuildRelease.csproj", "{0273723C-9B94-4A13-9635-4519633D9E0E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Build.Tester", "Google.Build.Tester\Google.Build.Tester.csproj", "{585E1BD4-C989-4041-9AA2-14EEB13D8F15}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Apis.NuGet.Publisher", "Google.Apis.NuGet.Publisher\Google.Apis.NuGet.Publisher.csproj", "{169385A5-0122-4BDD-BC34-73B6B399F781}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{E9959FE0-9FB2-499B-B624-DC2DC07B8106}" @@ -16,6 +10,10 @@ .nuget\NuGet.targets = .nuget\NuGet.targets EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Apis.Utils", "Google.Apis.Utils\Google.Apis.Utils.csproj", "{CBC99A4A-E3D0-4609-B704-7B2BF583FC30}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Apis.Release", "Google.Apis.Release\Google.Apis.Release.csproj", "{68A9F685-4B3D-4DFA-8CB1-F2F15B17A8AB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -26,36 +24,6 @@ Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {A6E792C8-D5E7-40DD-9483-3901E70BF93F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A6E792C8-D5E7-40DD-9483-3901E70BF93F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A6E792C8-D5E7-40DD-9483-3901E70BF93F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {A6E792C8-D5E7-40DD-9483-3901E70BF93F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {A6E792C8-D5E7-40DD-9483-3901E70BF93F}.Debug|x86.ActiveCfg = Debug|Any CPU - {A6E792C8-D5E7-40DD-9483-3901E70BF93F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A6E792C8-D5E7-40DD-9483-3901E70BF93F}.Release|Any CPU.Build.0 = Release|Any CPU - {A6E792C8-D5E7-40DD-9483-3901E70BF93F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {A6E792C8-D5E7-40DD-9483-3901E70BF93F}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {A6E792C8-D5E7-40DD-9483-3901E70BF93F}.Release|x86.ActiveCfg = Release|Any CPU - {0273723C-9B94-4A13-9635-4519633D9E0E}.Debug|Any CPU.ActiveCfg = Debug|x86 - {0273723C-9B94-4A13-9635-4519633D9E0E}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {0273723C-9B94-4A13-9635-4519633D9E0E}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {0273723C-9B94-4A13-9635-4519633D9E0E}.Debug|x86.ActiveCfg = Debug|x86 - {0273723C-9B94-4A13-9635-4519633D9E0E}.Debug|x86.Build.0 = Debug|x86 - {0273723C-9B94-4A13-9635-4519633D9E0E}.Release|Any CPU.ActiveCfg = Release|x86 - {0273723C-9B94-4A13-9635-4519633D9E0E}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {0273723C-9B94-4A13-9635-4519633D9E0E}.Release|Mixed Platforms.Build.0 = Release|x86 - {0273723C-9B94-4A13-9635-4519633D9E0E}.Release|x86.ActiveCfg = Release|x86 - {0273723C-9B94-4A13-9635-4519633D9E0E}.Release|x86.Build.0 = Release|x86 - {585E1BD4-C989-4041-9AA2-14EEB13D8F15}.Debug|Any CPU.ActiveCfg = Debug|x86 - {585E1BD4-C989-4041-9AA2-14EEB13D8F15}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {585E1BD4-C989-4041-9AA2-14EEB13D8F15}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {585E1BD4-C989-4041-9AA2-14EEB13D8F15}.Debug|x86.ActiveCfg = Debug|x86 - {585E1BD4-C989-4041-9AA2-14EEB13D8F15}.Debug|x86.Build.0 = Debug|x86 - {585E1BD4-C989-4041-9AA2-14EEB13D8F15}.Release|Any CPU.ActiveCfg = Release|x86 - {585E1BD4-C989-4041-9AA2-14EEB13D8F15}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {585E1BD4-C989-4041-9AA2-14EEB13D8F15}.Release|Mixed Platforms.Build.0 = Release|x86 - {585E1BD4-C989-4041-9AA2-14EEB13D8F15}.Release|x86.ActiveCfg = Release|x86 - {585E1BD4-C989-4041-9AA2-14EEB13D8F15}.Release|x86.Build.0 = Release|x86 {169385A5-0122-4BDD-BC34-73B6B399F781}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {169385A5-0122-4BDD-BC34-73B6B399F781}.Debug|Any CPU.Build.0 = Debug|Any CPU {169385A5-0122-4BDD-BC34-73B6B399F781}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU @@ -66,6 +34,26 @@ {169385A5-0122-4BDD-BC34-73B6B399F781}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {169385A5-0122-4BDD-BC34-73B6B399F781}.Release|Mixed Platforms.Build.0 = Release|Any CPU {169385A5-0122-4BDD-BC34-73B6B399F781}.Release|x86.ActiveCfg = Release|Any CPU + {CBC99A4A-E3D0-4609-B704-7B2BF583FC30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CBC99A4A-E3D0-4609-B704-7B2BF583FC30}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CBC99A4A-E3D0-4609-B704-7B2BF583FC30}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {CBC99A4A-E3D0-4609-B704-7B2BF583FC30}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {CBC99A4A-E3D0-4609-B704-7B2BF583FC30}.Debug|x86.ActiveCfg = Debug|Any CPU + {CBC99A4A-E3D0-4609-B704-7B2BF583FC30}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CBC99A4A-E3D0-4609-B704-7B2BF583FC30}.Release|Any CPU.Build.0 = Release|Any CPU + {CBC99A4A-E3D0-4609-B704-7B2BF583FC30}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {CBC99A4A-E3D0-4609-B704-7B2BF583FC30}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {CBC99A4A-E3D0-4609-B704-7B2BF583FC30}.Release|x86.ActiveCfg = Release|Any CPU + {68A9F685-4B3D-4DFA-8CB1-F2F15B17A8AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {68A9F685-4B3D-4DFA-8CB1-F2F15B17A8AB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {68A9F685-4B3D-4DFA-8CB1-F2F15B17A8AB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {68A9F685-4B3D-4DFA-8CB1-F2F15B17A8AB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {68A9F685-4B3D-4DFA-8CB1-F2F15B17A8AB}.Debug|x86.ActiveCfg = Debug|Any CPU + {68A9F685-4B3D-4DFA-8CB1-F2F15B17A8AB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {68A9F685-4B3D-4DFA-8CB1-F2F15B17A8AB}.Release|Any CPU.Build.0 = Release|Any CPU + {68A9F685-4B3D-4DFA-8CB1-F2F15B17A8AB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {68A9F685-4B3D-4DFA-8CB1-F2F15B17A8AB}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {68A9F685-4B3D-4DFA-8CB1-F2F15B17A8AB}.Release|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE