Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix project settings file getting corrupted #652

Closed
Closed
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 50 additions & 4 deletions source/VersionHandlerImpl/src/ProjectSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ public enum SettingsLocation {
/// This is a UnityEditor.EditorPrefs compatible interface.
/// </summary>
public interface ISettings {

/// <summary>
/// Determine whether setting are out of sync and needs to be persisted or not
/// </summary>
bool IsModified { get; set; }

/// <summary>
/// Set an int property.
/// </summary>
Expand Down Expand Up @@ -131,6 +137,13 @@ public interface ISettings {
/// Default implementation of system wide settings.
/// </summary>
internal class EditorSettings : ISettings {

/// <summary>
/// Determine whether setting are out of sync and needs to be persisted or not
/// Always false as editor settings are always persisted by Unity
/// </summary>
public bool IsModified { get { return false; } set { } }

/// <summary>
/// Set a int property.
/// </summary>
Expand Down Expand Up @@ -224,6 +237,12 @@ internal class EditorSettings : ISettings {
/// In-memory settings storage.
/// </summary>
internal class InMemorySettings : ISettings {

/// <summary>
/// Determine whether setting are out of sync and needs to be persisted or not
/// </summary>
public bool IsModified { get; set; }

/// <summary>
/// In-memory storage for settings.
/// </summary>
Expand All @@ -234,8 +253,14 @@ internal class InMemorySettings : ISettings {
/// </summary>
/// <param name="name">Name of the value.</param>
/// <param name="value">Value to set.</param>
private void Set<T>(string name, T value) {
settings[name] = value.ToString();
private void Set<T>(string name, T value)
{
string stringValue = value.ToString();

if (!settings.ContainsKey(name) || settings[name] != stringValue)
IsModified = true;
AliAlbarrak marked this conversation as resolved.
Show resolved Hide resolved

settings[name] = stringValue;
}

/// <summary>
Expand Down Expand Up @@ -333,6 +358,7 @@ internal class InMemorySettings : ISettings {
/// <param name="name">Name of the value to delete.</param>
public void DeleteKey(string name) {
settings.Remove(name);
IsModified = true;
}

/// <summary>
Expand All @@ -347,6 +373,16 @@ internal class InMemorySettings : ISettings {
/// either application or project level settings based upon the UseProjectSettings flag.
/// </summary>
public class ProjectSettings : ISettings {

/// <summary>
/// Determine whether setting are out of sync and needs to be persisted or not
/// </summary>
public bool IsModified
{
get { return systemSettings.IsModified || projectSettings.IsModified; }
set { systemSettings.IsModified = projectSettings.IsModified = value; }
}

/// <summary>
/// Whether to load settings from and save settings to disk.
/// Exposed for testing.
Expand Down Expand Up @@ -798,6 +834,9 @@ public class ProjectSettings : ISettings {
})) {
return false;
}

// Project settings were just loaded so there shouldn't be any stale values
projectSettings.IsModified = false;
return true;
}
}
Expand All @@ -807,7 +846,7 @@ public class ProjectSettings : ISettings {
/// </summary>
private static void Save() {
lock (classLock) {
if (projectSettings == null || !persistenceEnabled) {
if (projectSettings == null || !persistenceEnabled || !projectSettings.IsModified) {
return;
}
Directory.CreateDirectory(Path.GetDirectoryName(PROJECT_SETTINGS_FILE));
Expand All @@ -817,9 +856,10 @@ public class ProjectSettings : ISettings {
PROJECT_SETTINGS_FILE), LogLevel.Error);
return;
}
string tmpFile = Path.GetTempFileName();
try {
using (var writer =
XmlWriter.Create(PROJECT_SETTINGS_FILE,
XmlWriter.Create(tmpFile,
new XmlWriterSettings {
Encoding = new UTF8Encoding(false),
Indent = true,
Expand All @@ -839,6 +879,8 @@ public class ProjectSettings : ISettings {
}
writer.WriteEndElement();
}

File.Copy(tmpFile, PROJECT_SETTINGS_FILE, true);
} catch (Exception exception) {
if (exception is IOException || exception is UnauthorizedAccessException) {
logger.Log(String.Format("Unable to write to '{0}' ({1}, " +
Expand All @@ -848,6 +890,10 @@ public class ProjectSettings : ISettings {
}
throw exception;
}
finally
{
File.Delete(tmpFile);
}
}
}
}
Expand Down