/// <summary> /// saves /// </summary> /// <param name="activeProject"></param> /// <returns></returns> private void SaveChangesAssembly(Project activeProject, PackageInformation packageInfo, ProjectInformation projectInformation) { LoggingManager.Instance.Logger.Debug("save changes c++ started"); StringBuilder errorMessage = new StringBuilder(); if (packageInfo.ProjectOptions.NuGetOptions.NuSpecOptions.Metadata.Id.Save) { if (!Utils.ExtensionUtil.SetPropertyValue<string>(activeProject.Properties, projectInformation.Id, packageInfo.NuSpecPackage.Metadata.Id)) { string message = string.Format("could not save back id: {1}", packageInfo.NuSpecPackage.Metadata.Id); errorMessage.Append(string.Format("{0}{1}", Environment.NewLine, message)); LoggingManager.Instance.Logger.Warn(message); } } //-----find the assemblInfo string assemblyName = string.Format("{0}{1}", projectInformation.AssemblyName, projectInformation.FileExtension); ProjectItem assembly = Utils.ExtensionUtil.GetItem(assemblyName, activeProject.ProjectItems); if (assembly == null) { throw new FileNotFoundException(string.Format("assembly: {0} could not be found", assemblyName)); } else { //-----change the assemblyInfo string assemblyFileFullname = Utils.ExtensionUtil.GetPropertyValue<string>(assembly.Properties, Resources.PropertyFullpath, null); LoggingManager.Instance.Logger.Debug(string.Format("changing assemblyInfo: {0}", assemblyFileFullname)); try { IOUtil.ReadAndWriteLinesStream(assemblyFileFullname, true, string.Format("{0}.tmp", assemblyFileFullname), true, AssemblyInfoReadCallback, packageInfo, projectInformation); } catch (Exception) { string message = "error while changing the assembly info"; errorMessage.Append(string.Format("{0}{1}", Environment.NewLine, message)); } //-----log LoggingManager.Instance.Logger.Debug(string.Format("new project id: {0}", packageInfo.NuSpecPackage.Metadata.Id)); LoggingManager.Instance.Logger.Debug(string.Format("new project version: {0}", packageInfo.NuSpecPackage.Metadata.Version)); LoggingManager.Instance.Logger.Debug(string.Format("new project title: {0}", packageInfo.NuSpecPackage.Metadata.Title)); LoggingManager.Instance.Logger.Debug(string.Format("new project authors: {0}", packageInfo.NuSpecPackage.Metadata.Authors)); LoggingManager.Instance.Logger.Debug(string.Format("new project description: {0}", packageInfo.NuSpecPackage.Metadata.Description)); LoggingManager.Instance.Logger.Debug(string.Format("new project language: {0}", packageInfo.NuSpecPackage.Metadata.Language)); LoggingManager.Instance.Logger.Debug(string.Format("new project copyright: {0}", packageInfo.NuSpecPackage.Metadata.Copyright)); } LoggingManager.Instance.Logger.Debug("save changes c++ project finished"); if (errorMessage.Length > 0) { errorMessage.Insert(0, "Could not save back the following values:"); throw new IOException(errorMessage.ToString()); } }
/// <summary> /// add all the item from the project that match one of the file includes /// </summary> private void AddNuSpecFilesCSharpVisualBasic(ProjectItems items, PackageInformation packageInfo, ProjectInformation projectInformation) { //-----get all the include able item here foreach (ProjectItem item in items) { //-----check if the item contains an item type property string itemType = ExtensionUtil.GetPropertyValue<string>(item.Properties, projectInformation.ItemType, null); if (!string.IsNullOrEmpty(itemType)) { object itemOutput = ExtensionUtil.GetPropertyValue<object>(item.Properties, projectInformation.ItemOutput, -1); if (itemOutput != null && itemOutput.ToString() != "0") { string itemFullPath = ExtensionUtil.GetPropertyValue<string>(item.Properties, "FullPath", null); if (!string.IsNullOrEmpty(itemFullPath)) { try { string itemRelativePath = itemFullPath.Remove(0, Path.GetDirectoryName(packageInfo.ProjectFullName).Length + 1).Replace("\\", "/"); if (!itemRelativePath.Contains("/")) itemRelativePath = string.Format("/{0}", itemRelativePath); LoggingManager.Instance.Logger.Debug(string.Format("checking item [{0}] for a possible fit", itemRelativePath)); FileInclude fileInclude = packageInfo.ProjectOptions.NuGetOptions.NuSpecOptions.Files.FileIncludes.FirstOrDefault(x => { string wildcard = string.Format("{0}/{1}", string.IsNullOrEmpty(x.Folder) ? "*" : x.Folder.Replace("\\", "/"), string.IsNullOrEmpty(x.Name) ? "*" : x.Name.Replace("\\", "/")); LoggingManager.Instance.Logger.Debug(string.Format("checking file include [{0}]", wildcard)); return StringUtil.MatchesWildcard(itemRelativePath, wildcard); }); if (fileInclude != null) { packageInfo.NuSpecPackage.Files.Add(new Xml.NuGet.NuSpec.File() { Source = itemFullPath, Target = fileInclude.Target }); LoggingManager.Instance.Logger.Debug(string.Format("added file [{0}] under [{1}]", itemFullPath, fileInclude.Target)); } else { LoggingManager.Instance.Logger.Info(string.Format("could not add file [{0}] because no fitting file include was found", itemFullPath)); } } catch (Exception ex) { if (ex is ThreadAbortException || ex is ThreadInterruptedException) throw; LoggingManager.Instance.Logger.Error(string.Format("error occured while adding the item [{0}]", itemFullPath), ex); } } } } //-----check sub items if any AddNuSpecFilesCSharpVisualBasic(item.ProjectItems, packageInfo, projectInformation); } }
/// <summary> /// calles when one of the ui elements has changed /// </summary> /// <param name="sender">sender of the event</param> /// <param name="e">event that was send</param> private void OnChange(object sender, EventArgs e) { if (!_blockEvents) { if (sender == _uiProjectIdentifiers) { _selectedProjectOptions = (Xml.Settings.Project.Options)_uiProjectIdentifiers.SelectedItem; _uiUseFromExistingNuSpec.Checked = _selectedProjectOptions != null ? _selectedProjectOptions.NuGetOptions.NuSpecOptions.Files.UseFromSettings : false; SetCheckboxImage(_uiUseFromExistingNuSpec); _uiCurrentType.DataSource = null; _uiFiles.DataSource = null; _project = null; if (_selectedProjectOptions != null) { _project = OptionsManager.Instance.SupportedProjectInformation.FirstOrDefault(x => x.Identifier == _selectedProjectOptions.Identifier); _uiCurrentType.DataSource = _project.ValidItemTypes; GuiUtil.SetItem(_selectedProjectOptions.NuGetOptions.NuSpecOptions.Files.FileIncludes, _uiFiles); } else { _uiFiles.DataSource = null; _uiCurrentType.DataSource = null; _project = null; } } else if (sender == _uiUseFromExistingNuSpec && _selectedProjectOptions != null) { _selectedProjectOptions.NuGetOptions.NuSpecOptions.Files.UseFromSettings = _uiUseFromExistingNuSpec.Checked; _uiFilesSettings.Enabled = !_uiUseFromExistingNuSpec.Checked; SetCheckboxImage(_uiUseFromExistingNuSpec); } else if (sender == _uiFiles) { _selectedFile = (FileInclude)_uiFiles.SelectedItem; _blockEvents = true; if (_selectedFile != null) { _uiCurrentType.SelectedItem = _selectedFile.Type; _uiCurrentType.Enabled = true; _uiCurrentFolder.Text = _selectedFile.Folder; _uiCurrentFolder.Enabled = true; _uiCurrentName.Text = _selectedFile.Name; _uiCurrentName.Enabled = true; _uiCurrentTarget.Text = _selectedFile.Target; _uiCurrentTarget.Enabled = true; _uiCurrentInclude.Checked = _selectedFile.Include; _uiCurrentInclude.Enabled = true; _uiRemove.Enabled = true; } else { _uiCurrentType.SelectedItem = null; _uiCurrentType.Enabled = false; _uiCurrentFolder.Text = null; _uiCurrentFolder.Enabled = false; _uiCurrentName.Text = null; _uiCurrentName.Enabled = false; _uiCurrentTarget.Text = null; _uiCurrentTarget.Enabled = false; _uiCurrentInclude.Checked = false; _uiCurrentInclude.Enabled = false; _uiRemove.Enabled = false; } _blockEvents = false; _uiApplyChanges.Enabled = false; } else if ((sender == _uiCurrentType || sender == _uiCurrentFolder || sender == _uiCurrentName || sender == _uiCurrentTarget || sender == _uiCurrentInclude) && _selectedFile != null) { _uiApplyChanges.Enabled = _selectedFile.Type != (string)_uiCurrentType.SelectedItem || _selectedFile.Folder != _uiCurrentFolder.Text || _selectedFile.Name != _uiCurrentName.Text || _selectedFile.Target != _uiCurrentTarget.Text || _selectedFile.Include != _uiCurrentInclude.Checked; } } }
/// <summary> /// prepares the project and stores all the needed information in local variables /// </summary> /// <param name="activeProject">project that is supposed to be deployed, must not be null</param> /// <returns>null if the preparation was successfull, otherwise the error string</returns> private void PreAnalyseProject(Project activeProject, out PackageInformation packageInfo, out ProjectInformation projectInformation) { LoggingManager.Instance.Logger.Debug("prepare project started"); if (activeProject == null) throw new ArgumentNullException("activeProject", "given project must not be null"); //-----assign incoming values packageInfo = null; projectInformation = null; //-----make sure the project is supported projectInformation = OptionsManager.Instance.SupportedProjectInformation.FirstOrDefault(p => activeProject.FullName.EndsWith(p.Extension)); if (projectInformation == null) throw new ProjectNoSupportedException("project not supported"); //-----make sure the project is not being deployed already try { if (Mutex.OpenExisting(activeProject.FullName.GetHashCode().ToString()) != null) throw new ProjectIsBeingDeployedException("project is already being deployed"); } catch (WaitHandleCannotBeOpenedException) { LoggingManager.Instance.Logger.Debug(string.Format("project {0} is currently not being deployed", activeProject.FullName)); } //-----get the project options, which will either be used or project based string configFullName; Enumerations.ProjectIdentifier identifier = projectInformation.Identifier; Xml.Settings.Project.Options projectOptions = OptionsManager.Instance.DetermineProjectConfiguration(activeProject, identifier, out configFullName, true); //-----create the deployment info packageInfo = new PackageInformation() { ProjectOptions = projectOptions, NuSpecPackage = new Xml.NuGet.NuSpec.Package() { Metadata = new Xml.NuGet.NuSpec.Metadata() }, Build = new BuildOptions(), ProjectFullName = activeProject.FullName, }; LoggingManager.Instance.Logger.Debug("prepare project finished"); }
/// <summary> /// determines the nuspec files to add from the project /// </summary> private void DetermineNuSpecFiles(Project activeProject, PackageInformation packageInfo, ProjectInformation projectInformation, Xml.Settings.General.NuGet.Target nuGetTarget) { LoggingManager.Instance.Logger.Debug("determine nuspec files started"); //-----add the assembly file packageInfo.NuSpecPackage.Files = new List<Xml.NuGet.NuSpec.File>(); packageInfo.NuSpecPackage.Files.Add(new Xml.NuGet.NuSpec.File() { Source = Path.Combine(packageInfo.Build.BuildPath, packageInfo.OutputFileName), Target = string.Format(@"lib\{0}", nuGetTarget.Name) }); //-----add the pdb file only if the debug useage is used and the value is known if (packageInfo.ProjectOptions.MsBuildOptions.Usage.DebugInfo.Useage != Enumerations.Useage.None) { string source = Path.Combine(packageInfo.Build.BuildPath, StringUtil.ReplaceLastOccurrence(packageInfo.OutputFileName, Resources.ExtensionDLL, Resources.ExtensionPDB)); Xml.NuGet.NuSpec.File pdbFile = new Xml.NuGet.NuSpec.File() { Source = source, Target = string.Format(@"lib\{0}", nuGetTarget.Name) }; packageInfo.Build.PdbFiles.Add(pdbFile); if (packageInfo.Build.DebugInfo == Resources.DebugInfoPdbOnly || packageInfo.Build.DebugInfo == Resources.DebugInfoFull) packageInfo.NuSpecPackage.Files.Add(pdbFile); } //HACK this is needed since VB does not implement the documentation file the way CS does it, need to find a work arround if (projectInformation.Identifier == Enumerations.ProjectIdentifier.CS) { //include documentation files if needed foreach (string documentationFileUrl in ExtensionUtil.GetFilenames(activeProject.ConfigurationManager.ActiveConfiguration, Definitions.Constants.DocumentaionOutputGroupCanonicalName)) { Xml.NuGet.NuSpec.File documentationFile = new Xml.NuGet.NuSpec.File() { Source = documentationFileUrl, Target = string.Format(@"lib\{0}", nuGetTarget.Name) }; if (packageInfo.Build.DocumentationFile == null) packageInfo.Build.DocumentationFile = documentationFile; packageInfo.NuSpecPackage.Files.Add(documentationFile); } } //-----get all the includeable item here if (packageInfo.ProjectOptions.NuGetOptions.NuSpecOptions.Files.FileIncludes.Count > 0) { if (projectInformation.Identifier == Enumerations.ProjectIdentifier.CS || projectInformation.Identifier == Enumerations.ProjectIdentifier.VB) AddNuSpecFilesCSharpVisualBasic(activeProject.ProjectItems, packageInfo, projectInformation); } LoggingManager.Instance.Logger.Debug("determine nuspec files finished"); }
/// <summary> /// determines the build option of the project from the active configuration /// </summary> /// <param name="activeProject">the active project that is to be deployed</param> /// <param name="packageInfo">package information to use</param> private void DetermineBuildOptions(Project activeProject, PackageInformation packageInfo, ProjectInformation projectInformation) { LoggingManager.Instance.Logger.Debug("determine build options started"); //-----build info packageInfo.Build.PlatformName = activeProject.ConfigurationManager.ActiveConfiguration.PlatformName; packageInfo.Build.ConfigurationName = activeProject.ConfigurationManager.ActiveConfiguration.ConfigurationName; packageInfo.Build.BuildPath = Path.Combine(Path.GetDirectoryName(packageInfo.ProjectFullName), ExtensionUtil.GetPropertyValue(activeProject.ConfigurationManager.ActiveConfiguration.Properties, projectInformation.OutputPath, "")); packageInfo.Build.BuildPath = packageInfo.Build.BuildPath.TrimEnd(Path.DirectorySeparatorChar); //-----optimize if (packageInfo.ProjectOptions.MsBuildOptions.Usage.Optimize.Useage != Enumerations.Useage.None) { if (packageInfo.ProjectOptions.MsBuildOptions.Usage.Optimize.Useage == Enumerations.Useage.Project) packageInfo.Build.Optimize = ExtensionUtil.GetPropertyValue<bool?>(activeProject.ConfigurationManager.ActiveConfiguration.Properties, projectInformation.Optimize, null); else packageInfo.Build.Optimize = packageInfo.ProjectOptions.MsBuildOptions.Usage.Optimize.Value; } //-----debug constants if (packageInfo.ProjectOptions.MsBuildOptions.Usage.DebugConstants.Useage != Enumerations.Useage.None) { if (packageInfo.ProjectOptions.MsBuildOptions.Usage.DebugConstants.Useage == Enumerations.Useage.Project) packageInfo.Build.DebugConstants = ExtensionUtil.GetPropertyValue<string>(activeProject.ConfigurationManager.ActiveConfiguration.Properties, projectInformation.DefineConstants, null); else packageInfo.Build.DebugConstants = packageInfo.ProjectOptions.MsBuildOptions.Usage.DebugConstants.Value; } //-----debug info if (packageInfo.ProjectOptions.MsBuildOptions.Usage.DebugInfo.Useage != Enumerations.Useage.None) { if (packageInfo.ProjectOptions.MsBuildOptions.Usage.DebugInfo.Useage == Enumerations.Useage.Project) packageInfo.Build.DebugInfo = ExtensionUtil.GetPropertyValue(activeProject.ConfigurationManager.ActiveConfiguration.Properties, projectInformation.DebugInfo, Resources.DebugInfoNone); else packageInfo.Build.DebugInfo = packageInfo.ProjectOptions.MsBuildOptions.Usage.DebugInfo.Value; } //-----log LoggingManager.Instance.Logger.Debug(string.Format("project platform: {0}", packageInfo.Build.PlatformName)); LoggingManager.Instance.Logger.Debug(string.Format("project configuration: {0}", packageInfo.Build.ConfigurationName)); LoggingManager.Instance.Logger.Debug(string.Format("project build path: {0}", packageInfo.Build.BuildPath)); LoggingManager.Instance.Logger.Debug(string.Format("project optimize: {0}", packageInfo.Build.Optimize)); LoggingManager.Instance.Logger.Debug(string.Format("project define constants: {0}", packageInfo.Build.DebugConstants)); LoggingManager.Instance.Logger.Debug(string.Format("project debug info: {0}", packageInfo.Build.DebugInfo)); LoggingManager.Instance.Logger.Debug("determine build options finished"); }
/// <summary> /// prepares the project so all the needed projects information are known /// <para>those information is stored in the given transit and container object</para> /// <para>this method is intended to be used after the prepare method has been called</para> /// </summary> /// <param name="activeProject">project to analyse, must not be null</param> /// <param name="packageInfo">transit object used to store the analysed information, must not be null</param> /// <param name="container">container object which contains information needed to analyse the project,</param> /// <returns>null if the analyse process was successfull, otherwise the error message is returned</returns> private void AnalyseProject(Project activeProject, PackageInformation packageInfo, ProjectInformation projectInformation) { LoggingManager.Instance.Logger.Debug("analsye project started"); if (activeProject == null) throw new ArgumentNullException("activeProject", "given project must not be null"); if (packageInfo == null) throw new ArgumentNullException("transit", "given transit must not be null"); if (projectInformation == null) throw new ArgumentNullException("projectInformation", "given projectInformation must not be null"); string monikerValue = null; //----- analyse the project dependent on the identifier AnalyseAssembly(activeProject, packageInfo, projectInformation, out monikerValue); //-----get the nuget target Xml.Settings.General.NuGet.Target nuGetTarget = null; try { nuGetTarget = OptionsManager.Instance.Configuration.GeneralOptions.NuGetOptions.Targets.First(tf => tf.Moniker == monikerValue); } catch (InvalidOperationException ex) { throw new UnkownMonikerException(monikerValue, string.Format("given moniker {0} is not known", monikerValue), ex); } ChangeNuSpec(activeProject, packageInfo); DetermineBuildOptions(activeProject, packageInfo, projectInformation); DetermineNuSpecFiles(activeProject, packageInfo, projectInformation, nuGetTarget); DetermineNuSpecDependecies(activeProject, packageInfo); CheckNuSpecFile(activeProject, packageInfo); ValidatePackageInformation(packageInfo); LoggingManager.Instance.Logger.Debug("analsye project finished"); }
/// <summary> /// analyses the c#/visualbasic projects /// </summary> /// <param name="activeProject">the active project that is to be deployed</param> /// <param name="project">project configuration to use</param> /// <returns>null if all information was gathered, otherwise the error string</returns> private string AnalyseAssembly(Project activeProject, PackageInformation packageInfo, ProjectInformation projectInformation, out string monikerValue) { LoggingManager.Instance.Logger.Debug("analyse assembly started"); //-----minimum info monikerValue = ExtensionUtil.GetPropertyValue<string>(activeProject.Properties, projectInformation.Moniker, null); packageInfo.OutputFileName = ExtensionUtil.GetPropertyValue<string>(activeProject.Properties, projectInformation.OutputFileName, null); if (!string.IsNullOrEmpty(packageInfo.OutputFileName) && !packageInfo.OutputFileName.EndsWith(Definitions.Constants.OutputFileExtension)) packageInfo.OutputFileName = string.Format("{0}{1}", packageInfo.OutputFileName, Definitions.Constants.OutputFileExtension); //-----nuspec info packageInfo.NuSpecPackage = new Xml.NuGet.NuSpec.Package() { Metadata = new Xml.NuGet.NuSpec.Metadata(), Files = new List<Xml.NuGet.NuSpec.File>() }; packageInfo.NuSpecPackage.Metadata.Id = ExtensionUtil.GetPropertyValue<string>(activeProject.Properties, projectInformation.Id, null); //-----find the assemblInfo string assemblyName = string.Format("{0}{1}", projectInformation.AssemblyName, projectInformation.FileExtension); ProjectItem assembly = ExtensionUtil.GetItem(assemblyName, activeProject.ProjectItems); if (assembly == null) { throw new FileNotFoundException(string.Format("assembly: {0} could not be found", assemblyName)); } //-----read the assemblyInfo string assemblyFileFullname = ExtensionUtil.GetPropertyValue<string>(assembly.Properties, Resources.PropertyFullpath, null); LoggingManager.Instance.Logger.Debug(string.Format("reading assemblyInfo: {0}", assemblyFileFullname)); try { IOUtil.ReadLinesStream(assemblyFileFullname, AssemblyInfoReadCallback, packageInfo, projectInformation); } catch (Exception ex) { throw new IOException("could not read assemblyinfo", ex); } //-----log LoggingManager.Instance.Logger.Debug(string.Format("project moniker: {0}", monikerValue)); LoggingManager.Instance.Logger.Debug(string.Format("project output filename: {0}", packageInfo.OutputFileName)); LoggingManager.Instance.Logger.Debug(string.Format("project id: {0}", packageInfo.NuSpecPackage.Metadata.Id)); LoggingManager.Instance.Logger.Debug(string.Format("project version: {0}", packageInfo.NuSpecPackage.Metadata.Version)); LoggingManager.Instance.Logger.Debug(string.Format("project title: {0}", packageInfo.NuSpecPackage.Metadata.Title)); LoggingManager.Instance.Logger.Debug(string.Format("project authors: {0}", packageInfo.NuSpecPackage.Metadata.Authors)); LoggingManager.Instance.Logger.Debug(string.Format("project description: {0}", packageInfo.NuSpecPackage.Metadata.Description)); LoggingManager.Instance.Logger.Debug(string.Format("project language: {0}", packageInfo.NuSpecPackage.Metadata.Language)); LoggingManager.Instance.Logger.Debug(string.Format("project copyright: {0}", packageInfo.NuSpecPackage.Metadata.Copyright)); LoggingManager.Instance.Logger.Debug("analyse assembly finished"); return null; }
/// <summary> /// tries to determine the project configuration orm the given project /// </summary> /// <param name="activeProject">project to be used</param> /// <param name="userChoice">the choice the user made when asked to set the configuration to project based</param> /// <returns>null if the configuration file was found, otherwise an error message</returns> private void PrepareProjectOptions(Project activeProject, ProjectInformation project) { LoggingManager.Instance.Logger.Debug("prepare project configruation started"); //-----check if the project should have a configuration _projectOption = OptionsManager.Instance.DetermineProjectConfiguration(activeProject, project.Identifier, out _configurationFullName, false); if (_projectOption == null) { string errorMessage = string.Format("Could not deserialize the project configuration file: {0}", _configurationFullName); LoggingManager.Instance.Logger.Error(errorMessage); MessageBox.Show(errorMessage); return; } Text = string.Format("Configuration for {0} Projects", project.Identifier); LoggingManager.Instance.Logger.Debug("prepare project configuration finished"); }