src/RepositorySettings.cs
// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. using System; using System.IO; using System.Collections.Generic; using System.Management.Automation; using System.Xml.Linq; using System.Linq; using static System.Environment; namespace Microsoft.PowerShell.PowerShellGet.RepositorySettings { /// <summary> /// Repository settings /// </summary> class RespositorySettings { /// <summary> /// Default file name for a settings file is 'psresourcerepository.config' /// Also, the user level setting file at '%APPDATA%\NuGet' always uses this name /// </summary> public static readonly string DefaultRepositoryFileName = "PSResourceRepository.xml"; public static readonly string DefaultRepositoryPath = Path.Combine(Environment.GetFolderPath(SpecialFolder.LocalApplicationData), "PowerShellGet"); //"%APPDATA%/PowerShellGet"; // c:\code\temp\repositorycache public static readonly string DefaultFullRepositoryPath = Path.Combine(DefaultRepositoryPath, DefaultRepositoryFileName); public RespositorySettings() { } /// <summary> /// Find a repository XML /// Returns: /// </summary> /// <param name="sectionName"></param> public bool FindRepositoryXML() { // Search in the designated location for the repository XML if (File.Exists(DefaultFullRepositoryPath)) { return true; } return false; } /// <summary> /// Create a new repository XML /// Returns: void /// </summary> /// <param name="sectionName"></param> public void CreateNewRepositoryXML() { // Check to see if the file already exists; if it does return if (FindRepositoryXML()) { return; } // create directory if needed if (!Directory.Exists(DefaultRepositoryPath)) { Directory.CreateDirectory(DefaultRepositoryPath); } // If the repository xml file doesn't exist yet, create one XDocument newRepoXML = new XDocument( new XElement("configuration") ); // Should be saved in: newRepoXML.Save(DefaultFullRepositoryPath); } /// <summary> /// Add a repository to the XML /// Returns: void /// </summary> /// <param name="sectionName"></param> public void Add(string repoName, Uri repoURL, int repoPriority, bool repoTrusted) { // Check to see if information we're trying to add to the repository is valid if (string.IsNullOrEmpty(repoName)) { // throw new ArgumentException(Resources.Argument_Cannot_Be_Null_Or_Empty, nameof(sectionName)); throw new ArgumentException("Repository name cannot be null or empty"); } if (string.IsNullOrEmpty(repoURL.ToString())) { // throw new ArgumentException(Resources.Argument_Cannot_Be_Null_Or_Empty, nameof(sectionName)); throw new ArgumentException("Repository URL cannot be null or empty"); } // Create will make a new XML if one doesn't already exist try { CreateNewRepositoryXML(); } catch { throw new ArgumentException("Was not able to successfully create xml"); } // Open file XDocument doc = XDocument.Load(DefaultFullRepositoryPath); // Check if what's being added already exists, if it does throw an error var node = doc.Descendants("Repository").Where(e => string.Equals(e.Attribute("Url").ToString(), repoURL.AbsoluteUri, StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); if (node != null) { throw new ArgumentException(String.Format("The PSResource Repository '{0}' already exists.", repoName)); } // Else, keep going // Get root of XDocument (XElement) var root = doc.Root; // Create new element XElement newElement = new XElement( "Repository", new XAttribute("Name", repoName), new XAttribute("Url", repoURL), new XAttribute("Priority", repoPriority), new XAttribute("Trusted", repoTrusted) ); root.Add(newElement); // Close the file root.Save(DefaultFullRepositoryPath); } /// <summary> /// Updates a repository name, URL, priority, or installation policy /// Returns: void /// </summary> public void Update(string repoName, Uri repoURL, int repoPriority, bool? repoTrusted) { // Check to see if information we're trying to add to the repository is valid if (string.IsNullOrEmpty(repoName)) { // throw new ArgumentException(Resources.Argument_Cannot_Be_Null_Or_Empty, nameof(sectionName)); throw new ArgumentException("Repository name cannot be null or empty"); } // We expect the xml to exist, if it doesn't user needs to register a repository try { FindRepositoryXML(); } catch { throw new ArgumentException("Was not able to successfully find xml. Try running 'Register-PSResourceRepository -PSGallery'"); } // Open file XDocument doc = XDocument.Load(DefaultFullRepositoryPath); // Check if what's being updated is actually there first var node = doc.Descendants("Repository").Where(e => string.Equals(e.Attribute("Name").Value, repoName, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault(); if (node == null) { throw new ArgumentException("Cannot find the repository because it does not exist. Try registering the repository using 'Register-PSResourceRepository'"); } // Else, keep going // Get root of XDocument (XElement) var root = doc.Root; if (repoURL != null) { node.Attribute("Url").Value = repoURL.AbsoluteUri; } if (repoPriority >= 0) { node.Attribute("Priority").Value = repoPriority.ToString(); } // false, setting to true // true, setting to false // false setting to false // true setting to true if (repoTrusted != null) { node.Attribute("Trusted").Value = repoTrusted.ToString(); } // Close the file root.Save(DefaultFullRepositoryPath); } /// <summary> /// Removes a repository from the XML /// Returns: void /// </summary> /// <param name="sectionName"></param> public void Remove(string[] repoNames) { // Check to see if information we're trying to add to the repository is valid if (repoNames == null || repoNames.Length == 0) { // throw new ArgumentException(Resources.Argument_Cannot_Be_Null_Or_Empty, nameof(sectionName)); throw new ArgumentException("Repository name cannot be null or empty"); } if (!FindRepositoryXML()) { throw new ArgumentException("Was not able to successfully find xml. Try running 'Register-PSResourceRepository -PSGallery'"); } // Open file XDocument doc = XDocument.Load(DefaultFullRepositoryPath); // Get root of XDocument (XElement) var root = doc.Root; foreach (var repo in repoNames) { // Check if what's being added doesn't already exist, throw an error var node = doc.Descendants("Repository").Where(e => string.Equals(e.Attribute("Name").Value, repo, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault(); if (node == null) { throw new ArgumentException(String.Format("Unable to find repository '{0}'. Use Get-PSResourceRepository to see all available repositories.", repo)); } // Remove item from file node.Remove(); } // Close the file root.Save(DefaultFullRepositoryPath); } public List<PSObject> Read(string[] repoNames) { // Can be null, will just retrieve all // Call FindRepositoryXML() [Create will make a new xml if one doesn't already exist] if (!FindRepositoryXML()) { throw new ArgumentException("Was not able to successfully find xml. Try running 'Register-PSResourceRepository -PSGallery'"); } // Open file XDocument doc = XDocument.Load(DefaultFullRepositoryPath); var foundRepos = new List<PSObject>(); if (repoNames == null || !repoNames.Any() || string.Equals(repoNames[0], "*") || repoNames[0] == null) { // array is null and we will list all repositories // iterate through the doc foreach (var repo in doc.Descendants("Repository")) { PSObject repoAsPSObject = new PSObject(); repoAsPSObject.Members.Add(new PSNoteProperty("Name", repo.Attribute("Name").Value)); repoAsPSObject.Members.Add(new PSNoteProperty("Url", repo.Attribute("Url").Value)); repoAsPSObject.Members.Add(new PSNoteProperty("Trusted", repo.Attribute("Trusted").Value)); repoAsPSObject.Members.Add(new PSNoteProperty("Priority", repo.Attribute("Priority").Value)); foundRepos.Add(repoAsPSObject); } } else { foreach (var repo in repoNames) { // Check to see if repository exists // need to fix the case sensitivity var node = doc.Descendants("Repository").Where(e => string.Equals(e.Attribute("Name").Value, repo, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault(); if (node != null) { PSObject repoAsPSObject = new PSObject(); repoAsPSObject.Members.Add(new PSNoteProperty("Name", node.Attribute("Name").Value)); repoAsPSObject.Members.Add(new PSNoteProperty("Url", node.Attribute("Url").Value)); repoAsPSObject.Members.Add(new PSNoteProperty("Trusted", node.Attribute("Trusted").Value)); repoAsPSObject.Members.Add(new PSNoteProperty("Priority", node.Attribute("Priority").Value)); foundRepos.Add(repoAsPSObject); } } } // Sort by priority, then by repo name // foundRepos.Sort((x, y) => ( Int32.Parse((x.Members.Where(m => m.Name.Equals("Priority"))).FirstOrDefault().Value.ToString()).CompareTo( Int32.Parse((y.Members.Where(m2 => m2.Name.Equals("Priority"))).FirstOrDefault().Value.ToString()) ) )); var reposToReturn = foundRepos.OrderBy(x => (Int32.Parse((x.Members.Where(m => m.Name.Equals("Priority"))).FirstOrDefault().Value.ToString()))) .ThenBy(x => (x.Members.Where(m => m.Name.Equals("Name"))).FirstOrDefault().Value.ToString()); return reposToReturn.ToList(); } } } |