Esempio n. 1
0
        private static PackageManifest LoadManifest(out List <string> manifestFileLines)
        {
            PackageManifest manifest = null;

            manifestFileLines = new List <string>();

            if (string.IsNullOrWhiteSpace(ManifestFilePath))
            {
                return(null);
            }

            // Read the package manifest into a list of strings (for easy finding of entries)
            // and then deserialize.
            using (FileStream manifestStream = new FileStream(ManifestFilePath, FileMode.Open, FileAccess.Read))
            {
                using (StreamReader reader = new StreamReader(manifestStream))
                {
                    // Read the manifest file a line at a time.
                    while (!reader.EndOfStream)
                    {
                        string line = reader.ReadLine();
                        manifestFileLines.Add(line);
                    }

                    // Go back to the start of the file.
                    manifestStream.Seek(0, 0);

                    // Deserialize the scoped registries portion of the package manifest.
                    manifest = JsonUtility.FromJson <PackageManifest>(reader.ReadToEnd());
                }
            }

            return(manifest);
        }
Esempio n. 2
0
        /// <summary>
        /// Writes the Unity Package Manager manifest file.
        /// </summary>
        /// <param name="manifest">The manifest to be written.</param>
        /// <param name="manifestFileLines">Contents of the manifest file as a collection of lines.</param>
        /// <param name="registriesStartIndex">The line number on which the scopedRegistries section begins.</param>
        /// <param name="dependenciesStartIndex">The line number on which the dependencies section begins.</param>
        /// <remarks>
        /// The Unity JSON parser / writer appear to not have full support for dictionaries. As a result, the
        /// provided manifest contains only the scoped registry collection, while the manifestFileLines contains
        /// a potentially modified collection of packages to install, along with the previous collection of scoped
        /// registries. The registries collection in manifestFileLines will be replaced by those contained in
        /// the provided manifest.
        /// </remarks>
        private static void WriteManifest(
            PackageManifest manifest,
            List <string> manifestFileLines,
            int registriesStartIndex,
            int dependenciesStartIndex)
        {
            // First, serialize the scoped registry collection.
            string serializedRegistriesJson = string.Empty;

            if (manifest.scopedRegistries.Length > 0)
            {
                serializedRegistriesJson = JsonUtility.ToJson(manifest, true);
            }

            // Ensure that the file is truncated to ensure it is always valid after writing.
            using (FileStream outFile = new FileStream(ManifestFilePath, FileMode.Truncate, FileAccess.Write))
            {
                using (StreamWriter writer = new StreamWriter(outFile))
                {
                    bool scopedRegistriesWritten = false;

                    // Write each line of the manifest back to the file.
                    for (int i = 0; i < manifestFileLines.Count; i++)
                    {
                        if ((registriesStartIndex > 0) &&
                            (i >= registriesStartIndex) &&
                            (i < dependenciesStartIndex))
                        {
                            // Skip these lines, they will be replaced.
                            continue;
                        }

                        if (!string.IsNullOrWhiteSpace(serializedRegistriesJson) &&
                            !scopedRegistriesWritten &&
                            (i > 0))
                        {
                            // Trim the leading '{' and '\n' from the serialized scoped registries
                            serializedRegistriesJson = serializedRegistriesJson.Remove(0, 2);
                            // Trim, the trailing '\n' and '}'
                            serializedRegistriesJson = serializedRegistriesJson.Remove(serializedRegistriesJson.Length - 2);
                            // Append a trailing ',' to close the scopedRegistries node
                            serializedRegistriesJson = serializedRegistriesJson.Insert(serializedRegistriesJson.Length, ",");
                            writer.WriteLine(serializedRegistriesJson);

                            scopedRegistriesWritten = true;
                        }

                        writer.WriteLine(manifestFileLines[i]);
                    }
                }
            }
        }
        /// <summary>
        /// Ensures the required settings exist in the package manager to allow for using MSBuild for Unity.
        /// </summary>
        internal static void EnsureMSBuildForUnity()
        {
            PackageManifest manifest = null;

            string manifestPath = GetPackageManifestFilePath();

            if (string.IsNullOrWhiteSpace(manifestPath))
            {
                return;
            }

            // Read the package manifest into a list of strings (for easy finding of entries)
            // and then deserialize.
            List <string> manifestFileLines = new List <string>();

            using (FileStream manifestStream = new FileStream(manifestPath, FileMode.Open, FileAccess.Read))
            {
                using (StreamReader reader = new StreamReader(manifestStream))
                {
                    // Read the manifest file a line at a time.
                    while (!reader.EndOfStream)
                    {
                        string line = reader.ReadLine();
                        manifestFileLines.Add(line);
                    }

                    // Go back to the start of the file.
                    manifestStream.Seek(0, 0);

                    // Deserialize the scoped registries portion of the package manifest.
                    manifest = JsonUtility.FromJson <PackageManifest>(reader.ReadToEnd());
                }
            }

            if (manifest == null)
            {
                Debug.LogError($"Failed to read the package manifest file ({manifestPath})");
                return;
            }

            // Ensure that pre-existing scoped registries are retained.
            List <ScopedRegistry> scopedRegistries = new List <ScopedRegistry>();

            if ((manifest.scopedRegistries != null) && (manifest.scopedRegistries.Length > 0))
            {
                scopedRegistries.AddRange(manifest.scopedRegistries);
            }

            // Attempt to find an entry in the scoped registries collection for the MSBuild for Unity URL
            bool needToAddRegistry = true;

            foreach (ScopedRegistry registry in scopedRegistries)
            {
                if (registry.url == MSBuildRegistryUrl)
                {
                    needToAddRegistry = false;
                }
            }

            // If no entry was found, add one.
            if (needToAddRegistry)
            {
                ScopedRegistry registry = new ScopedRegistry();
                registry.name   = MSBuildRegistryName;
                registry.url    = MSBuildRegistryUrl;
                registry.scopes = MSBuildRegistryScopes;

                scopedRegistries.Add(registry);
            }

            // Update the manifest's scoped registries, as the collection may have been modified.
            manifest.scopedRegistries = scopedRegistries.ToArray();

            int dependenciesStartIndex     = -1;
            int scopedRegistriesStartIndex = -1;
            int scopedRegistriesEndIndex   = -1;
            int packageLine = -1;

            // Presume that we need to add the MSBuild for Unity package. If this value is false,
            // we will check to see if the currently configured version meets or exceeds the
            // minimum requirements.
            bool needToAddPackage = true;

            // Attempt to find the MSBuild for Unity package entry in the dependencies collection
            // This loop also identifies the dependencies collection line and the start / end of a
            // pre-existing scoped registries collections
            for (int i = 0; i < manifestFileLines.Count; i++)
            {
                if (manifestFileLines[i].Contains("\"scopedRegistries\":"))
                {
                    scopedRegistriesStartIndex = i;
                }
                if (manifestFileLines[i].Contains("],") && (scopedRegistriesStartIndex != -1) && (scopedRegistriesEndIndex == -1))
                {
                    scopedRegistriesEndIndex = i;
                }
                if (manifestFileLines[i].Contains("\"dependencies\": {"))
                {
                    dependenciesStartIndex = i;
                }
                if (manifestFileLines[i].Contains(MSBuildPackageName))
                {
                    packageLine      = i;
                    needToAddPackage = false;
                }
            }

            // If no package was found add it to the dependencies collection.
            if (needToAddPackage)
            {
                // Add the package to the collection (pad the entry with four spaces)
                manifestFileLines.Insert(dependenciesStartIndex + 1, $"    \"{MSBuildPackageName}\": \"{MSBuildPackageVersion}\",");
            }
            else
            {
                // Replace the line that currently exists
                manifestFileLines[packageLine] = $"    \"{MSBuildPackageName}\": \"{MSBuildPackageVersion}\",";
            }

            // Update the manifest file.
            // First, serialize the scoped registry collection.
            string serializedRegistriesJson = JsonUtility.ToJson(manifest, true);

            // Ensure that the file is truncated to ensure it is always valid after writing.
            using (FileStream outFile = new FileStream(manifestPath, FileMode.Truncate, FileAccess.Write))
            {
                using (StreamWriter writer = new StreamWriter(outFile))
                {
                    bool scopedRegistriesWritten = false;

                    // Write each line of the manifest back to the file.
                    for (int i = 0; i < manifestFileLines.Count; i++)
                    {
                        if ((i >= scopedRegistriesStartIndex) && (i <= scopedRegistriesEndIndex))
                        {
                            // Skip these lines, they will be replaced.
                            continue;
                        }

                        if (!scopedRegistriesWritten && (i > 0))
                        {
                            // Trim the leading '{' and '\n' from the serialized scoped registries
                            serializedRegistriesJson = serializedRegistriesJson.Remove(0, 2);
                            // Trim, the trailing '\n' and '}'
                            serializedRegistriesJson = serializedRegistriesJson.Remove(serializedRegistriesJson.Length - 2);
                            // Append a trailing ',' to close the scopedRegistries node
                            serializedRegistriesJson = serializedRegistriesJson.Insert(serializedRegistriesJson.Length, ",");
                            writer.WriteLine(serializedRegistriesJson);

                            scopedRegistriesWritten = true;
                        }

                        writer.WriteLine(manifestFileLines[i]);
                    }
                }
            }
        }
        /// <summary>
        /// Ensures the required settings exist in the package manager to allow for
        /// installing MSBuild for Unity.
        /// </summary>
        internal static void EnsureMSBuildForUnity()
        {
            // Locate the full path to the package manifest.
            DirectoryInfo projectRoot = new DirectoryInfo(Application.dataPath).Parent;

            string[] paths        = { projectRoot.FullName, "Packages", "manifest.json" };
            string   manifestPath = Path.Combine(paths);

            // Verify that the package manifest file exists.
            if (!File.Exists(manifestPath))
            {
                Debug.LogError($"Package manifest file ({manifestPath}) could not be found.");
                return;
            }

            PackageManifest manifest = null;

            // Read the package manifest into a list of strings (for easy finding of entries)
            // and then deserialize.
            List <string> manifestFileLines = new List <string>();

            using (FileStream manifestStream = new FileStream(manifestPath, FileMode.Open, FileAccess.Read))
            {
                using (StreamReader reader = new StreamReader(manifestStream))
                {
                    // Read the manifest file a line at a time.
                    while (!reader.EndOfStream)
                    {
                        string line = reader.ReadLine();
                        manifestFileLines.Add(line);
                    }

                    // Go back to the start of the file.
                    manifestStream.Seek(0, 0);

                    // Deserialize the scoped registries portion of the package manifest.
                    manifest = JsonUtility.FromJson <PackageManifest>(reader.ReadToEnd());
                }
            }

            if (manifest == null)
            {
                Debug.LogError($"Failed to read the package manifest file ({manifestPath})");
                return;
            }

            // Ensure that pre-exising scoped registries are retained.
            List <ScopedRegistry> scopedRegistries = new List <ScopedRegistry>();

            if ((manifest.scopedRegistries != null) && (manifest.scopedRegistries.Length > 0))
            {
                scopedRegistries.AddRange(manifest.scopedRegistries);
            }

            // Attempt to find an entry in the scoped regstries collection for the MSBuild for Unity url
            bool needToAddRegistry = true;

            foreach (ScopedRegistry registry in scopedRegistries)
            {
                if (registry.url == MSBuildRegistryUrl)
                {
                    needToAddRegistry = false;
                }
            }

            // If no entry was found, add one.
            if (needToAddRegistry)
            {
                ScopedRegistry registry = new ScopedRegistry();
                registry.name   = MSBuildRegistryName;
                registry.url    = MSBuildRegistryUrl;
                registry.scopes = MSBuildRegistryScopes;

                scopedRegistries.Add(registry);
            }

            // Update the manifest's scoped registries, as the collection may have been modified.
            manifest.scopedRegistries = scopedRegistries.ToArray();

            int dependenciesStartIndex     = -1;
            int scopedRegistriesStartIndex = -1;
            int scopedRegistriesEndIndex   = -1;

            // Attempt to find the MSBuild for Unity package entry in the dependencies collection
            // This loop also identifies the dependecies collection line and the start / end of a
            // pre-existing scoped registries collections
            bool needToAddPackage = true;

            for (int i = 0; i < manifestFileLines.Count; i++)
            {
                if (manifestFileLines[i].Contains("\"scopedRegistries\":"))
                {
                    scopedRegistriesStartIndex = i;
                }
                if (manifestFileLines[i].Contains("],") && (scopedRegistriesStartIndex != -1) && (scopedRegistriesEndIndex == -1))
                {
                    scopedRegistriesEndIndex = i;
                }
                if (manifestFileLines[i].Contains("\"dependencies\": {"))
                {
                    dependenciesStartIndex = i;
                }
                if (manifestFileLines[i].Contains(MSBuildPackageName))
                {
                    needToAddPackage = false;
                }
            }

            // If no package was found add it to the dependencies collection.
            if (needToAddPackage)
            {
                // Add the package to the collection (pad the entry with four spaces)
                manifestFileLines.Insert(dependenciesStartIndex + 1, $"    \"{MSBuildPackageName}\": \"{MSBuildPackageVersion}\",");
            }

            if (needToAddRegistry || needToAddPackage)
            {
                // If we added a scoped registry or package, rewrite the manifest file.

                // First, serialize the scoped registry collection.
                string serializedRegistriesJson = JsonUtility.ToJson(manifest, true);

                // Ensure that the file is truncated to ensure it is always valid after writing.
                using (FileStream outFile = new FileStream(manifestPath, FileMode.Truncate, FileAccess.Write))
                {
                    using (StreamWriter writer = new StreamWriter(outFile))
                    {
                        bool scopedRegistriesWritten = false;

                        // Write each line of the manifest back to the file.
                        for (int i = 0; i < manifestFileLines.Count; i++)
                        {
                            if ((i >= scopedRegistriesStartIndex) && (i <= scopedRegistriesEndIndex))
                            {
                                // Skip these lines, they will be replaced.
                                continue;
                            }

                            if (!scopedRegistriesWritten && (i > 0))
                            {
                                // Trim the leading '{' and '\n' from the serialized scoped registries
                                serializedRegistriesJson = serializedRegistriesJson.Remove(0, 2);
                                // Trim, the trailing '\n' and '}'
                                serializedRegistriesJson = serializedRegistriesJson.Remove(serializedRegistriesJson.Length - 2);
                                // Append a trailing ',' to close the scopedRegistries node
                                serializedRegistriesJson = serializedRegistriesJson.Insert(serializedRegistriesJson.Length, ",");
                                writer.WriteLine(serializedRegistriesJson);

                                scopedRegistriesWritten = true;
                            }

                            writer.WriteLine(manifestFileLines[i]);
                        }
                    }
                }
            }
        }
