// Perforce and other VCS have a lock mechanism that usually // only makes the file writable once checked out. We need to // check them out before writing to them for auto-generated files. public static void Unlock(string path) { Ensure.That(nameof(path)).IsNotNull(path); UnityAPI.Await ( () => { // The API changed in 2019, adding a third optional ChangeSet parameter // which defaults to null but breaks the compiled signature below // Furthermore, we can't even so much as have the call in the body of this method, // or it will fail even if the if branch evaluates to false. So we if (File.Exists(path) && Provider.enabled && Provider.isActive && Provider.hasCheckoutSupport) { try { var provider = typeof(Provider); if (EditorApplicationUtility.unityVersion >= "2019.1.0") { var method = provider.GetMethods() .FirstOrDefault ( m => m.Name == "Checkout" && m.GetParameters().Length == 3 && m.GetParameters()[0].ParameterType == typeof(string) && m.GetParameters()[1].ParameterType == typeof(CheckoutMode) ); if (method == null) { throw new MissingMemberException(provider.FullName, "Checkout"); } method.InvokeOptimized(null, PathUtility.FromProject(path), CheckoutMode.Both, null); } else { var method = provider.GetMethods() .FirstOrDefault ( m => m.Name == "Checkout" && m.GetParameters().Length == 2 && m.GetParameters()[0].ParameterType == typeof(string) && m.GetParameters()[1].ParameterType == typeof(CheckoutMode) ); if (method == null) { throw new MissingMemberException(provider.FullName, "Checkout"); } method.InvokeOptimized(null, PathUtility.FromProject(path), CheckoutMode.Both); } } catch (Exception ex) { Debug.LogWarning($"Failed to automatically checkout file from version control:\n{path}\n{ex}"); } } if (File.Exists(path)) { var info = new FileInfo(path); if (info.IsReadOnly) { var sb = new StringBuilder(); sb.AppendLine($"File '{info.Name}' is read-only despite attempted checkout. Manually forcing to writable."); sb.AppendLine($"This may cause version control issues. Please report the following debug information:"); sb.AppendLine($"File Exists: {File.Exists(path)}"); sb.AppendLine($"Provider.enabled: {Provider.enabled}"); sb.AppendLine($"Provider.isActive: {Provider.isActive}"); sb.AppendLine($"Provider.hasCheckoutSupport: {Provider.hasCheckoutSupport}"); Debug.LogWarning(sb.ToString()); info.IsReadOnly = false; } } } ); }
protected override void OnContentGUI() { if (!plugins.Any()) { Complete(); } GUILayout.BeginVertical(Styles.background, GUILayout.ExpandHeight(true)); LudiqGUI.FlexibleSpace(); GUILayout.Label($"The following plugins have been downgraded to a previous version: ", LudiqStyles.centeredLabel); LudiqGUI.FlexibleSpace(); UpdateWizard.DrawPluginVersionTable(plugins); LudiqGUI.FlexibleSpace(); GUILayout.Label("This will likely cause backwards incompatibility issues.", LudiqStyles.centeredLabel); GUILayout.Label("We recommend that you re-install their saved version to avoid data corruption.", LudiqStyles.centeredLabel); LudiqGUI.FlexibleSpace(); LudiqGUI.BeginHorizontal(); LudiqGUI.FlexibleSpace(); if (GUILayout.Button("Close", Styles.button)) { throw new WindowClose(); } LudiqGUI.Space(10); if (GUILayout.Button("Force Consolidate", Styles.button)) { var consolidationExplanation = string.Empty; consolidationExplanation += $"By forcing consolidation, the saved versions will be set to match the installed versions. "; consolidationExplanation += "This does not roll back updates and may lead to data corruption. "; consolidationExplanation += "You should only do this if you know what you are doing. "; consolidationExplanation += "A backup will be created automatically if you decide to proceed."; if (EditorUtility.DisplayDialog("Force Consolidate Version", consolidationExplanation, "Force Consolidate", "Cancel")) { var forceConsolidate = false; if (EditorUtility.DisplayDialog("Force Consolidate Version", "Create backup before consolidating?", "Yes", "No")) { try { BackupUtility.BackupAssetsFolder(); forceConsolidate = true; } catch (Exception ex) { EditorUtility.DisplayDialog("Backup", "Failed to create backup. Version consolidation canceled.", "OK"); UnityEngine.Debug.LogException(ex); } } else { forceConsolidate = true; } if (forceConsolidate) { foreach (var plugin in plugins) { plugin.manifest.savedVersion = plugin.manifest.currentVersion; } Complete(); } } } LudiqGUI.Space(10); if (GUILayout.Button("Backups", Styles.button)) { PathUtility.CreateDirectoryIfNeeded(Paths.backups); Process.Start(Paths.backups); } LudiqGUI.FlexibleSpace(); LudiqGUI.EndHorizontal(); LudiqGUI.FlexibleSpace(); LudiqGUI.EndVertical(); }
private static void GenerateStubScript(string scriptPath, IEnumerable <AotStubWriter> stubWriters) { Ensure.That(nameof(stubWriters)).IsNotNull(stubWriters); var unit = new CodeCompileUnit(); var @namespace = new CodeNamespace("Ludiq.Generated.Aot"); unit.Namespaces.Add(@namespace); var @class = new CodeTypeDeclaration("AotStubs") { IsClass = true }; @class.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeTypeReference(typeof(PreserveAttribute)))); @namespace.Types.Add(@class); var usedMethodNames = new HashSet <string>(); foreach (var stubWriter in stubWriters.OrderBy(sw => sw.stubMethodComment)) { if (stubWriter.skip) { continue; } var methodName = stubWriter.stubMethodName; var i = 0; while (usedMethodNames.Contains(methodName)) { methodName = stubWriter.stubMethodName + "_" + i++; } usedMethodNames.Add(methodName); @class.Comments.Add(new CodeCommentStatement(stubWriter.stubMethodComment)); var @method = new CodeMemberMethod { Name = methodName, ReturnType = new CodeTypeReference(typeof(void)), Attributes = MemberAttributes.Public | MemberAttributes.Static }; @method.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeTypeReference(typeof(PreserveAttribute), CodeTypeReferenceOptions.GlobalReference))); @method.Comments.Add(new CodeCommentStatement(stubWriter.stubMethodComment)); @method.Statements.AddRange(stubWriter.GetStubStatements().ToArray()); @class.Members.Add(@method); } PathUtility.CreateDirectoryIfNeeded(LudiqCore.Paths.transientGenerated); DeleteStubScript(); using (var provider = CodeDomProvider.CreateProvider("CSharp")) { var options = new CodeGeneratorOptions { BracingStyle = "C", IndentString = "\t", BlankLinesBetweenMembers = true, ElseOnClosing = false, VerbatimOrder = true }; using (var scriptWriter = new StreamWriter(scriptPath)) { provider.GenerateCodeFromCompileUnit(new CodeSnippetCompileUnit("#pragma warning disable 219"), scriptWriter, options); // Disable unused variable warning provider.GenerateCodeFromCompileUnit(unit, scriptWriter, options); } } AssetDatabase.Refresh(); }