Skip to content

Fix project settings file getting corrupted #652

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

Closed
Closed
Changes from all 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
55 changes: 51 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 @@ public IEnumerable<string> Keys {
/// 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,15 @@ 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;
}

settings[name] = stringValue;
}

/// <summary>
Expand Down Expand Up @@ -333,6 +359,7 @@ public bool HasKey(string name) {
/// <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 +374,16 @@ public void DeleteKey(string name) {
/// 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 +835,9 @@ private static bool Load() {
})) {
return false;
}

// Project settings were just loaded so there shouldn't be any stale values
projectSettings.IsModified = false;
return true;
}
}
Expand All @@ -807,7 +847,7 @@ private static bool Load() {
/// </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 +857,10 @@ private static void Save() {
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 +880,8 @@ private static void Save() {
}
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 +891,10 @@ private static void Save() {
}
throw exception;
}
finally
{
File.Delete(tmpFile);
}
}
}
}
Expand Down