public LanguageDetectorResult Detect(ISourceRepo sourceRepo)
        {
            if (!sourceRepo.FileExists(PythonConstants.RequirementsFileName))
            {
                _logger.LogDebug($"File '{PythonConstants.RequirementsFileName}' does not exist in source repo");
                return(null);
            }

            string runtimeVersion = DetectPythonVersionFromRuntimeFile(sourceRepo);

            if (string.IsNullOrEmpty(runtimeVersion))
            {
                var files = sourceRepo.EnumerateFiles(
                    PythonConstants.PythonFileNamePattern,
                    searchSubDirectories: false);

                if (files == null || !files.Any())
                {
                    _logger.LogDebug($"Files with extension '{PythonConstants.PythonFileNamePattern}' do not exist " +
                                     "in source repo root");
                    return(null);
                }
            }

            runtimeVersion = VerifyAndResolveVersion(runtimeVersion);

            return(new LanguageDetectorResult
            {
                Language = PythonConstants.PythonName,
                LanguageVersion = runtimeVersion,
            });
        }
        internal void ReadSettingsFromFile(IDictionary <string, string> settings)
        {
            if (!_sourceRepo.FileExists(Constants.BuildEnvironmentFileName))
            {
                _logger.LogDebug(
                    $"Could not find file '{Constants.BuildEnvironmentFileName}' to load environment settings.");
                return;
            }

            var lines = _sourceRepo.ReadAllLines(Constants.BuildEnvironmentFileName);

            if (lines == null || lines.Length == 0)
            {
                return;
            }

            foreach (var line in lines)
            {
                // Ignore comments and blank lines
                if (line.StartsWith("#") || string.IsNullOrEmpty(line))
                {
                    continue;
                }

                // Ignore invalid values
                if (NameAndValuePairParser.TryParse(line, out var key, out var value))
                {
                    settings[key] = value;
                }
Example #3
0
        private string DetectPythonVersionFromRuntimeFile(ISourceRepo sourceRepo)
        {
            const string versionPrefix = "python-";

            // Most Python sites will have at least a .py file in the root, but
            // some may not. In that case, let them opt in with the runtime.txt
            // file, which is used to specify the version of Python.
            if (sourceRepo.FileExists(PythonConstants.RuntimeFileName))
            {
                try
                {
                    var content          = sourceRepo.ReadFile(PythonConstants.RuntimeFileName);
                    var hasPythonVersion = content.StartsWith(versionPrefix, StringComparison.OrdinalIgnoreCase);
                    if (!hasPythonVersion)
                    {
                        _logger.LogDebug("Prefix {verPrefix} was not found in file {rtFileName}", versionPrefix, PythonConstants.RuntimeFileName);
                        return(null);
                    }

                    var pythonVersion = content.Remove(0, versionPrefix.Length);
                    _logger.LogDebug("Found version {pyVer} in runtime file", pythonVersion);
                    return(pythonVersion);
                }
                catch (IOException ex)
                {
                    _logger.LogError(ex, "An error occurred while reading file {rtFileName}", PythonConstants.RuntimeFileName);
                }
            }
            else
            {
                _logger.LogDebug("Could not find file '{rtFileName}' in source repo", PythonConstants.RuntimeFileName);
            }

            return(null);
        }
        private bool IsPythonApp(ISourceRepo sourceRepo)
        {
            if (sourceRepo.FileExists(PythonConstants.RequirementsFileName))
            {
                _logger.LogInformation($"Found {PythonConstants.RequirementsFileName} at the root of the repo.");
                return(true);
            }
            else
            {
                _logger.LogInformation(
                    $"Cound not find {PythonConstants.RequirementsFileName} at the root of the repo.");
            }

            var files = sourceRepo.EnumerateFiles(PythonConstants.PythonFileNamePattern, searchSubDirectories: true);

            if (files != null && files.Any())
            {
                _logger.LogInformation(
                    $"Found files with extension '{PythonConstants.PythonFileNamePattern}' " +
                    $"in the repo.");
                return(true);
            }
            else
            {
                _logger.LogInformation(
                    $"Could not find any file with extension '{PythonConstants.PythonFileNamePattern}' " +
                    $"in the repo.");
            }

            return(false);
        }
Example #5
0
        public LanguageDetectorResult Detect(ISourceRepo sourceRepo)
        {
            if (!sourceRepo.FileExists(PhpConstants.ComposerFileName))
            {
                _logger.LogDebug($"File '{PhpConstants.ComposerFileName}' does not exist in source repo");
                return(null);
            }

            dynamic composerFile = null;

            try
            {
                composerFile = sourceRepo.ReadJsonObjectFromFile(PhpConstants.ComposerFileName);
            }
            catch (Exception ex)
            {
                // We just ignore errors, so we leave malformed composer.json files for Composer to handle,
                // not us. This prevents us from erroring out when Composer itself might be able to tolerate
                // some errors in the composer.json file.
                _logger.LogWarning(ex, $"Exception caught while trying to deserialize {PhpConstants.ComposerFileName}");
            }

            string runtimeVersion = VerifyAndResolveVersion(composerFile?.require?.php?.Value as string);

            return(new LanguageDetectorResult
            {
                Language = PhpConstants.PhpName,
                LanguageVersion = runtimeVersion,
            });
        }
Example #6
0
        public string GetSatisfyingSdkVersion(
            ISourceRepo sourceRepo,
            string runtimeVersion,
            IEnumerable <string> availableSdks)
        {
            string sdkVersion;

            if (sourceRepo.FileExists(DotNetCoreConstants.GlobalJsonFileName))
            {
                var globalJsonContent = sourceRepo.ReadFile(
                    Path.Combine(sourceRepo.RootPath, DotNetCoreConstants.GlobalJsonFileName));

                _logger.LogDebug(
                    "Detected presence of global.json file with content {globalJsonContent}",
                    globalJsonContent);

                var globalJsonModel = JsonConvert.DeserializeObject <GlobalJsonModel>(globalJsonContent);
                sdkVersion = GetSatisfyingSdkVersion(globalJsonModel, availableSdks);

                _logger.LogDebug(
                    "Resolved sdk version to {resolvedSdkVersion} based on global.json file and available sdk versions",
                    sdkVersion);
            }
            else
            {
                // As per global.json spec, if a global.json file is not present, then roll forward policy is
                // considered as 'latestMajor'. This can cause end users apps to fail since in this case even prelreease
                // versions are considered. So here we minimize the impact by relying on the runtime version instead.
                // We choose only the 'major' and 'minor' part of the runtime version.
                // For example, 2.1.14 of runtime will result in a latest minor sdk in '1', for example
                // 2.1.202 or 2.1.400
                var version         = new SemVer.Version(runtimeVersion);
                var globalJsonModel = new GlobalJsonModel
                {
                    Sdk = new SdkModel
                    {
                        Version = $"{version.Major}.{version.Minor}.100",

                        // Get latest feature and patch of the version
                        RollForward     = RollForwardPolicy.LatestFeature,
                        AllowPreRelease = true,
                    },
                };

                _logger.LogDebug(
                    "global.json file was not find in the repo, so choosing an sdk version which satisfies the " +
                    "version {defaultSdkVersion}, roll forward policy of {defaultRollForwardPolicy} and " +
                    "allowPrerelease value of {defaultAllowPrerelease}.",
                    globalJsonModel.Sdk.Version,
                    globalJsonModel.Sdk.RollForward,
                    globalJsonModel.Sdk.AllowPreRelease);

                sdkVersion = GetSatisfyingSdkVersion(globalJsonModel, availableSdks);
            }

            return(sdkVersion);
        }
        public LanguageDetectorResult Detect(ISourceRepo sourceRepo)
        {
            var projectFile = _aspNetCoreWebAppProjectFileProvider.GetRelativePathToProjectFile(sourceRepo);

            if (string.IsNullOrEmpty(projectFile))
            {
                return(null);
            }

            var projectFileDoc         = XDocument.Load(new StringReader(sourceRepo.ReadFile(projectFile)));
            var targetFrameworkElement = projectFileDoc.XPathSelectElement(
                DotnetCoreConstants.TargetFrameworkElementXPathExpression);
            var targetFramework = targetFrameworkElement?.Value;

            if (string.IsNullOrEmpty(targetFramework))
            {
                _logger.LogDebug(
                    $"Could not find 'TargetFramework' element in the project file '{projectFile}'.");
                return(null);
            }

            // If a repo explicitly specifies an sdk version, then just use it as it is.
            string languageVersion = null;

            if (sourceRepo.FileExists(DotnetCoreConstants.GlobalJsonFileName))
            {
                var globalJson = GetGlobalJsonObject(sourceRepo);
                var sdkVersion = globalJson?.sdk?.version?.Value as string;
                if (sdkVersion != null)
                {
                    languageVersion = sdkVersion;
                }
            }

            if (string.IsNullOrEmpty(languageVersion))
            {
                languageVersion = DetermineSdkVersion(targetFramework);
            }

            if (languageVersion == null)
            {
                _logger.LogDebug(
                    $"Could not find a {DotnetCoreConstants.LanguageName} version corresponding to 'TargetFramework'" +
                    $" '{targetFramework}'.");
                return(null);
            }

            languageVersion = VerifyAndResolveVersion(languageVersion);

            return(new LanguageDetectorResult
            {
                Language = DotnetCoreConstants.LanguageName,
                LanguageVersion = languageVersion
            });
        }
Example #8
0
        private void TryLogDependencies(string pythonVersion, ISourceRepo repo)
        {
            if (!repo.FileExists(PythonConstants.RequirementsFileName))
            {
                return;
            }

            try
            {
                var deps = repo.ReadAllLines(PythonConstants.RequirementsFileName)
                           .Where(line => !line.TrimStart().StartsWith("#"));
                _logger.LogDependencies(PythonConstants.PlatformName, pythonVersion, deps);
            }
            catch (Exception exc)
            {
                _logger.LogWarning(exc, "Exception caught while logging dependencies");
            }
        }
Example #9
0
        private void TryLogDependencies(string pythonVersion, ISourceRepo repo)
        {
            var customRequirementsTxtPath = this.pythonScriptGeneratorOptions.CustomRequirementsTxtPath;
            var requirementsTxtPath       = customRequirementsTxtPath == null ? PythonConstants.RequirementsFileName : customRequirementsTxtPath;

            if (!repo.FileExists(requirementsTxtPath))
            {
                return;
            }

            try
            {
                var deps = repo.ReadAllLines(requirementsTxtPath)
                           .Where(line => !line.TrimStart().StartsWith("#"));
                this.logger.LogDependencies(PythonConstants.PlatformName, pythonVersion, deps);
            }
            catch (Exception exc)
            {
                this.logger.LogWarning(exc, "Exception caught while logging dependencies");
            }
        }
Example #10
0
        private bool IsPythonApp(ISourceRepo sourceRepo)
        {
            if (sourceRepo.FileExists(PythonConstants.RequirementsFileName))
            {
                _logger.LogInformation($"Found {PythonConstants.RequirementsFileName} at the root of the repo.");
                return(true);
            }
            else
            {
                _logger.LogInformation(
                    $"Cound not find {PythonConstants.RequirementsFileName} at the root of the repo.");
            }

            var searchSubDirectories = !_options.DisableRecursiveLookUp;

            if (!searchSubDirectories)
            {
                _logger.LogDebug("Skipping search for files in sub-directories as it has been disabled.");
            }

            var files = sourceRepo.EnumerateFiles(PythonConstants.PythonFileNamePattern, searchSubDirectories);

            if (files != null && files.Any())
            {
                _logger.LogInformation(
                    $"Found files with extension '{PythonConstants.PythonFileNamePattern}' " +
                    $"in the repo.");
                return(true);
            }
            else
            {
                _logger.LogInformation(
                    $"Could not find any file with extension '{PythonConstants.PythonFileNamePattern}' " +
                    $"in the repo.");
            }

            return(false);
        }
Example #11
0
        /// <summary>
        /// Gets the package json object.
        /// </summary>
        /// <param name="sourceRepo">The source repository.</param>
        /// <param name="logger">The logger of Node.js platform.</param>
        /// <returns>Package json Object.</returns>
        internal static dynamic GetPackageJsonObject(ISourceRepo sourceRepo, ILogger logger)
        {
            if (!sourceRepo.FileExists(NodeConstants.PackageJsonFileName))
            {
                return(null);
            }

            dynamic packageJson = null;

            try
            {
                packageJson = sourceRepo.ReadJsonObjectFromFile(NodeConstants.PackageJsonFileName);
            }
            catch (Exception exc)
            {
                // Leave malformed package.json files for Node.js to handle.
                // This prevents Oryx from erroring out when Node.js itself might be able to tolerate the file.
                logger.LogWarning(
                    exc,
                    $"Exception caught while trying to deserialize {NodeConstants.PackageJsonFileName.Hash()}");
            }

            return(packageJson);
        }
Example #12
0
        /// <summary>
        /// Checks whether or not the given repository is a Hugo application.
        /// </summary>
        /// <param name="sourceRepo">Source repo for the application.</param>
        /// <param name="environment">Environment abstraction.</param>
        /// <returns>True if the app is a Hugo app, false otherwise.</returns>
        public static bool IsHugoApp(ISourceRepo sourceRepo, IEnvironment environment)
        {
            // Check for Hugo environment variables
            var environmentVariables = environment.GetEnvironmentVariables();

            foreach (var key in environmentVariables?.Keys)
            {
                if (key.ToString().StartsWith(HugoEnvironmentVariablePrefix))
                {
                    return(true);
                }
            }

            // Hugo configuration variables: https://gohugo.io/getting-started/configuration/#all-configuration-settings
            var tomlFilePaths = new List <string>();
            var yamlFilePaths = new List <string>();
            var jsonFilePaths = new List <string>();

            // Search for config.toml
            if (sourceRepo.FileExists(NodeConstants.HugoTomlFileName))
            {
                tomlFilePaths.Add(Path.Combine(sourceRepo.RootPath, NodeConstants.HugoTomlFileName));
            }

            // Search for config.yaml
            if (sourceRepo.FileExists(NodeConstants.HugoYamlFileName))
            {
                yamlFilePaths.Add(Path.Combine(sourceRepo.RootPath, NodeConstants.HugoYamlFileName));
            }

            // Search for config.json
            if (sourceRepo.FileExists(NodeConstants.HugoJsonFileName))
            {
                jsonFilePaths.Add(Path.Combine(sourceRepo.RootPath, NodeConstants.HugoJsonFileName));
            }

            if (sourceRepo.DirExists(NodeConstants.HugoConfigFolderName))
            {
                var configSourceRepo = new LocalSourceRepo(Path.Combine(sourceRepo.RootPath, NodeConstants.HugoConfigFolderName));

                // Search for config/*.toml
                tomlFilePaths.AddRange(configSourceRepo.EnumerateFiles("*.toml", true));

                // Search for config/*.yaml
                yamlFilePaths.AddRange(configSourceRepo.EnumerateFiles("*.yaml", true));

                // Search for config/*.json
                jsonFilePaths.AddRange(configSourceRepo.EnumerateFiles("*.json", true));
            }

            foreach (var path in tomlFilePaths)
            {
                var tomlTable = ParserHelper.ParseTomlFile(sourceRepo, path);
                if (tomlTable.Keys
                    .Any(k => HugoConfigurationVariables.Contains(k, StringComparer.OrdinalIgnoreCase)))
                {
                    return(true);
                }
            }

            foreach (var path in yamlFilePaths)
            {
                var yamlNode = ParserHelper.ParseYamlFile(sourceRepo, path);
                if (yamlNode.Children.Keys
                    .Select(k => k.ToString())
                    .Any(k => HugoConfigurationVariables.Contains(k, StringComparer.OrdinalIgnoreCase)))
                {
                    return(true);
                }
            }

            foreach (var path in jsonFilePaths)
            {
                var jObject = ParserHelper.ParseJsonFile(sourceRepo, path);
                if (jObject.Children()
                    .Select(c => c.Path)
                    .Any(c => HugoConfigurationVariables.Contains(c, StringComparer.OrdinalIgnoreCase)))
                {
                    return(true);
                }
            }

            return(false);
        }
        public string GetProjectFile(ISourceRepo sourceRepo)
        {
            if (_probedForProjectFile)
            {
                return(_projectFile);
            }

            var projectEnvVariablePath = _options.Project;

            string projectFile = null;

            if (string.IsNullOrEmpty(projectEnvVariablePath))
            {
                // Check if root of the repo has a .csproj file
                projectFile = sourceRepo
                              .EnumerateFiles($"*.{DotnetCoreConstants.ProjectFileExtensionName}", searchSubDirectories: false)
                              .FirstOrDefault();
            }
            else
            {
                projectEnvVariablePath = projectEnvVariablePath.Trim();
                projectFile            = Path.Combine(sourceRepo.RootPath, projectEnvVariablePath);
                if (!sourceRepo.FileExists(projectFile))
                {
                    _logger.LogWarning($"Could not find the project file '{projectFile}'.");
                    return(null);
                }
            }

            if (projectFile != null)
            {
                if (!IsAspNetCoreWebApplicationProject(sourceRepo, projectFile))
                {
                    return(null);
                }

                return(projectFile);
            }

            // Check if any of the sub-directories has a .csproj file and if that .csproj file has references
            // to typical AspNetCore package references.
            if (projectFile == null)
            {
                var projectFiles = sourceRepo
                                   .EnumerateFiles($"*.{DotnetCoreConstants.ProjectFileExtensionName}", searchSubDirectories: true);

                if (!projectFiles.Any())
                {
                    _logger.LogDebug(
                        $"Could not find any files with extension '{DotnetCoreConstants.ProjectFileExtensionName}' in repo.");
                    return(null);
                }

                var webAppProjects = new List <string>();
                foreach (var file in projectFiles)
                {
                    if (IsAspNetCoreWebApplicationProject(sourceRepo, file))
                    {
                        webAppProjects.Add(file);
                    }
                }

                if (webAppProjects.Count == 0)
                {
                    _logger.LogDebug(
                        "Could not find any ASP.NET Core web application projects. " +
                        $"Found the following project files: '{string.Join(" ", projectFiles)}'");
                    return(null);
                }

                if (webAppProjects.Count > 1)
                {
                    throw new InvalidUsageException(
                              "Ambiguity in selecting an ASP.NET Core web application to build. " +
                              "Found multiple applications: " + string.Join(", ", webAppProjects));
                }

                projectFile = webAppProjects[0];
            }

            // Cache the results
            _probedForProjectFile = true;
            _projectFile          = projectFile;

            return(_projectFile);
        }
Example #14
0
        private bool IsHugoApp(ISourceRepo sourceRepo, out string appDirectory)
        {
            // Hugo configuration variables:
            // https://gohugo.io/getting-started/configuration/#all-configuration-settings
            appDirectory = string.Empty;

            // Search for config.toml
            if (sourceRepo.FileExists(HugoConstants.TomlFileName) &&
                IsHugoTomlFile(sourceRepo, HugoConstants.TomlFileName))
            {
                return(true);
            }

            // Search for config.yml
            if (sourceRepo.FileExists(HugoConstants.YmlFileName) &&
                IsHugoYamlFile(sourceRepo, HugoConstants.YmlFileName))
            {
                return(true);
            }

            // Search for config.yaml
            if (sourceRepo.FileExists(HugoConstants.YamlFileName) &&
                IsHugoYamlFile(sourceRepo, HugoConstants.YamlFileName))
            {
                return(true);
            }

            // Search for config.json
            if (sourceRepo.FileExists(HugoConstants.JsonFileName) &&
                IsHugoYamlFile(sourceRepo, HugoConstants.JsonFileName))
            {
                return(true);
            }

            // NOTE: we do NOT disable looking up into the 'config' folder because it is a special folder
            // from perspective of Hugo where users can have configuration files.
            if (sourceRepo.DirExists(HugoConstants.ConfigFolderName))
            {
                // Search for config/**/*.toml
                var tomlFiles = sourceRepo.EnumerateFiles(
                    "*.toml",
                    searchSubDirectories: true,
                    subDirectoryToSearchUnder: HugoConstants.ConfigFolderName);
                foreach (var tomlFile in tomlFiles)
                {
                    if (IsHugoTomlFile(sourceRepo, tomlFile))
                    {
                        return(true);
                    }
                }

                // Search for config/**/*.yaml and config/**/*.yml
                var yamlFiles = sourceRepo.EnumerateFiles(
                    "*.yaml",
                    searchSubDirectories: true,
                    subDirectoryToSearchUnder: HugoConstants.ConfigFolderName);
                foreach (var yamlFile in yamlFiles)
                {
                    if (IsHugoYamlFile(sourceRepo, yamlFile))
                    {
                        return(true);
                    }
                }

                var ymlFiles = sourceRepo.EnumerateFiles(
                    "*.yml",
                    searchSubDirectories: true,
                    subDirectoryToSearchUnder: HugoConstants.ConfigFolderName);
                foreach (var ymlFile in ymlFiles)
                {
                    if (IsHugoYamlFile(sourceRepo, ymlFile))
                    {
                        return(true);
                    }
                }

                // Search for config/**/*.json
                var jsonFiles = sourceRepo.EnumerateFiles(
                    "*.json",
                    searchSubDirectories: true,
                    subDirectoryToSearchUnder: HugoConstants.ConfigFolderName);
                foreach (var jsonFile in jsonFiles)
                {
                    if (IsHugoJsonFile(sourceRepo, jsonFile))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Example #15
0
        public string GetRelativePathToProjectFile(ISourceRepo sourceRepo)
        {
            if (_probedForProjectFile)
            {
                return(_projectFileRelativePath);
            }

            var projectEnvVariablePath = _options.Project;

            string projectFile = null;

            if (!string.IsNullOrEmpty(projectEnvVariablePath))
            {
                var projectFileWithRelativePath = projectEnvVariablePath.Trim();
                projectFile = Path.Combine(sourceRepo.RootPath, projectFileWithRelativePath);
                if (!sourceRepo.FileExists(projectFile))
                {
                    _logger.LogWarning($"Could not find the project file '{projectFile}'.");
                    throw new InvalidUsageException(
                              $"Could not find the project file '{projectFile}' specified by the environment variable" +
                              $" '{EnvironmentSettingsKeys.Project}' with value '{projectFileWithRelativePath}'. " +
                              "Make sure the path to the project file is relative to the root of the repo. " +
                              "For example: PROJECT=src/Dashboard/Dashboard.csproj");
                }

                // NOTE: Do not check if the project file specified by the end user is a web application since this
                // can be a escape hatch for end users if our logic to determine a web app is incorrect.
                return(projectFileWithRelativePath);
            }

            // Check if root of the repo has a .csproj or a .fsproj file
            projectFile = GetProjectFileAtRoot(sourceRepo, DotNetCoreConstants.CSharpProjectFileExtension) ??
                          GetProjectFileAtRoot(sourceRepo, DotNetCoreConstants.FSharpProjectFileExtension);

            if (projectFile != null)
            {
                if (!IsAspNetCoreWebApplicationProject(sourceRepo, projectFile))
                {
                    return(null);
                }

                return(new FileInfo(projectFile).Name);
            }

            // Check if any of the sub-directories has a .csproj file and if that .csproj file has references
            // to web sdk.
            if (projectFile == null)
            {
                // search for .csproj files
                var projectFiles = GetAllProjectFilesInRepo(
                    sourceRepo,
                    DotNetCoreConstants.CSharpProjectFileExtension);

                if (!projectFiles.Any())
                {
                    _logger.LogDebug(
                        "Could not find any files with extension " +
                        $"'{DotNetCoreConstants.CSharpProjectFileExtension}' in repo.");

                    // search for .fsproj files
                    projectFiles = GetAllProjectFilesInRepo(
                        sourceRepo,
                        DotNetCoreConstants.FSharpProjectFileExtension);

                    if (!projectFiles.Any())
                    {
                        _logger.LogDebug(
                            "Could not find any files with extension " +
                            $"'{DotNetCoreConstants.FSharpProjectFileExtension}' in repo.");
                        return(null);
                    }
                }

                var webAppProjects = new List <string>();
                foreach (var file in projectFiles)
                {
                    if (IsAspNetCoreWebApplicationProject(sourceRepo, file))
                    {
                        webAppProjects.Add(file);
                    }
                }

                if (webAppProjects.Count == 0)
                {
                    _logger.LogDebug(
                        "Could not find any ASP.NET Core web application projects. " +
                        $"Found the following project files: '{string.Join(" ", projectFiles)}'");
                    return(null);
                }

                if (webAppProjects.Count > 1)
                {
                    var projects = string.Join(", ", webAppProjects);
                    throw new InvalidUsageException(
                              "Ambiguity in selecting an ASP.NET Core web application to build. " +
                              $"Found multiple applications: '{projects}'. Use the environment variable " +
                              $"'{EnvironmentSettingsKeys.Project}' to specify the relative path to the project " +
                              "to be deployed.");
                }

                projectFile = webAppProjects[0];
            }

            // Cache the results
            _probedForProjectFile    = true;
            _projectFileRelativePath = GetRelativePathToRoot(projectFile, sourceRepo.RootPath);
            return(_projectFileRelativePath);
        }
Example #16
0
        public LanguageDetectorResult Detect(ISourceRepo sourceRepo)
        {
            bool isNodeApp = false;

            if (sourceRepo.FileExists(NodeConstants.PackageJsonFileName) ||
                sourceRepo.FileExists(NodeConstants.PackageLockJsonFileName) ||
                sourceRepo.FileExists(NodeConstants.YarnLockFileName))
            {
                isNodeApp = true;
            }
            else
            {
                _logger.LogDebug(
                    $"Could not find {NodeConstants.PackageJsonFileName}/{NodeConstants.PackageLockJsonFileName}" +
                    $"/{NodeConstants.YarnLockFileName} in repo");
            }

            if (!isNodeApp)
            {
                // Copying the logic currently running in Kudu:
                var mightBeNode = false;
                foreach (var typicalNodeFile in TypicalNodeDetectionFiles)
                {
                    if (sourceRepo.FileExists(typicalNodeFile))
                    {
                        mightBeNode = true;
                        break;
                    }
                }

                if (mightBeNode)
                {
                    // Check if any of the known iis start pages exist
                    // If so, then it is not a node.js web site otherwise it is
                    foreach (var iisStartupFile in IisStartupFiles)
                    {
                        if (sourceRepo.FileExists(iisStartupFile))
                        {
                            _logger.LogDebug(
                                "App in repo is not a Node.js app as it has the file {iisStartupFile}",
                                iisStartupFile);
                            return(null);
                        }
                    }

                    isNodeApp = true;
                }
                else
                {
                    // No point in logging the actual file list, as it's constant
                    _logger.LogDebug("Could not find typical Node.js files in repo");
                }
            }

            if (isNodeApp)
            {
                var packageJson = NodePlatform.GetPackageJsonObject(sourceRepo, _logger);
                var nodeVersion = DetectNodeVersion(packageJson);

                return(new LanguageDetectorResult
                {
                    Language = NodeConstants.NodeJsName,
                    LanguageVersion = nodeVersion,
                });
            }
            else
            {
                _logger.LogDebug("App in repo is not a Node.js app");
            }

            return(null);
        }