Esempio n. 5
0
        internal static void DisableMSBuildForUnity()
        {
            List <string>   manifestFileLines;
            PackageManifest manifest = LoadManifest(out manifestFileLines);

            if (manifest == null)
            {
                Debug.LogError($"Failed to read the package manifest file ({ManifestFilePath})");
                return;
            }

            // Ensure that pre-existing scoped registries are retained.
            List <ScopedRegistry> scopedRegistries = new List <ScopedRegistry>();

            if ((manifest.scopedRegistries != null) && (manifest.scopedRegistries.Length > 0))
            {
                scopedRegistries.AddRange(manifest.scopedRegistries);
            }

            // Attempt to find an entry in the scoped registries collection for the MSBuild for Unity URL
            int registryToRemove = -1;

            for (int i = 0; i < scopedRegistries.Count; i++)
            {
                if (scopedRegistries[i].url == MSBuildRegistryUrl)
                {
                    registryToRemove = i;
                    break;
                }
            }
            if (registryToRemove != -1)
            {
                scopedRegistries.RemoveAt(registryToRemove);
                // Update the manifest's scoped registries.
                manifest.scopedRegistries = scopedRegistries.ToArray();
            }

            // Attempt to find the msbuild for unity package
            // This loop also identifies the lines that enclose the scoped registry collection.
            int registriesStartIndex   = -1;
            int dependenciesStartIndex = -1;
            int packageToRemove        = -1;

            for (int i = 0; i < manifestFileLines.Count; i++)
            {
                if (manifestFileLines[i].Contains("\"scopedRegistries\":"))
                {
                    registriesStartIndex = i;
                }
                if (manifestFileLines[i].Contains("\"dependencies\":"))
                {
                    dependenciesStartIndex = i;
                }
                if (manifestFileLines[i].Contains(MSBuildPackageName))
                {
                    packageToRemove = i;
                    break;
                }
            }
            if (packageToRemove != -1)
            {
                manifestFileLines.RemoveAt(packageToRemove);
            }

            // Update the manifest file
            if ((registryToRemove == -1) &&
                (packageToRemove == -1))
            {
                // No changes needed.
                return;
            }

            WriteManifest(
                manifest,
                manifestFileLines,
                registriesStartIndex,
                dependenciesStartIndex);
        }
