Browse Source

Handle being unable to read or update NuGet.Config.

pull/622/head
Matt Ward 11 years ago
parent
commit
56ef4ff293
  1. 1
      src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj
  2. 8
      src/AddIns/Misc/PackageManagement/Project/Src/Design/FakeSettings.cs
  3. 53
      src/AddIns/Misc/PackageManagement/Project/Src/MessageServiceExtensions.cs
  4. 13
      src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementOptionsView.xaml.cs
  5. 13
      src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementServices.cs
  6. 25
      src/AddIns/Misc/PackageManagement/Project/Src/RegisteredPackageSourceSettings.cs
  7. 12
      src/AddIns/Misc/PackageManagement/Project/Src/RegisteredPackageSourcesView.xaml.cs
  8. 8
      src/AddIns/Misc/PackageManagement/Project/Src/SettingsProvider.cs
  9. 1
      src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj
  10. 46
      src/AddIns/Misc/PackageManagement/Test/Src/Helpers/FakeReadOnlySettings.cs
  11. 40
      src/AddIns/Misc/PackageManagement/Test/Src/PackageManagementOptionsTests.cs
  12. 14
      src/AddIns/Misc/PackageManagement/Test/Src/SettingsProviderTests.cs

1
src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj

@ -224,6 +224,7 @@ @@ -224,6 +224,7 @@
<Compile Include="Src\IThreadSafePackageManagementEvents.cs" />
<Compile Include="Src\ManagePackagesUserPrompts.cs" />
<Compile Include="Src\ManagePackagesViewTitle.cs" />
<Compile Include="Src\MessageServiceExtensions.cs" />
<Compile Include="Src\MSBuildBasedProjectExtensions.cs" />
<Compile Include="Src\IPackageFromRepositoryExtensions.cs" />
<Compile Include="Src\NoPackageSourcesConfiguredException.cs" />

8
src/AddIns/Misc/PackageManagement/Project/Src/Design/FakeSettings.cs

@ -100,14 +100,14 @@ namespace ICSharpCode.PackageManagement.Design @@ -100,14 +100,14 @@ namespace ICSharpCode.PackageManagement.Design
return SavedSectionValueLists[RegisteredPackageSourceSettings.PackageSourcesSectionName];
}
public bool DeleteValue(string section, string key)
public virtual bool DeleteValue(string section, string key)
{
throw new NotImplementedException();
}
public List<string> SectionsDeleted = new List<string>();
public bool DeleteSection(string section)
public virtual bool DeleteSection(string section)
{
SectionsDeleted.Add(section);
return true;
@ -162,7 +162,7 @@ namespace ICSharpCode.PackageManagement.Design @@ -162,7 +162,7 @@ namespace ICSharpCode.PackageManagement.Design
return new List<KeyValuePair<string, string>>();
}
public void SetNestedValues(string section, string key, IList<KeyValuePair<string, string>> values)
public virtual void SetNestedValues(string section, string key, IList<KeyValuePair<string, string>> values)
{
throw new NotImplementedException();
}
@ -184,7 +184,7 @@ namespace ICSharpCode.PackageManagement.Design @@ -184,7 +184,7 @@ namespace ICSharpCode.PackageManagement.Design
}
}
public void SetPackageRestoreSetting(bool enabled)
public virtual void SetPackageRestoreSetting(bool enabled)
{
var items = new List<KeyValuePair<string, string>>();
items.Add(new KeyValuePair<string, string>("enabled", enabled.ToString()));

53
src/AddIns/Misc/PackageManagement/Project/Src/MessageServiceExtensions.cs

@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.IO;
using ICSharpCode.Core;
namespace ICSharpCode.PackageManagement
{
public static class MessageServiceExtensions
{
public static void ShowNuGetConfigFileSaveError(string message)
{
MessageService.ShowError(
String.Format("{0}{1}{1}{2}",
message,
Environment.NewLine,
GetSaveNuGetConfigFileErrorMessage()));
}
/// <summary>
/// Returns a non-Windows specific error message instead of the one NuGet returns.
///
/// NuGet returns a Windows specific error:
///
/// "DeleteSection" cannot be called on a NullSettings. This may be caused on account of
/// insufficient permissions to read or write to "%AppData%\NuGet\NuGet.config".
/// </summary>
static string GetSaveNuGetConfigFileErrorMessage()
{
string path = Path.Combine (
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"NuGet",
"NuGet.config");
return String.Format("Unable to read or write to \"{0}\".", path);
}
}
}

13
src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementOptionsView.xaml.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui;
namespace ICSharpCode.PackageManagement
@ -30,9 +31,15 @@ namespace ICSharpCode.PackageManagement @@ -30,9 +31,15 @@ namespace ICSharpCode.PackageManagement
public override bool SaveOptions()
{
var viewModel = DataContext as PackageManagementOptionsViewModel;
viewModel.SaveOptions();
return true;
try {
var viewModel = DataContext as PackageManagementOptionsViewModel;
viewModel.SaveOptions();
return true;
} catch (Exception ex) {
LoggingService.Error("Unable to save NuGet.config changes", ex);
MessageServiceExtensions.ShowNuGetConfigFileSaveError("Unable to save package management options.");
}
return false;
}
}
}

