Newer
Older
CGTrack / Assets / Oculus / SampleFramework / Core / Gradle / Editor / Utils.cs
using System.Collections.Generic;
using UnityEditor;
using System.IO;
using System.Text.RegularExpressions;

namespace Gradle
{
    public static class Configuration
    {
        private static readonly string androidPluginsFolder = "Assets/Plugins/Android/";
        private static readonly string gradleTemplatePath = androidPluginsFolder + "mainTemplate.gradle";
        private static readonly string disabledGradleTemplatePath = gradleTemplatePath + ".DISABLED";
        private static readonly string internalGradleTemplatePath = Path.Combine(Path.Combine(GetBuildToolsDirectory(BuildTarget.Android), "GradleTemplates"), "mainTemplate.gradle");

        private static string GetBuildToolsDirectory(UnityEditor.BuildTarget bt)
        {
            return (string)(typeof(BuildPipeline).GetMethod("GetBuildToolsDirectory", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).Invoke(null, new object[] { bt }));
        }

        public static void UseGradle()
        {
            EditorUserBuildSettings.androidBuildSystem = AndroidBuildSystem.Gradle;

            // create android plugins directory if it doesn't exist
            if (!Directory.Exists(androidPluginsFolder))
            {
                Directory.CreateDirectory(androidPluginsFolder);
            }

            if (!File.Exists(gradleTemplatePath))
            {
                if (File.Exists(gradleTemplatePath + ".DISABLED"))
                {
                    File.Move(disabledGradleTemplatePath, gradleTemplatePath);
                    File.Move(disabledGradleTemplatePath + ".meta", gradleTemplatePath + ".meta");
                }
                else
                {
                    File.Copy(internalGradleTemplatePath, gradleTemplatePath);
                }
                AssetDatabase.ImportAsset(gradleTemplatePath);
            }
        }

        public static bool IsUsingGradle()
        {
            return EditorUserBuildSettings.androidBuildSystem == AndroidBuildSystem.Gradle 
                && Directory.Exists(androidPluginsFolder) 
                && File.Exists(gradleTemplatePath);
        }

        public static List<string> ReadLines()
        {
            var allText = IsUsingGradle() ? File.ReadAllText(gradleTemplatePath) : "";
            return new List<string>(allText.Split('\n'));
        }

        public static void WriteLines(List<string> lines)
        {
            if (IsUsingGradle())
            {
                File.WriteAllText(gradleTemplatePath, string.Join("\n", lines.ToArray()));
            }
        }

//        // doesn't seem to be needed anymore as of Unity 2018.4.28f LTS
//        public static void VersionFixups(List<string> lines)
//        {
//            // add compileOptions to add Java 1.8 compatibility
//            int android = Gradle.Parsing.GoToSection("android", lines);
//            if (Gradle.Parsing.FindInScope("compileOptions", android + 1, lines) == -1)
//            {
//                int compileOptionsIndex = Gradle.Parsing.GetScopeEnd(android + 1, lines);
//                lines.Insert(compileOptionsIndex, "\t}");
//                lines.Insert(compileOptionsIndex, "\t\ttargetCompatibility JavaVersion.VERSION_1_8");
//                lines.Insert(compileOptionsIndex, "\t\tsourceCompatibility JavaVersion.VERSION_1_8");
//                lines.Insert(compileOptionsIndex, "\tcompileOptions {");
//            }

//            // add sourceSets if Version < 2018.2
//#if !UNITY_2018_2_OR_NEWER
//            if (Gradle.Parsing.FindInScope("sourceSets\\.main\\.java\\.srcDir", android + 1, lines) == -1)
//            {
//                lines.Insert(Gradle.Parsing.GetScopeEnd(android + 1, lines), "\tsourceSets.main.java.srcDir \"" + gradleSourceSetPath + "\"");
//            }
//#endif
//        }
    }

    public static class Dependencies
    {
        public static void AddRepository(string section, string name, List<string> lines)
        {
            int sectionIndex = Gradle.Parsing.GoToSection($"{section}.repositories", lines);
            if (Gradle.Parsing.FindInScope($"{name}\\(\\)", sectionIndex + 1, lines) == -1)
            {
                lines.Insert(Gradle.Parsing.GetScopeEnd(sectionIndex + 1, lines), $"\t\t{name}()");
            }
        }

        public static void AddDependency(string name, string version, List<string> lines)
        {
            int dependencies = Gradle.Parsing.GoToSection("dependencies", lines);
            if (Gradle.Parsing.FindInScope(Regex.Escape(name), dependencies + 1, lines) == -1)
            {
                lines.Insert(Gradle.Parsing.GetScopeEnd(dependencies + 1, lines), $"\tcompile '{name}:{version}'");
            }
        }

        public static void RemoveDependency(string name, List<string> lines)
        {
            int dependencies = Gradle.Parsing.GoToSection("dependencies", lines);
            int target = Gradle.Parsing.FindInScope(Regex.Escape(name), dependencies + 1, lines);
            if (target != -1)
            {
                lines.RemoveAt(target);
            }
        }

        public static void RemoveSourceSet(string name, List<string> lines)
        {
            int android = Gradle.Parsing.GoToSection("android", lines);
            int sourceSets = Gradle.Parsing.FindInScope(Regex.Escape(name), android + 1, lines);
            if (sourceSets != -1)
            {
                lines.RemoveAt(sourceSets);
            }
        }
    }

    public static class Parsing
    {
        public static string GetVersion(string text)
        {
            return new System.Text.RegularExpressions.Regex("com.android.tools.build:gradle:([0-9]+\\.[0-9]+\\.[0-9]+)").Match(text).Groups[1].Value;
        }
        public static int GoToSection(string section, List<string> lines)
        {
            return GoToSection(section, 0, lines);
        }

        public static int GoToSection(string section, int start, List<string> lines)
        {
            var sections = section.Split('.');

            int p = start - 1;
            for (int i = 0; i < sections.Length; i++)
            {
                p = FindInScope("\\s*" + sections[i] + "\\s*\\{\\s*", p + 1, lines);
            }

            return p;
        }

        public static int FindInScope(string search, int start, List<string> lines)
        {
            var regex = new System.Text.RegularExpressions.Regex(search);

            int depth = 0;

            for (int i = start; i < lines.Count; i++)
            {
                if (depth == 0 && regex.IsMatch(lines[i]))
                {
                    return i;
                }

                // count the number of open and close braces. If we leave the current scope, break
                if (lines[i].Contains("{"))
                {
                    depth++;
                }
                if (lines[i].Contains("}"))
                {
                    depth--;
                }
                if (depth < 0)
                {
                    break;
                }
            }
            return -1;
        }

        public static int GetScopeEnd(int start, List<string> lines)
        {
            int depth = 0;
            for (int i = start; i < lines.Count; i++)
            {
                // count the number of open and close braces. If we leave the current scope, break
                if (lines[i].Contains("{"))
                {
                    depth++;
                }
                if (lines[i].Contains("}"))
                {
                    depth--;
                }
                if (depth < 0)
                {
                    return i;
                }
            }

            return -1;
        }
    }
}