diff --git a/src/code/RepositorySettings.cs b/src/code/RepositorySettings.cs index b622bbe8e..dec5d2d15 100644 --- a/src/code/RepositorySettings.cs +++ b/src/code/RepositorySettings.cs @@ -98,7 +98,7 @@ public static PSRepositoryInfo Add(string repoName, Uri repoUri, int repoPriorit XElement newElement = new XElement( "Repository", new XAttribute("Name", repoName), - new XAttribute("Uri", repoUri), + new XAttribute("Url", repoUri), new XAttribute("Priority", repoPriority), new XAttribute("Trusted", repoTrusted) ); @@ -139,17 +139,60 @@ public static PSRepositoryInfo Update(string repoName, Uri repoUri, int repoPrio throw new ArgumentException("Cannot find the repository because it does not exist. Try registering the repository using 'Register-PSResourceRepository'"); } + // Check that repository node we are attempting to update has all required attributes: Name, Url (or Uri), Priority, Trusted. + // Name attribute is already checked for in FindRepositoryElement() + + if (node.Attribute("Priority") == null) + { + throw new ArgumentException("Repository element does not contain neccessary 'Priority' attribute, in file located at path: {0}. Fix this in your file and run again.", FullRepositoryPath); + } + + if (node.Attribute("Trusted") == null) + { + throw new ArgumentException("Repository element does not contain neccessary 'Trusted' attribute, in file located at path: {0}. Fix this in your file and run again.", FullRepositoryPath); + } + + bool urlAttributeExists = node.Attribute("Url") != null; + bool uriAttributeExists = node.Attribute("Uri") != null; + if (!urlAttributeExists && !uriAttributeExists) + { + throw new ArgumentException("Repository element does not contain neccessary 'Url' attribute (or alternatively 'Uri' attribute), in file located at path: {0}. Fix this in your file and run again.", FullRepositoryPath); + } + // Else, keep going // Get root of XDocument (XElement) var root = doc.Root; - // A null Uri value passed in signifies the Uri was not attempted to be set. + // A null Uri (or Url) value passed in signifies the Uri was not attempted to be set. // So only set Uri attribute if non-null value passed in for repoUri + + // determine if existing repository node (which we wish to update) had Url to Uri attribute + Uri thisUrl = null; if (repoUri != null) { - node.Attribute("Uri").Value = repoUri.AbsoluteUri; + if (urlAttributeExists) + { + node.Attribute("Url").Value = repoUri.AbsoluteUri; + // Create Uri from node Uri attribute to create PSRepositoryInfo item to return. + if (!Uri.TryCreate(node.Attribute("Url").Value, UriKind.Absolute, out thisUrl)) + { + throw new PSInvalidOperationException(String.Format("Unable to read incorrectly formatted Url for repo {0}", repoName)); + } + } + else + { + // Uri attribute exists + node.Attribute("Uri").Value = repoUri.AbsoluteUri; + if (!Uri.TryCreate(node.Attribute("Uri").Value, UriKind.Absolute, out thisUrl)) + { + throw new PSInvalidOperationException(String.Format("Unable to read incorrectly formatted Uri for repo {0}", repoName)); + } + } } + + + // A negative Priority value passed in signifies the Priority value was not attempted to be set. // So only set Priority attribute if non-null value passed in for repoPriority if (repoPriority >= 0) @@ -187,12 +230,6 @@ public static PSRepositoryInfo Update(string repoName, Uri repoUri, int repoPrio } } - // Create Uri from node Uri attribute to create PSRepositoryInfo item to return. - if (!Uri.TryCreate(node.Attribute("Uri").Value, UriKind.Absolute, out Uri thisUri)) - { - throw new PSInvalidOperationException(String.Format("Unable to read incorrectly formatted Uri for repo {0}", repoName)); - } - // Create CredentialInfo based on new values or whether it was empty to begin with PSCredentialInfo thisCredentialInfo = null; if (node.Attribute(PSCredentialInfo.VaultNameAttribute)?.Value != null && @@ -204,7 +241,7 @@ public static PSRepositoryInfo Update(string repoName, Uri repoUri, int repoPrio } updatedRepo = new PSRepositoryInfo(repoName, - thisUri, + thisUrl, Int32.Parse(node.Attribute("Priority").Value), Boolean.Parse(node.Attribute("Trusted").Value), thisCredentialInfo); @@ -257,9 +294,32 @@ public static List Remove(string[] repoNames, out string[] err { repoCredentialInfo = new PSCredentialInfo(node.Attribute("VaultName").Value, node.Attribute("SecretName").Value); } + + if (node.Attribute("Priority") == null) + { + tempErrorList.Add(String.Format("Repository element does not contain neccessary 'Priority' attribute, in file located at path: {0}. Fix this in your file and run again.", FullRepositoryPath)); + continue; + } + + if (node.Attribute("Trusted") == null) + { + tempErrorList.Add(String.Format("Repository element does not contain neccessary 'Trusted' attribute, in file located at path: {0}. Fix this in your file and run again.", FullRepositoryPath)); + continue; + } + + // determine if repo had Url or Uri (less likely) attribute + bool urlAttributeExists = node.Attribute("Url") != null; + bool uriAttributeExists = node.Attribute("Uri") != null; + if (!urlAttributeExists && !uriAttributeExists) + { + tempErrorList.Add(String.Format("Repository element does not contain neccessary 'Url' or equivalent 'Uri' attribute (it must contain one per Repository), in file located at path: {0}. Fix this in your file and run again.", FullRepositoryPath)); + continue; + } + + string attributeUrlUriName = urlAttributeExists ? "Url" : "Uri"; removedRepos.Add( new PSRepositoryInfo(repo, - new Uri(node.Attribute("Uri").Value), + new Uri(node.Attribute(attributeUrlUriName).Value), Int32.Parse(node.Attribute("Priority").Value), Boolean.Parse(node.Attribute("Trusted").Value), repoCredentialInfo)); @@ -290,17 +350,58 @@ public static List Read(string[] repoNames, out string[] error throw new PSInvalidOperationException(String.Format("Loading repository store failed: {0}", e.Message)); } - if (repoNames == null || !repoNames.Any() || string.Equals(repoNames[0], "*") || repoNames[0] == null) + if (repoNames == null || repoNames.Length == 0 || string.Equals(repoNames[0], "*") || repoNames[0] == null) { // Name array or single value is null so we will list all repositories registered // iterate through the doc foreach (XElement repo in doc.Descendants("Repository")) { - if (!Uri.TryCreate(repo.Attribute("Uri").Value, UriKind.Absolute, out Uri thisUri)) + if (repo.Attribute("Name") == null) + { + tempErrorList.Add(String.Format("Repository element does not contain neccessary 'Name' attribute, in file located at path: {0}. Fix this in your file and run again.", FullRepositoryPath)); + continue; + } + + if (repo.Attribute("Priority") == null) { - tempErrorList.Add(String.Format("Unable to read incorrectly formatted Uri for repo {0}", repo.Attribute("Name").Value)); + tempErrorList.Add(String.Format("Repository element does not contain neccessary 'Priority' attribute, in file located at path: {0}. Fix this in your file and run again.", FullRepositoryPath)); continue; } + + if (repo.Attribute("Trusted") == null) + { + tempErrorList.Add(String.Format("Repository element does not contain neccessary 'Trusted' attribute, in file located at path: {0}. Fix this in your file and run again.", FullRepositoryPath)); + continue; + } + + bool urlAttributeExists = repo.Attribute("Url") != null; + bool uriAttributeExists = repo.Attribute("Uri") != null; + // case: neither Url nor Uri attributes exist + if (!urlAttributeExists && !uriAttributeExists) + { + tempErrorList.Add(String.Format("Repository element does not contain neccessary 'Url' or equivalent 'Uri' attribute (it must contain one), in file located at path: {0}. Fix this in your file and run again.", FullRepositoryPath)); + continue; + } + + Uri thisUrl = null; + // case: either attribute Uri or Url exists + // TODO: do we only allow both to exist, across repositories? (i.e if a file has Uri attribute for one repo and Url attribute for another --> is that invalid?) + if (urlAttributeExists) + { + if (!Uri.TryCreate(repo.Attribute("Url").Value, UriKind.Absolute, out thisUrl)) + { + tempErrorList.Add(String.Format("Unable to read incorrectly formatted Url for repo {0}", repo.Attribute("Name").Value)); + continue; + } + } + else if (uriAttributeExists) + { + if (!Uri.TryCreate(repo.Attribute("Uri").Value, UriKind.Absolute, out thisUrl)) + { + tempErrorList.Add(String.Format("Unable to read incorrectly formatted Uri for repo {0}", repo.Attribute("Name").Value)); + continue; + } + } PSCredentialInfo thisCredentialInfo; string credentialInfoErrorMessage = $"Repository {repo.Attribute("Name").Value} has invalid CredentialInfo. {PSCredentialInfo.VaultNameAttribute} and {PSCredentialInfo.SecretNameAttribute} should both be present and non-empty"; @@ -335,7 +436,7 @@ public static List Read(string[] repoNames, out string[] error } PSRepositoryInfo currentRepoItem = new PSRepositoryInfo(repo.Attribute("Name").Value, - thisUri, + thisUrl, Int32.Parse(repo.Attribute("Priority").Value), Boolean.Parse(repo.Attribute("Trusted").Value), thisCredentialInfo); @@ -350,15 +451,50 @@ public static List Read(string[] repoNames, out string[] error bool repoMatch = false; WildcardPattern nameWildCardPattern = new WildcardPattern(repo, WildcardOptions.IgnoreCase); - foreach (var node in doc.Descendants("Repository").Where(e => nameWildCardPattern.IsMatch(e.Attribute("Name").Value))) + foreach (var node in doc.Descendants("Repository").Where(e => e.Attribute("Name") != null && nameWildCardPattern.IsMatch(e.Attribute("Name").Value))) { - repoMatch = true; - if (!Uri.TryCreate(node.Attribute("Uri").Value, UriKind.Absolute, out Uri thisUri)) + if (node.Attribute("Priority") == null) { - //debug statement - tempErrorList.Add(String.Format("Unable to read incorrectly formatted Uri for repo {0}", node.Attribute("Name").Value)); + tempErrorList.Add(String.Format("Repository element does not contain neccessary 'Priority' attribute, in file located at path: {0}. Fix this in your file and run again.", FullRepositoryPath)); continue; } + + if (node.Attribute("Trusted") == null) + { + tempErrorList.Add(String.Format("Repository element does not contain neccessary 'Trusted' attribute, in file located at path: {0}. Fix this in your file and run again.", FullRepositoryPath)); + continue; + } + + repoMatch = true; + bool urlAttributeExists = node.Attribute("Url") != null; + bool uriAttributeExists = node.Attribute("Uri") != null; + + // case: neither Url nor Uri attributes exist + if (!urlAttributeExists && !uriAttributeExists) + { + tempErrorList.Add(String.Format("Repository element does not contain neccessary 'Url' or equivalent 'Uri' attribute (it must contain one), in file located at path: {0}. Fix this in your file and run again.", FullRepositoryPath)); + continue; + } + + Uri thisUrl = null; + // case: either attribute Uri or Url exists + // TODO: do we only allow both to exist, across repositories? (i.e if a file has Uri attribute for one repo and Url attribute for another --> is that invalid?) + if (urlAttributeExists) + { + if (!Uri.TryCreate(node.Attribute("Url").Value, UriKind.Absolute, out thisUrl)) + { + tempErrorList.Add(String.Format("Unable to read incorrectly formatted Url for repo {0}", node.Attribute("Name").Value)); + continue; + } + } + else if (uriAttributeExists) + { + if (!Uri.TryCreate(node.Attribute("Uri").Value, UriKind.Absolute, out thisUrl)) + { + tempErrorList.Add(String.Format("Unable to read incorrectly formatted Uri for repo {0}", node.Attribute("Name").Value)); + continue; + } + } PSCredentialInfo thisCredentialInfo; string credentialInfoErrorMessage = $"Repository {node.Attribute("Name").Value} has invalid CredentialInfo. {PSCredentialInfo.VaultNameAttribute} and {PSCredentialInfo.SecretNameAttribute} should both be present and non-empty"; @@ -393,7 +529,7 @@ public static List Read(string[] repoNames, out string[] error } PSRepositoryInfo currentRepoItem = new PSRepositoryInfo(node.Attribute("Name").Value, - thisUri, + thisUrl, Int32.Parse(node.Attribute("Priority").Value), Boolean.Parse(node.Attribute("Trusted").Value), thisCredentialInfo); @@ -421,7 +557,8 @@ public static List Read(string[] repoNames, out string[] error private static XElement FindRepositoryElement(XDocument doc, string name) { return doc.Descendants("Repository").Where( - e => string.Equals( + e => e.Attribute("Name") != null && + string.Equals( e.Attribute("Name").Value, name, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();