13
src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementServices.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using ICSharpCode.Core;
using ICSharpCode.PackageManagement.Scripting;
using NuGet;
@ -61,13 +62,23 @@ namespace ICSharpCode.PackageManagement @@ -61,13 +62,23 @@ namespace ICSharpCode.PackageManagement
static void InitializeCredentialProvider()
{
ISettings settings = Settings.LoadDefaultSettings(null, null, null);
ISettings settings = LoadSettings();
var packageSourceProvider = new PackageSourceProvider(settings);
var credentialProvider = new SettingsCredentialProvider(new SharpDevelopCredentialProvider(), packageSourceProvider);
HttpClient.DefaultCredentialProvider = credentialProvider;
}
static ISettings LoadSettings ()
{
try {
return Settings.LoadDefaultSettings(null, null, null);
} catch (Exception ex) {
LoggingService.Error("Unable to load NuGet.Config.", ex);
}
return NullSettings.Instance;
}
public static PackageManagementOptions Options {
get { return options; }
}

25
src/AddIns/Misc/PackageManagement/Project/Src/RegisteredPackageSourceSettings.cs

@ -21,6 +21,7 @@ using System.Collections.Generic; @@ -21,6 +21,7 @@ using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Project;
using NuGet;
@ -82,12 +83,26 @@ namespace ICSharpCode.PackageManagement @@ -82,12 +83,26 @@ namespace ICSharpCode.PackageManagement
public RegisteredPackageSources PackageSources {
get {
if (packageSources == null) {
ReadPackageSources();
TryReadPackageSources();
}
return packageSources;
}
}
void TryReadPackageSources()
{
try {
ReadPackageSources();
} catch (Exception ex) {
LoggingService.Warn("Unable to read NuGet.config file.", ex);
// Fallback to using the default package source only (nuget.org)
// and treat NuGet.config as read-only.
packageSourceProvider = CreatePackageSourceProvider(NullSettings.Instance);
ReadPackageSources();
}
}
void ReadPackageSources()
{
IEnumerable<PackageSource> savedPackageSources = packageSourceProvider.LoadPackageSources();
@ -119,6 +134,12 @@ namespace ICSharpCode.PackageManagement @@ -119,6 +134,12 @@ namespace ICSharpCode.PackageManagement
}
set {
activePackageSource = value;
if (settings is NullSettings) {
// NuGet failed to load settings so do not try to update them since this will fail.
return;
}
if (activePackageSource == null) {
RemoveActivePackageSourceSetting();
} else {
@ -148,7 +169,7 @@ namespace ICSharpCode.PackageManagement @@ -148,7 +169,7 @@ namespace ICSharpCode.PackageManagement
void SettingsChanged(object sender, EventArgs e)
{
settings = settingsProvider.LoadSettings();
packageSourceProvider = new PackageSourceProvider(settings);
packageSourceProvider = CreatePackageSourceProvider(settings);
ReadActivePackageSource();
ResetPackageSources();
}

12
src/AddIns/Misc/PackageManagement/Project/Src/RegisteredPackageSourcesView.xaml.cs

@ -17,6 +17,8 @@ @@ -17,6 +17,8 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.IO;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui;
namespace ICSharpCode.PackageManagement
@ -46,8 +48,14 @@ namespace ICSharpCode.PackageManagement @@ -46,8 +48,14 @@ namespace ICSharpCode.PackageManagement
public override bool SaveOptions()
{
ViewModel.Save();
return true;
try {
ViewModel.Save();
return true;
} catch (Exception ex) {
LoggingService.Error("Unable to save NuGet.config changes", ex);
MessageServiceExtensions.ShowNuGetConfigFileSaveError("Unable to save package source changes.");
}
return false;
}
}
}

8
src/AddIns/Misc/PackageManagement/Project/Src/SettingsProvider.cs

@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
using System;
using System.IO;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Project;
using NuGet;
@ -38,7 +39,12 @@ namespace ICSharpCode.PackageManagement @@ -38,7 +39,12 @@ namespace ICSharpCode.PackageManagement
public ISettings LoadSettings()
{
return LoadSettings(GetSolutionDirectory());
try {
return LoadSettings(GetSolutionDirectory());
} catch (Exception ex) {
LoggingService.Error("Unable to load NuGet.Config file.", ex);
}
return NullSettings.Instance;
}
string GetSolutionDirectory()

1
src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj

