Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
ModuleSpecification.cs385 linesDownload Raw Back to Modules
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System;5using System.Collections;6using System.Collections.Generic;7using System.Management.Automation;8using System.Management.Automation.Internal;9using System.Management.Automation.Language;10using System.Text;11 12using Dbg = System.Management.Automation.Diagnostics;13 14//15// Now define the set of commands for manipulating modules.16//17 18namespace Microsoft.PowerShell.Commands19{20    #region Module Specification class21 22    /// <summary>23    /// Represents module specification written in a module manifest (i.e. in RequiredModules member/field).24    ///25    /// Module manifest allows 2 forms of module specification:26    /// 1. string - module name27    /// 2. hashtable - [string]ModuleName (required) + [Version]ModuleVersion/RequiredVersion (required) + [Guid]GUID (optional)28    ///29    /// so we have a constructor that takes a string and a constructor that takes a hashtable30    /// (so that LanguagePrimitives.ConvertTo can cast a string or a hashtable to this type)31    /// </summary>32    public class ModuleSpecification33    {34        /// <summary>35        /// Default constructor.36        /// </summary>37        public ModuleSpecification()38        {39        }40 41        /// <summary>42        /// Construct a module specification from the module name.43        /// </summary>44        /// <param name="moduleName">The module name.</param>45        public ModuleSpecification(string moduleName)46        {47            ArgumentException.ThrowIfNullOrEmpty(moduleName);48 49            this.Name = moduleName;50 51            // Alias name of miniumVersion52            this.Version = null;53            this.RequiredVersion = null;54            this.MaximumVersion = null;55            this.Guid = null;56        }57 58        /// <summary>59        /// Construct a module specification from a hashtable.60        /// Keys can be ModuleName, ModuleVersion, and Guid.61        /// ModuleName must be convertible to <see cref="string"/>.62        /// ModuleVersion must be convertible to <see cref="Version"/>.63        /// Guid must be convertible to <see cref="Guid"/>.64        /// </summary>65        /// <param name="moduleSpecification">The module specification as a hashtable.</param>66        public ModuleSpecification(Hashtable moduleSpecification)67        {68            ArgumentNullException.ThrowIfNull(moduleSpecification);69 70            var exception = ModuleSpecificationInitHelper(this, moduleSpecification);71            if (exception != null)72            {73                throw exception;74            }75        }76 77        /// <summary>78        /// Initialize moduleSpecification from hashtable. Return exception object, if hashtable cannot be converted.79        /// Return null, in the success case.80        /// </summary>81        /// <param name="moduleSpecification">Object to initialize.</param>82        /// <param name="hashtable">Contains info about object to initialize.</param>83        /// <returns></returns>84        internal static Exception ModuleSpecificationInitHelper(ModuleSpecification moduleSpecification, Hashtable hashtable)85        {86            StringBuilder badKeys = new StringBuilder();87            try88            {89                foreach (DictionaryEntry entry in hashtable)90                {91                    string field = entry.Key.ToString();92 93                    if (field.Equals("ModuleName", StringComparison.OrdinalIgnoreCase))94                    {95                        moduleSpecification.Name = LanguagePrimitives.ConvertTo<string>(entry.Value);96                    }97                    else if (field.Equals("ModuleVersion", StringComparison.OrdinalIgnoreCase))98                    {99                        moduleSpecification.Version = LanguagePrimitives.ConvertTo<Version>(entry.Value);100                    }101                    else if (field.Equals("RequiredVersion", StringComparison.OrdinalIgnoreCase))102                    {103                        moduleSpecification.RequiredVersion = LanguagePrimitives.ConvertTo<Version>(entry.Value);104                    }105                    else if (field.Equals("MaximumVersion", StringComparison.OrdinalIgnoreCase))106                    {107                        moduleSpecification.MaximumVersion = LanguagePrimitives.ConvertTo<string>(entry.Value);108                        ModuleCmdletBase.GetMaximumVersion(moduleSpecification.MaximumVersion);109                    }110                    else if (field.Equals("GUID", StringComparison.OrdinalIgnoreCase))111                    {112                        moduleSpecification.Guid = LanguagePrimitives.ConvertTo<Guid?>(entry.Value);113                    }114                    else115                    {116                        if (badKeys.Length > 0)117                        {118                            badKeys.Append(", ");119                        }120 121                        badKeys.Append('\'');122                        badKeys.Append(entry.Key.ToString());123                        badKeys.Append('\'');124                    }125                }126            }127            // catch all exceptions here, we are going to report them via return value.128            // Example of caught exception: one of conversions to Version failed.129            catch (Exception e)130            {131                return e;132            }133 134            string message;135            if (badKeys.Length != 0)136            {137                message = StringUtil.Format(Modules.InvalidModuleSpecificationMember, "ModuleName, ModuleVersion, RequiredVersion, GUID", badKeys);138                return new ArgumentException(message);139            }140 141            if (string.IsNullOrEmpty(moduleSpecification.Name))142            {143                message = StringUtil.Format(Modules.RequiredModuleMissingModuleName);144                return new MissingMemberException(message);145            }146 147            if (moduleSpecification.RequiredVersion == null && moduleSpecification.Version == null && moduleSpecification.MaximumVersion == null)148            {149                message = StringUtil.Format(Modules.RequiredModuleMissingModuleVersion);150                return new MissingMemberException(message);151            }152 153            if (moduleSpecification.RequiredVersion != null && moduleSpecification.Version != null)154            {155                message = StringUtil.Format(SessionStateStrings.GetContent_TailAndHeadCannotCoexist, "ModuleVersion", "RequiredVersion");156                return new ArgumentException(message);157            }158 159            if (moduleSpecification.RequiredVersion != null && moduleSpecification.MaximumVersion != null)160            {161                message = StringUtil.Format(SessionStateStrings.GetContent_TailAndHeadCannotCoexist, "MaximumVersion", "RequiredVersion");162                return new ArgumentException(message);163            }164 165            return null;166        }167 168        internal string GetRequiredModuleNotFoundVersionMessage()169        {170            if (RequiredVersion is not null)171            {172                return StringUtil.Format(173                    Modules.RequiredModuleNotFoundRequiredVersion,174                    Name,175                    RequiredVersion);176            }177 178            bool hasVersion = Version is not null;179            bool hasMaximumVersion = MaximumVersion is not null;180 181            if (hasVersion && hasMaximumVersion)182            {183                return StringUtil.Format(184                    Modules.RequiredModuleNotFoundModuleAndMaximumVersion,185                    Name,186                    Version,187                    MaximumVersion);188            }189 190            if (hasVersion)191            {192                return StringUtil.Format(193                    Modules.RequiredModuleNotFoundModuleVersion,194                    Name,195                    Version);196            }197 198            if (hasMaximumVersion)199            {200                return StringUtil.Format(201                    Modules.RequiredModuleNotFoundMaximumVersion,202                    Name,203                    MaximumVersion);204            }205 206            return StringUtil.Format(207                Modules.RequiredModuleNotFoundWithoutVersion,208                Name);209        }210 211        internal ModuleSpecification(PSModuleInfo moduleInfo)212        {213            ArgumentNullException.ThrowIfNull(moduleInfo);214 215            this.Name = moduleInfo.Name;216            this.Version = moduleInfo.Version;217            this.Guid = moduleInfo.Guid;218        }219 220        /// <summary>221        /// Implements ToString() for a module specification. If the specification222        /// just contains a Name, then that is returned as is. Otherwise, the object is223        /// formatted as a PowerSHell hashtable.224        /// </summary>225        /// <returns></returns>226        public override string ToString()227        {228            if (Guid == null && Version == null && RequiredVersion == null && MaximumVersion == null)229            {230                return Name;231            }232 233            var moduleSpecBuilder = new StringBuilder();234 235            moduleSpecBuilder.Append("@{ ModuleName = '").Append(Name).Append('\'');236 237            if (Guid != null)238            {239                moduleSpecBuilder.Append("; Guid = '{").Append(Guid).Append("}' ");240            }241 242            if (RequiredVersion != null)243            {244                moduleSpecBuilder.Append("; RequiredVersion = '").Append(RequiredVersion).Append('\'');245            }246            else247            {248                if (Version != null)249                {250                    moduleSpecBuilder.Append("; ModuleVersion = '").Append(Version).Append('\'');251                }252 253                if (MaximumVersion != null)254                {255                    moduleSpecBuilder.Append("; MaximumVersion = '").Append(MaximumVersion).Append('\'');256                }257            }258 259            moduleSpecBuilder.Append(" }");260 261            return moduleSpecBuilder.ToString();262        }263 264        /// <summary>265        /// Parse the specified string into a ModuleSpecification object.266        /// </summary>267        /// <param name="input">The module specification string.</param>268        /// <param name="result">The ModuleSpecification object.</param>269        /// <returns></returns>270        public static bool TryParse(string input, out ModuleSpecification result)271        {272            result = null;273            try274            {275                Hashtable hashtable;276                if (Parser.TryParseAsConstantHashtable(input, out hashtable))277                {278                    result = new ModuleSpecification(hashtable);279                    return true;280                }281            }282            catch283            {284                // Ignoring the exceptions to return false285            }286 287            return false;288        }289 290        /// <summary>291        /// Copy the module specification while normalizing the name292        /// so that paths become absolute and use the right directory separators.293        /// </summary>294        /// <param name="context">The current execution context. Used for path normalization.</param>295        /// <param name="basePath">The base path where a relative path should be interpreted with respect to.</param>296        /// <returns>A fresh module specification object with the name normalized for use internally.</returns>297        internal ModuleSpecification WithNormalizedName(ExecutionContext context, string basePath)298        {299            // Save allocating a new module spec if we don't need to change anything300            if (!ModuleIntrinsics.IsModuleNamePath(Name))301            {302                return this;303            }304 305            return new ModuleSpecification()306            {307                Guid = Guid,308                MaximumVersion = MaximumVersion,309                Version = Version,310                RequiredVersion = RequiredVersion,311                Name = ModuleIntrinsics.NormalizeModuleName(Name, basePath, context)312            };313        }314 315        /// <summary>316        /// The module name.317        /// </summary>318        public string Name { get; internal set; }319 320        /// <summary>321        /// The module GUID, if specified.322        /// </summary>323        public Guid? Guid { get; internal set; }324 325        /// <summary>326        /// The module version number if specified, otherwise null.327        /// </summary>328        public Version Version { get; internal set; }329 330        /// <summary>331        /// The module maxVersion number if specified, otherwise null.332        /// </summary>333        public string MaximumVersion { get; internal set; }334 335        /// <summary>336        /// The exact version of the module if specified, otherwise null.337        /// </summary>338        public Version RequiredVersion { get; internal set; }339    }340 341    /// <summary>342    /// Compares two ModuleSpecification objects for equality.343    /// </summary>344    internal class ModuleSpecificationComparer : IEqualityComparer<ModuleSpecification>345    {346        /// <summary>347        /// Check if two module specifications are property-wise equal.348        /// </summary>349        /// <param name="x"></param>350        /// <param name="y"></param>351        /// <returns>True if the specifications are equal, false otherwise.</returns>352        public bool Equals(ModuleSpecification x, ModuleSpecification y)353        {354            if (x == y)355            {356                return true;357            }358 359            return x != null && y != null360                && string.Equals(x.Name, y.Name, StringComparison.OrdinalIgnoreCase)361                && Guid.Equals(x.Guid, y.Guid)362                && Version.Equals(x.RequiredVersion, y.RequiredVersion)363                && Version.Equals(x.Version, y.Version)364                && string.Equals(x.MaximumVersion, y.MaximumVersion);365        }366 367        /// <summary>368        /// Get a property-based hashcode for a ModuleSpecification object.369        /// </summary>370        /// <param name="obj">The module specification for the object.</param>371        /// <returns>A hashcode that is always the same for any module specification with the same properties.</returns>372        public int GetHashCode(ModuleSpecification obj)373        {374            if (obj == null)375            {376                return 0;377            }378 379            return HashCode.Combine(obj.Name, obj.Guid, obj.RequiredVersion, obj.Version, obj.MaximumVersion);380        }381    }382 383    #endregion384}385