public static VirtualFileSystemRoot GetRoot()
        {
            var applicationBase = LoaderLock.ApplicationBase ?? string.Empty;

            if (_vfs.TryGetValue(applicationBase, out var root))
            {
                return(root);
            }
            var newRoot = new VirtualFileSystemRoot();

            if (0 < applicationBase.Length)
            {
                newRoot.LoadFrom(applicationBase);
            }
            _vfs.Add(applicationBase, newRoot);
            return(newRoot);
        }
Example #2
0
        public static void Compile(UserQueryTypeInfo userQuery, QueryInfo currentQuery, CompilationOptions options, QueryInfo currentQueryInfo)
        {
            Debug.WriteLine("==== Compiler pass begin ====", nameof(Compiler));

            // ====

            if (options.OutDir == null)
            {
                throw new InvalidOperationException("Compilation option 'OutDir' cannot be null");
            }

            // ====

            var functions = FunctionBinder.BindAll(userQuery.Type);

            // ====

            var functionDirs = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            // ====

            var assemblyName = typeof(Program).Assembly.GetName();
            var generatedBy  = assemblyName.Name + "-" + assemblyName.Version.Major + "." + assemblyName.Version.Minor + "." + assemblyName.Version.Build; // .NET calls build what semver calls revision

            foreach (var f in functions)
            {
                var functionJson = new JObject();

                functionJson["generatedBy"] = assemblyName.Name + "-" + assemblyName.Version.Major + "." + assemblyName.Version.Minor + "." + assemblyName.Version.Build; // .NET calls build what semver calls revision

                // "attributes" is used by the Azure Web Jobs SDK
                // to bind using metadata and takes precedence
                // over "config". we do not want this.
                functionJson["configurationSource"] = "config";

                functionJson["bindings"]   = JToken.FromObject(f.Trigger.GetBindings());
                functionJson["disabled"]   = false;
                functionJson["scriptFile"] = "../bin/CloudPad.FunctionApp.dll";
                functionJson["entryPoint"] = f.Trigger.GetEntryPoint();

                var cloudPad = new JObject();

                cloudPad["applicationBase"] = $"../scripts/{options.QueryName}_{userQuery.Id}";
                cloudPad["scriptFile"]      = userQuery.AssemblyLocationFileName;
                cloudPad["typeName"]        = userQuery.Type.FullName;
                cloudPad["methodName"]      = f.Method.Name;

                var connInfo = currentQueryInfo.GetConnectionInfo();
                if (connInfo != null)
                {
                    cloudPad["providerName"]     = connInfo.Provider;
                    cloudPad["connectionString"] = Util.CurrentCxString;
                }

                functionJson["cloudPad"] = cloudPad;

                // ====

                var functionName = options.QueryName + "_" + f.Method.Name;
                var functionDir  = Path.Combine(options.OutDir, functionName);
                Directory.CreateDirectory(functionDir);
                File.WriteAllText(Path.Combine(functionDir, "function.json"), JsonConvert.SerializeObject(functionJson, Formatting.Indented));
                functionDirs.Add(functionName);
            }

            if (Directory.Exists(options.OutDir))
            {
                foreach (var d in Directory.EnumerateDirectories(options.OutDir, "*", SearchOption.TopDirectoryOnly))
                {
                    var name = Path.GetFileName(d);
                    if ("bin".Equals(name, StringComparison.OrdinalIgnoreCase))
                    {
                        continue;
                    }
                    if ("scripts".Equals(name, StringComparison.OrdinalIgnoreCase))
                    {
                        continue;
                    }
                    if (!functionDirs.Contains(name))
                    {
                        Directory.Delete(d, true);
                    }
                }
            }

            // ====

            var userAssemblies = LoadAllUserAssemblies2(userQuery, currentQuery);

            // ====

            var lib = Path.Combine(options.OutDir, "scripts", options.QueryName + "_" + userQuery.Id);

            Directory.CreateDirectory(lib);
            foreach (var userAssembly in userAssemblies)
            {
                var destination = Path.Combine(lib, Path.GetFileName(userAssembly.Name.Name + ".dll")); // stabilize DLL name (simplifies assembly resolve)
                if (File.Exists(destination))
                {
                    Debug.WriteLine($"Output file exists '{destination}'", nameof(Compiler));
                    continue;
                }
                AssemblyBindingTarget.Rewrite(userAssembly.Location, destination);
            }

            // ====

            var root = VirtualFileSystemRoot.GetRoot();

            root.SaveTo(lib);

            // ====

            Debug.WriteLine($"==== Compiler pass end, OutDir= {options.OutDir} ====", nameof(Compiler));
        }