@ -112,6 +112,7 @@ @@ -112,6 +112,7 @@
<Compile Include="Src\Helpers\FakeCodeGenerator.cs" />
<Compile Include="Src\Helpers\FakeOperationAwarePackageRepository.cs" />
<Compile Include="Src\Helpers\FakePackageRepositoryWithConstraintProvider.cs" />
<Compile Include="Src\Helpers\FakeReadOnlySettings.cs" />
<Compile Include="Src\Helpers\FakeSelectProjectsService.cs" />
<Compile Include="Src\Helpers\FakeServiceBasedRepository.cs" />
<Compile Include="Src\Helpers\FakeSolutionPackageRepositoryFactory.cs" />

46
src/AddIns/Misc/PackageManagement/Test/Src/Helpers/FakeReadOnlySettings.cs

@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using ICSharpCode.PackageManagement.Design;
namespace PackageManagement.Tests.Helpers
{
public class FakeReadOnlySettings : FakeSettings
{
public override bool DeleteSection(string section)
{
throw new ApplicationException("DeleteSection called");
}
public override bool DeleteValue(string section, string key)
{
throw new ApplicationException("DeleteValue called");
}
public override void SetNestedValues(string section, string key, System.Collections.Generic.IList<System.Collections.Generic.KeyValuePair<string, string>> values)
{
throw new ApplicationException("SetNestedValues called");
}
public override void SetPackageRestoreSetting(bool enabled)
{
throw new ApplicationException("SetPackageRestoreSetting called");
}
}
}

40
src/AddIns/Misc/PackageManagement/Test/Src/PackageManagementOptionsTests.cs

@ -39,6 +39,13 @@ namespace PackageManagement.Tests @@ -39,6 +39,13 @@ namespace PackageManagement.Tests
SettingsProvider settingsProvider;
FakePackageManagementProjectService projectService;
[TearDown]
public void TearDown()
{
// This resets SettingsProvider.LoadDefaultSettings.
TestablePackageManagementOptions.CreateSettingsProvider(fakeSettings, projectService);
}
void CreateOptions()
{
CreateProperties();
@ -69,6 +76,12 @@ namespace PackageManagement.Tests @@ -69,6 +76,12 @@ namespace PackageManagement.Tests
options = new PackageManagementOptions(properties, settingsProvider);
}
void CreateOptions(Properties properties, ISettingsProvider provider)
{
CreateSettings();
options = new PackageManagementOptions(properties, provider);
}
void CreateSettingsProvider(FakeSettings fakeSettings)
{
projectService = new FakePackageManagementProjectService();
@ -559,5 +572,32 @@ namespace PackageManagement.Tests @@ -559,5 +572,32 @@ namespace PackageManagement.Tests
Assert.AreEqual(expectedInitialSources, actualInitialPackageSources);
Assert.AreEqual(new PackageSource[] { expectedActivePackageSource }, options.PackageSources);
}
[Test]
public void PackageSources_ReadOnlyNuGetConfigFile_DoesNotThrowException()
{
var settings = new FakeReadOnlySettings();
CreateOptions(settings);
int count = 0;
Assert.DoesNotThrow(() => count = options.PackageSources.Count);
Assert.AreEqual(1, count);
Assert.AreEqual(options.PackageSources[0], new PackageSource("https://www.nuget.org/api/v2/", "nuget.org"));
}
[Test]
public void PackageSources_UpdateActivePackageSourceWhenNuGetConfigAccessIsUnauthorized_DoesNotThrowException()
{
CreateProperties();
fakeSettings = new FakeReadOnlySettings();
CreateSettingsProvider(fakeSettings);
SettingsProvider.LoadDefaultSettings = (fileSystem, configFile, machineSettings) => {
throw new UnauthorizedAccessException();
};
CreateOptions(properties, settingsProvider);
var packageSource = new PackageSource("http://test.com");
Assert.DoesNotThrow(() => options.ActivePackageSource = packageSource);
}
}
}

14
src/AddIns/Misc/PackageManagement/Test/Src/SettingsProviderTests.cs

@ -76,5 +76,19 @@ namespace PackageManagement.Tests @@ -76,5 +76,19 @@ namespace PackageManagement.Tests
Assert.AreEqual(@"d:\projects\MyProject\.nuget", fileSystemUsedToLoadSettings.Root);
Assert.AreEqual(fakeSettings, settings);
}
[Test]
public void LoadSettings_NuGetSettingsThrowsUnauthorizedAccessException_ExceptionHandledAndSettingsNullObjectReturned()
{
fileSystemUsedToLoadSettings = new FakeFileSystem();
configFileUsedToLoadSettings = "configFile";
SettingsProvider.LoadDefaultSettings = (fileSystem, configFile, machineSettings) => {
throw new UnauthorizedAccessException();
};
ISettings settings = settingsProvider.LoadSettings();
Assert.IsInstanceOf<NullSettings>(settings);
}
}
}

Loading…
Cancel
Save