-
Notifications
You must be signed in to change notification settings - Fork 448
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
Rename Source metadata property, clean up resolution logic (#351) #352
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -407,8 +407,8 @@ private Collection<FunctionDescriptor> ReadFunctions(ScriptHostConfiguration con | |
// TODO: we need to define a json schema document and do | ||
// schema validation and give more informative responses | ||
string json = File.ReadAllText(functionConfigPath); | ||
JObject configMetadata = JObject.Parse(json); | ||
FunctionMetadata metadata = ParseFunctionMetadata(functionName, config.HostConfig.NameResolver, configMetadata); | ||
JObject functionConfig = JObject.Parse(json); | ||
FunctionMetadata metadata = ParseFunctionMetadata(functionName, config.HostConfig.NameResolver, functionConfig); | ||
|
||
// determine the primary script | ||
string[] functionFiles = Directory.EnumerateFiles(scriptDir).Where(p => Path.GetFileName(p).ToLowerInvariant() != ScriptConstants.FunctionConfigFileName).ToArray(); | ||
|
@@ -417,42 +417,18 @@ private Collection<FunctionDescriptor> ReadFunctions(ScriptHostConfiguration con | |
AddFunctionError(functionName, "No function script files present."); | ||
continue; | ||
} | ||
else if (functionFiles.Length == 1) | ||
string scriptFile = DeterminePrimaryScriptFile(functionConfig, functionFiles); | ||
if (string.IsNullOrEmpty(scriptFile)) | ||
{ | ||
// if there is only a single file, that file is primary | ||
metadata.Source = functionFiles[0]; | ||
} | ||
else | ||
{ | ||
// if there is a "run" file, that file is primary | ||
string functionPrimary = null; | ||
functionPrimary = functionFiles.FirstOrDefault(p => Path.GetFileNameWithoutExtension(p).ToLowerInvariant() == "run"); | ||
if (string.IsNullOrEmpty(functionPrimary)) | ||
{ | ||
// for Node, any index.js file is primary | ||
functionPrimary = functionFiles.FirstOrDefault(p => Path.GetFileName(p).ToLowerInvariant() == "index.js"); | ||
if (string.IsNullOrEmpty(functionPrimary)) | ||
{ | ||
// finally, if there is an explicit primary file indicated | ||
// in config, use it | ||
JToken token = configMetadata["source"]; | ||
if (token != null) | ||
{ | ||
string sourceFileName = (string)token; | ||
functionPrimary = Path.Combine(scriptDir, sourceFileName); | ||
} | ||
} | ||
} | ||
|
||
if (string.IsNullOrEmpty(functionPrimary)) | ||
{ | ||
AddFunctionError(functionName, "Unable to determine primary function script."); | ||
continue; | ||
} | ||
metadata.Source = functionPrimary; | ||
AddFunctionError(functionName, | ||
"Unable to determine the primary function script. Try renaming your entry point script to 'run' (or 'index' in the case of Node), " + | ||
"or alternatively you can specify the name of the entry point script explicitly by adding a 'scriptFile' property to your function metadata."); | ||
continue; | ||
} | ||
metadata.ScriptFile = scriptFile; | ||
|
||
metadata.ScriptType = ParseScriptType(metadata.Source); | ||
// determine the script type based on the primary script file extension | ||
metadata.ScriptType = ParseScriptType(metadata.ScriptFile); | ||
|
||
metadatas.Add(metadata); | ||
} | ||
|
@@ -466,6 +442,40 @@ private Collection<FunctionDescriptor> ReadFunctions(ScriptHostConfiguration con | |
return ReadFunctions(metadatas, descriptorProviders); | ||
} | ||
|
||
/// <summary> | ||
/// Determines which script should be considered the "primary" entry point script. | ||
/// </summary> | ||
internal static string DeterminePrimaryScriptFile(JObject functionConfig, string[] functionFiles) | ||
{ | ||
if (functionFiles.Length == 1) | ||
{ | ||
// if there is only a single file, that file is primary | ||
return functionFiles[0]; | ||
} | ||
else | ||
{ | ||
// First see if there is an explicit primary file indicated | ||
// in config. If so use that. | ||
string functionPrimary = null; | ||
string scriptFileName = (string)functionConfig["scriptFile"]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This property used to be called "source". We're renaming this to "scriptFile". It's an undocumented property at this point, so we'll be safe in making the breaking change. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep :) |
||
if (!string.IsNullOrEmpty(scriptFileName)) | ||
{ | ||
functionPrimary = functionFiles.FirstOrDefault(p => | ||
string.Compare(Path.GetFileName(p), scriptFileName, StringComparison.OrdinalIgnoreCase) == 0); | ||
} | ||
else | ||
{ | ||
// if there is a "run" file, that file is primary, | ||
// for Node, any index.js file is primary | ||
functionPrimary = functionFiles.FirstOrDefault(p => | ||
Path.GetFileNameWithoutExtension(p).ToLowerInvariant() == "run" || | ||
Path.GetFileName(p).ToLowerInvariant() == "index.js"); | ||
} | ||
|
||
return functionPrimary; | ||
} | ||
} | ||
|
||
private static ScriptType ParseScriptType(string scriptFilePath) | ||
{ | ||
string extension = Path.GetExtension(scriptFilePath).ToLowerInvariant().TrimStart('.'); | ||
|
@@ -729,7 +739,7 @@ internal static bool TryGetFunctionFromException(Collection<FunctionDescriptor> | |
// We use the directory name for the script rather than the full script path itself to ensure | ||
// that we handle cases where the error might be coming from some other script (e.g. an NPM | ||
// module) that is part of the function. | ||
string absoluteScriptPath = Path.GetFullPath(currFunction.Metadata.Source).ToLowerInvariant(); | ||
string absoluteScriptPath = Path.GetFullPath(currFunction.Metadata.ScriptFile).ToLowerInvariant(); | ||
string functionDirectory = Path.GetDirectoryName(absoluteScriptPath); | ||
if (errorStack.Contains(functionDirectory)) | ||
{ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know it would be a breaking change, but looking back, I wish we didn't have this special case at all, as it results in a cliff. I'd rather it fail right away when users only have one file, then mysteriously start failing when you add a second one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that functionFiles contains only the non function.json files, so this case handles the 90% case where there is just a function.json and a single file in the directory, say a DoIt.BAT. We don't want it to fail if there is only a single file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's debatable. My take is that we cause more harm with the 'second source file cliff' than if you force people to follow a (simple) pattern from the get go.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand what you're proposing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean we'd be better off if we had the same requirements in the 1-source-file case as in the n-source-files case. Of course, changing it now is a breaking chance, but we should still consider it. Simpler rules, less magical, less cliff.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's not change this now.