Esempio n. 6
0
        internal static void EnableMSBuildForUnity()
        {
            if (!EditorUtility.DisplayDialog(
                    "Use MSBuild for Unity for dependency resolution",
                    "Some versions of Unity have experienced issues with MSBuild for Unity. Do you wish to continue?",
                    "Yes", "No"))
            {
                return;
            }

            List <string>   manifestFileLines;
            PackageManifest manifest = LoadManifest(out manifestFileLines);

            if (manifest == null)
            {
                Debug.LogError($"Failed to read the package manifest file ({ManifestFilePath})");
                return;
            }

            // Ensure that pre-existing scoped registries are retained.
            List <ScopedRegistry> scopedRegistries = new List <ScopedRegistry>();

            if ((manifest.scopedRegistries != null) && (manifest.scopedRegistries.Length > 0))
            {
                scopedRegistries.AddRange(manifest.scopedRegistries);
            }

            // Attempt to find an entry in the scoped registries collection for the MSBuild for Unity URL
            bool needToAddRegistry = true;

            foreach (ScopedRegistry registry in scopedRegistries)
            {
                if (registry.url == MSBuildRegistryUrl)
                {
                    needToAddRegistry = false;
                    break;
                }
            }

            // If no entry was found, add one.
            if (needToAddRegistry)
            {
                ScopedRegistry registry = new ScopedRegistry();
                registry.name   = MSBuildRegistryName;
                registry.url    = MSBuildRegistryUrl;
                registry.scopes = MSBuildRegistryScopes;

                scopedRegistries.Add(registry);
            }

            // Update the manifest's scoped registries, as the collection may have been modified.
            manifest.scopedRegistries = scopedRegistries.ToArray();

            // Presume that we need to add the MSBuild for Unity package. If this value is false,
            // we will check to see if the currently configured version meets or exceeds the
            // minimum requirements.
            bool needToAddPackage = true;

            // Attempt to find the MSBuild for Unity package entry in the dependencies collection
            // This loop also identifies the line that starts the dependencies and encloses the
            // scoped registries collection.
            int dependenciesStartIndex = -1;
            int registriesStartIndex   = -1;
            int packageLine            = -1;

            for (int i = 0; i < manifestFileLines.Count; i++)
            {
                if (manifestFileLines[i].Contains("\"scopedRegistries\":"))
                {
                    registriesStartIndex = i;
                }
                if (manifestFileLines[i].Contains("\"dependencies\": {"))
                {
                    dependenciesStartIndex = i;
                }
                if (manifestFileLines[i].Contains(MSBuildPackageName))
                {
                    packageLine      = i;
                    needToAddPackage = false;
                }
            }

            // If no package was found add it to the dependencies collection.
            if (needToAddPackage)
            {
                // Add the package to the collection (pad the entry with four spaces)
                manifestFileLines.Insert(dependenciesStartIndex + 1, $"    \"{MSBuildPackageName}\": \"{MSBuildPackageVersion}\",");
            }
            else
            {
                // Replace the line that currently exists
                manifestFileLines[packageLine] = $"    \"{MSBuildPackageName}\": \"{MSBuildPackageVersion}\",";
            }

            // Update the manifest
            if (!needToAddRegistry && !needToAddPackage)
            {
                // No changes required.
                return;
            }
            WriteManifest(
                manifest,
                manifestFileLines,
                registriesStartIndex,
                dependenciesStartIndex);
        }