diff --git a/src/pfe/file-watcher/server/src/controllers/projectsController.ts b/src/pfe/file-watcher/server/src/controllers/projectsController.ts index dcc8ae17f..ef7971060 100644 --- a/src/pfe/file-watcher/server/src/controllers/projectsController.ts +++ b/src/pfe/file-watcher/server/src/controllers/projectsController.ts @@ -146,7 +146,7 @@ export async function createProject(req: ICreateProjectParams): Promise { const projectMetadata = getProjectMetadataById(projectID); const projectInfo: ProjectInfo = await getProjectInfoFromFile(projectMetadata.infoFile); const projectLocation = projectInfo.location; - const projectName = projectLocation.split("/").pop(); + const projectName = utils.getProjectNameFromPath(projectLocation); logger.logProjectTrace("Retrieved project information for project " + projectMetadata.infoFile, projectID); logger.logProjectTrace(JSON.stringify(projectInfo), projectID); @@ -1154,7 +1154,7 @@ export function saveProjectInfo(projectID: string, projectInfo: ProjectInfo, sav const projectJSON = JSON.stringify(projectInfo); const infoFile = getProjectMetadataById(projectID).infoFile; projectInfoCache[infoFile] = projectJSON; - const projectName = projectInfo.location.split("/").pop(); + const projectName = utils.getProjectNameFromPath(projectInfo.location); logger.logProjectTrace(JSON.stringify(projectInfoCache), projectID); if (saveIntoJsonFile) { fs.writeFile(infoFile, projectJSON, "utf8", (err) => { diff --git a/src/pfe/file-watcher/server/src/extensions/projectExtensions.ts b/src/pfe/file-watcher/server/src/extensions/projectExtensions.ts index 1f8dc1c99..6ce80fdb2 100644 --- a/src/pfe/file-watcher/server/src/extensions/projectExtensions.ts +++ b/src/pfe/file-watcher/server/src/extensions/projectExtensions.ts @@ -164,7 +164,7 @@ export function getAllProjectTypes(): Array { async function getExtensionProjectHandler(projectInfo: ProjectInfo): Promise { const key = projectInfo.projectID; - const projectName = path.basename(projectInfo.location); + const projectName = utils.getProjectNameFromPath(projectInfo.location); let handler = extensionProjectHandlers[key]; // is there an extension handler for the project? diff --git a/src/pfe/file-watcher/server/src/projects/OdoExtensionProject.ts b/src/pfe/file-watcher/server/src/projects/OdoExtensionProject.ts index c7d239e78..65e7a38fa 100644 --- a/src/pfe/file-watcher/server/src/projects/OdoExtensionProject.ts +++ b/src/pfe/file-watcher/server/src/projects/OdoExtensionProject.ts @@ -22,6 +22,7 @@ import { ProjectInfo, BuildLog, AppLog, ProjectCapabilities, defaultProjectCapab import { Validator } from "./Validator"; import { IExtensionProject } from "../extensions/IExtensionProject"; import { IFileChangeEvent } from "../utils/fileChanges"; +import { getProjectNameFromPath } from "../utils/utils"; // skeleton for the logs originated from the extension json const logsOrigin: logHelper.ILogTypes = { @@ -207,7 +208,7 @@ export class OdoExtensionProject implements IExtensionProject { */ getContainerName = async (projectID: string, projectLocation: string): Promise => { let podName: string = undefined; - const projectName: string = path.basename(projectLocation); + const projectName: string = getProjectNameFromPath(projectLocation); const componentName: string = await projectUtil.getComponentName(projectName); const args: string[] = [ projectLocation, @@ -246,7 +247,7 @@ export class OdoExtensionProject implements IExtensionProject { let appName: string = undefined; const projectInfo: ProjectInfo = await projectUtil.getProjectInfo(projectID); const projectLocation = projectInfo.location; - const projectName = path.basename(projectLocation); + const projectName = getProjectNameFromPath(projectLocation); const args: string[] = [ projectLocation, "", @@ -284,7 +285,7 @@ export class OdoExtensionProject implements IExtensionProject { let appPort: string = undefined; const projectInfo: ProjectInfo = await projectUtil.getProjectInfo(projectID); const projectLocation = projectInfo.location; - const projectName = path.basename(projectLocation); + const projectName = getProjectNameFromPath(projectLocation); const componentName: string = await projectUtil.getComponentName(projectName); const args: string[] = [ projectLocation, @@ -323,7 +324,7 @@ export class OdoExtensionProject implements IExtensionProject { let appBaseURL: string = undefined; const projectInfo: ProjectInfo = await projectUtil.getProjectInfo(projectID); const projectLocation = projectInfo.location; - const projectName = path.basename(projectLocation); + const projectName = getProjectNameFromPath(projectLocation); const componentName: string = await projectUtil.getComponentName(projectName); const args: string[] = [ projectLocation, diff --git a/src/pfe/file-watcher/server/src/projects/ShellExtensionProject.ts b/src/pfe/file-watcher/server/src/projects/ShellExtensionProject.ts index 4ceeead40..d63b34f1b 100644 --- a/src/pfe/file-watcher/server/src/projects/ShellExtensionProject.ts +++ b/src/pfe/file-watcher/server/src/projects/ShellExtensionProject.ts @@ -14,6 +14,7 @@ import fs from "fs-extra"; import * as path from "path"; import * as projectUtil from "./projectUtil"; +import { getProjectNameFromPath } from "../utils/utils"; import { Operation } from "./operation"; import { ProjectInfo, BuildLog, AppLog, ProjectCapabilities, defaultProjectCapabilities } from "./Project"; import { Validator } from "./Validator"; @@ -112,7 +113,7 @@ export class ShellExtensionProject implements IExtensionProject { private setLanguage = async (projectInfo: ProjectInfo): Promise => { const logDir = await logHelper.getLogDir( - projectInfo.projectID, path.basename(projectInfo.location)); + projectInfo.projectID, getProjectNameFromPath(projectInfo.location)); const args = [ projectInfo.location, diff --git a/src/pfe/file-watcher/server/src/projects/Validator.ts b/src/pfe/file-watcher/server/src/projects/Validator.ts index 7e8fe117f..90dcebf23 100644 --- a/src/pfe/file-watcher/server/src/projects/Validator.ts +++ b/src/pfe/file-watcher/server/src/projects/Validator.ts @@ -57,7 +57,7 @@ export class Validator { async validateRequiredFiles (requiredFiles: string[]): Promise { if (requiredFiles) { const projectID = this.projectID; - const projectName = this.location.split("/").pop(); + const projectName = utils.getProjectNameFromPath(this.location); const OR_SPLIT = "|"; try { @@ -179,7 +179,7 @@ export class Validator { */ sendResult(): void { const projectID = this.projectID; - const projectName = this.location.split("/").pop(); + const projectName = utils.getProjectNameFromPath(this.location); logger.logProjectInfo("Sending validation result", projectID, projectName); io.emitOnListener("projectValidated", this.result()); } diff --git a/src/pfe/file-watcher/server/src/projects/actions.ts b/src/pfe/file-watcher/server/src/projects/actions.ts index 5c132e14e..71897f298 100644 --- a/src/pfe/file-watcher/server/src/projects/actions.ts +++ b/src/pfe/file-watcher/server/src/projects/actions.ts @@ -57,7 +57,7 @@ export const validate = async function(args: IProjectActionParams): Promise<{ op "projectType": projectType, "location": location } as ProjectInfo; - const projectName = location.split("/").pop(); + const projectName = utils.getProjectNameFromPath(location); if (args.extensionID) { projectInfo.extensionID = args.extensionID; } @@ -131,7 +131,7 @@ export const enableautobuild = async function (args: IProjectActionParams): Prom async function enableAndBuild(projectInfo: ProjectInfo): Promise { const projectHandler = await projectExtensions.getProjectHandler(projectInfo); const projectID = projectInfo.projectID; - const projectName = projectInfo.location.split("/").pop(); + const projectName = utils.getProjectNameFromPath(projectInfo.location); if (projectHandler.hasOwnProperty("setAutoBuild")) { const operation = new Operation("enableautobuild", projectInfo); diff --git a/src/pfe/file-watcher/server/src/projects/projectUtil.ts b/src/pfe/file-watcher/server/src/projects/projectUtil.ts index 69c867df5..e4d0913c3 100644 --- a/src/pfe/file-watcher/server/src/projects/projectUtil.ts +++ b/src/pfe/file-watcher/server/src/projects/projectUtil.ts @@ -104,7 +104,7 @@ export async function containerCreate(operation: Operation, script: string, comm const event = "projectCreation"; const projectLocation = operation.projectInfo.location; const projectID = operation.projectInfo.projectID; - const projectName = projectLocation.split("/").pop(); + const projectName = utils.getProjectNameFromPath(projectLocation); const projectType = operation.projectInfo.projectType; if (projectList.indexOf(projectID) === -1) projectList.push(projectID); @@ -211,7 +211,7 @@ export async function containerUpdate(operation: Operation, script: string, comm const projectLocation = operation.projectInfo.location; const projectID = operation.projectInfo.projectID; - const projectName = projectLocation.split("/").pop(); + const projectName = utils.getProjectNameFromPath(projectLocation); const projectType = operation.projectInfo.projectType; logger.logProjectInfo("Updating container for " + operation.projectInfo.projectType + " project " + projectLocation, projectID, projectName); operation.containerName = await getContainerName(operation.projectInfo); @@ -316,7 +316,7 @@ export async function containerUpdate(operation: Operation, script: string, comm async function executeBuildScript(operation: Operation, script: string, args: Array, event: string): Promise { const projectID = operation.projectInfo.projectID; const projectLocation = operation.projectInfo.location; - const projectName = projectLocation.split("/").pop(); + const projectName = utils.getProjectNameFromPath(projectLocation); const projectInfo = { operationId: operation.operationId, projectID: operation.projectInfo.projectID @@ -612,7 +612,7 @@ export async function getProjectMavenSettings(projectInfo: ProjectInfo): Promise export async function getProjectLogs(projectInfo: ProjectInfo): Promise { const projectID = projectInfo.projectID; const projectLocation = projectInfo.location; - const projectName = projectLocation.split("/").pop(); + const projectName = utils.getProjectNameFromPath(projectLocation); const projectType = projectInfo.projectType; const projectLogDir = await logHelper.getLogDir(projectID, projectName); const logDirectory = path.join(projectConstants.projectsLogDir, projectLogDir); @@ -655,7 +655,7 @@ export async function getProjectLogs(projectInfo: ProjectInfo): Promise { const projectID = projectInfo.projectID; - const projectName = projectInfo.location.split("/").pop(); + const projectName = utils.getProjectNameFromPath(projectInfo.location); const containerName = await getContainerName(projectInfo); const imagePushRegistry = projectInfo.deploymentRegistry; logger.logProjectInfo("containerDelete: Kill running processes and remove container... ", projectID, projectName); @@ -725,7 +725,7 @@ export function getLogName(projectID: string, projectLocation: string): string { const hash = crypto.createHash("sha1", "utf8").update(projectLocation); let logName = projectConstants.containerPrefix + projectID + "-" + hash.digest("hex"); - const projectName = projectLocation.split("/").pop(); + const projectName = utils.getProjectNameFromPath(projectLocation); if (process.env.IN_K8 === "true" && logName.length > 53) { logName = logName.substring(0, 53); @@ -751,7 +751,7 @@ export function getDefaultContainerName(projectID: string, projectLocation: stri } // Sanitize project name to ensure project name only supports lower case letter and number - const projectNameOrigin: string = path.basename(projectLocation); + const projectNameOrigin: string = utils.getProjectNameFromPath(projectLocation); const letterNumber: RegExp = /[A-Za-z0-9]/; const upperCaseLetter: RegExp = /[A-Z]/; const defaultProjectName: string = "cw"; @@ -1249,7 +1249,7 @@ export async function runScript(projectInfo: ProjectInfo, script: string, comman const containerName = await getContainerName(projectInfo); const logName = getLogName(projectInfo.projectID, projectInfo.location); const logDir = await logHelper.getLogDir(projectInfo.projectID, projectInfo.projectName); - const projectName = path.basename(projectInfo.location); + const projectName = utils.getProjectNameFromPath(projectInfo.location); let args = [projectInfo.location, LOCAL_WORKSPACE, projectID, command, containerName, String(projectInfo.autoBuildEnabled), logName, projectInfo.startMode, projectInfo.debugPort, "NONE", logDir]; @@ -1290,7 +1290,7 @@ export async function buildAndRun(operation: Operation, command: string): Promis const projectLocation = operation.projectInfo.location; const projectID = operation.projectInfo.projectID; - const projectName = projectLocation.split("/").pop(); + const projectName = utils.getProjectNameFromPath(projectLocation); if (projectList.indexOf(projectID) === -1) projectList.push(projectID); @@ -1446,7 +1446,7 @@ export async function buildAndRun(operation: Operation, command: string): Promis */ async function containerBuildAndRun(event: string, buildInfo: BuildRequest, operation: Operation): Promise { const normalizedProjectLocation = path.resolve(buildInfo.projectLocation); - const projectName = normalizedProjectLocation.split("/").reverse()[0]; + const projectName = utils.getProjectNameFromPath(normalizedProjectLocation); const logDir = await logHelper.getLogDir(buildInfo.projectID, projectName); const dockerBuildLog = path.resolve(buildInfo.projectLocation + "/../.logs/" + logDir, logHelper.buildLogs.dockerBuild + logHelper.logExtension); if (process.env.IN_K8 === "true") { @@ -1668,7 +1668,7 @@ async function containerBuildAndRun(event: string, buildInfo: BuildRequest, oper */ async function runLocalContainer(buildInfo: BuildRequest): Promise { const normalizedProjectLocation = path.resolve(buildInfo.projectLocation); - const projectName = normalizedProjectLocation.split("/").reverse()[0]; + const projectName = utils.getProjectNameFromPath(normalizedProjectLocation); const logDir = await logHelper.getLogDir(buildInfo.projectID, projectName); const appLog = path.resolve(buildInfo.projectLocation + "/../.logs/" + logDir, logHelper.appLogs.app + logHelper.logExtension); try { @@ -1799,7 +1799,7 @@ export async function isApplicationPodUp(buildInfo: BuildRequest, projectName: s export async function removeProject(projectInfo: ProjectInfo): Promise { const projectID = projectInfo.projectID; - const projectName = projectInfo.location.split("/").pop(); + const projectName = utils.getProjectNameFromPath(projectInfo.location); const containerName = await getContainerName(projectInfo); logger.logProjectInfo("removeProject: Kill running processes and remove container... ", projectID, projectName); logger.logProjectInfo("Project ID: " + projectInfo.projectID, projectID, projectName); @@ -1903,7 +1903,7 @@ async function getPODInfoAndSendToPortal(operation: Operation, event: string = " const projectInfo = operation.projectInfo; const projectLocation = projectInfo.location; const projectID = projectInfo.projectID; - const projectName = projectLocation.split("/").pop(); + const projectName = utils.getProjectNameFromPath(projectLocation); const keyValuePair: UpdateProjectInfoPair = { key: "buildRequest", value: false @@ -2203,7 +2203,7 @@ export async function updateDetailedAppStatus(projectID: string, ip: string, por export async function exposeOverIngress(projectInfo: ProjectInfo, appPort?: number): Promise { if (process.env.IN_K8) { const projectID = projectInfo.projectID; - const projectName = projectInfo.location.split("/").pop(); + const projectName = utils.getProjectNameFromPath(projectInfo.location); projectInfo.appBaseURL = await kubeutil.exposeOverIngress(projectID, projectName, projectInfo.isHttps, appPort, projectInfo.appBaseURL); await projectsController.saveProjectInfo(projectID, projectInfo, true); } diff --git a/src/pfe/file-watcher/server/src/utils/kubeutil.ts b/src/pfe/file-watcher/server/src/utils/kubeutil.ts index 71b6290cf..2676543f3 100644 --- a/src/pfe/file-watcher/server/src/utils/kubeutil.ts +++ b/src/pfe/file-watcher/server/src/utils/kubeutil.ts @@ -21,6 +21,7 @@ import * as processManager from "./processManager"; import { ProcessResult } from "./processManager"; import { ProjectInfo } from "../projects/Project"; import * as logHelper from "../projects/logHelper"; +import { getProjectNameFromPath } from "./utils"; const k8s = require("@kubernetes/client-node"); // tslint:disable-line:no-require-imports @@ -90,13 +91,13 @@ export async function getApplicationContainerInfo(projectInfo: ProjectInfo, oper if (!projectInfo.compositeAppName) { return undefined; } - const componentName = path.basename(projectInfo.location); + const componentName = getProjectNameFromPath(projectInfo.location); releaseLabel = "deploymentconfig=" + "cw-" + componentName + "-" + projectInfo.compositeAppName; } else if (projectInfo.projectType == "odo-devfile") { - const componentName = path.basename(projectInfo.location); + const componentName = getProjectNameFromPath(projectInfo.location); releaseLabel = "component=" + "cw-" + componentName; } - const projectName = path.basename(projectLocation); + const projectName = getProjectNameFromPath(projectLocation); // Before deploying the application, we added a release label to the deployment, pod, and service, // Use that to get the application's pod and service names. @@ -127,7 +128,7 @@ export async function getApplicationContainerInfo(projectInfo: ProjectInfo, oper logger.logProjectInfo("Pod name was not found while looking up service information for project.", projectID, projectName); } } catch (err) { - logger.logProjectError("Failed to get the pod name for: " + path.basename(projectLocation), projectID, projectName); + logger.logProjectError("Failed to get the pod name for: " + getProjectNameFromPath(projectLocation), projectID, projectName); logger.logProjectError(err, projectID, projectName); } @@ -292,7 +293,7 @@ export async function isContainerActive(containerName: string, projectInfo?: Pro try { let releaseLabel = "release=" + containerName; if (projectInfo && ["odo", "odo-devfile"].includes(projectInfo.projectType)) { - const componentName = path.basename(projectInfo.location); + const componentName = getProjectNameFromPath(projectInfo.location); releaseLabel = projectInfo.projectType === "odo" ? "deploymentconfig=" + "cw-" + componentName + "-" + projectInfo.compositeAppName : "component=" + "cw-" + componentName; diff --git a/src/pfe/file-watcher/server/src/utils/logger.ts b/src/pfe/file-watcher/server/src/utils/logger.ts index 9a76bdd58..53c6b3dee 100644 --- a/src/pfe/file-watcher/server/src/utils/logger.ts +++ b/src/pfe/file-watcher/server/src/utils/logger.ts @@ -15,6 +15,7 @@ import * as path from "path"; import { promisify } from "util"; import * as constants from "../projects/constants"; import * as stackTrace from "stack-trace"; +import { getProjectNameFromPath } from "./utils"; const chalk = require("chalk"); // tslint:disable-line:no-require-imports const GENERAL_LOG_FILE_NAME = "Turbine.log"; @@ -101,7 +102,7 @@ export async function getProjectNameByProjectID(projectID: string): Promise> { return undefined; } } + +/** + * Get the projectName from a path + * + * @param location The project's location + */ +export function getProjectNameFromPath(location: string): string { + const splitPaths = location.split("/"); + const cwIndex = splitPaths.indexOf("codewind-workspace"); + if (cwIndex === -1) { + logger.logError("Unable to get project name from path: codewind-workspace isn't in the path"); + // Fall back to old method if codewind-workspace isn't in the path + return path.basename(location); + } + // Project name is the directory after codewind-workspace + const projectName = splitPaths[cwIndex + 1]; + return projectName; +} diff --git a/src/pfe/file-watcher/server/test/unit-test/tests/projectUtil.module.test.ts b/src/pfe/file-watcher/server/test/unit-test/tests/projectUtil.module.test.ts index 8c31ddd09..0258eeb7a 100644 --- a/src/pfe/file-watcher/server/test/unit-test/tests/projectUtil.module.test.ts +++ b/src/pfe/file-watcher/server/test/unit-test/tests/projectUtil.module.test.ts @@ -449,4 +449,4 @@ export function projectUtilTestModule(): void { }); } }); -} \ No newline at end of file +} diff --git a/src/pfe/file-watcher/server/test/unit-test/tests/utils.module.test.ts b/src/pfe/file-watcher/server/test/unit-test/tests/utils.module.test.ts index 68b664855..8a34ce18e 100644 --- a/src/pfe/file-watcher/server/test/unit-test/tests/utils.module.test.ts +++ b/src/pfe/file-watcher/server/test/unit-test/tests/utils.module.test.ts @@ -362,4 +362,35 @@ export function utilsTestModule(): void { } }); + describe("getProjectNameFromPath", () => { + const tests = [ + { + title: "should return 'projectName' when it's the directory after 'codewind-workspace'", + path: '/codewind-workspace/projectName', + want: 'projectName', + }, + { + title: "should return 'projectName' when the path is normalized", + path: path.resolve('/codewind-workspace/projectName'), + want: 'projectName', + }, + { + title: "should return 'projectName' when subdirectories are given", + path: path.resolve('/codewind-workspace/projectName/templates/default'), + want: 'projectName', + }, + { + title: "returns 'finalDir' as 'codewind-workspace' isn't in the path", + path: path.resolve('/projectName/templates/default/finalDir'), + want: 'finalDir', + }, + ]; + tests.forEach(({ title, path, want }) => { + it(`should return '${want}' when the input is '${path}'`, () => { + const got = utils.getProjectNameFromPath(path); + expect(got).to.equal(want); + }); + }); + }); + } diff --git a/src/pfe/portal/modules/FileWatcher.js b/src/pfe/portal/modules/FileWatcher.js index 1390a85ce..7c59cd2ae 100644 --- a/src/pfe/portal/modules/FileWatcher.js +++ b/src/pfe/portal/modules/FileWatcher.js @@ -736,7 +736,11 @@ function createProjectActionForBuildAndRun(project, settings) { autoBuild, ports, } = project; - const location = project.projectPath(); + + let location = project.projectPath(); + if (extension && extension.projectSubDirectory) { + location = path.join(location, extension.projectSubDirectory); + } const projectAction = { projectID, diff --git a/src/pfe/portal/modules/Templates.js b/src/pfe/portal/modules/Templates.js index d1ec34804..bb3f737ed 100644 --- a/src/pfe/portal/modules/Templates.js +++ b/src/pfe/portal/modules/Templates.js @@ -326,7 +326,7 @@ async function constructRepositoryObject(url, description, name, isRepoProtected } if (gitCredentials) { if (gitCredentials.username) { - repository.authentication = { username: gitCredentials.username }; + repository.authentication = { username: gitCredentials.username }; } else if (gitCredentials.personalAccessToken) { repository.authentication = {}; } @@ -503,6 +503,9 @@ async function getTemplatesFromRepo(repository, gitCredentials) { if (summary.projectStyle) { template.projectStyle = summary.projectStyle; } + if (summary.subDirectory || summary.subDirectory === "") { + template.subDirectory = summary.subDirectory; + } if (repository.name) { template.source = repository.name; } diff --git a/src/pfe/portal/routes/projects/bind.route.js b/src/pfe/portal/routes/projects/bind.route.js index 3390d1ac6..713ba7db2 100644 --- a/src/pfe/portal/routes/projects/bind.route.js +++ b/src/pfe/portal/routes/projects/bind.route.js @@ -102,8 +102,16 @@ async function bindStart(req, res) { let extension = user.extensionList.getExtensionForProjectType(projectType); if (extension) { projectDetails.extension = extension; - if (extension.config.needsMount && !global.codewind.RUNNING_IN_K8S) + if (extension.config.needsMount && !global.codewind.RUNNING_IN_K8S) { projectDetails.workspace = global.codewind.MOUNTED_WORKSPACE; + } + + const allTemplates = user.templates.getTemplates(false); + // Check the template for this project to see if it has a subDirectory field + const subDirectory = getSubDirectoryFromTemplate(allTemplates, projectType, language); + // Add the subdirectory to the directory path so we sync the correct path to file-watcher + // For open-liberty it'll be something like /codewind-workspace/openlib/templates/default + projectDetails.extension.projectSubDirectory = subDirectory; } } @@ -125,9 +133,9 @@ async function bindStart(req, res) { try { let tempDirName = path.join(global.codewind.CODEWIND_WORKSPACE, global.codewind.CODEWIND_TEMP_WORKSPACE); let dirName = newProject.projectPath(); - await fs.mkdir(dirName); + await fs.ensureDir(dirName); let tempProjPath = path.join(tempDirName, newProject.name); - await fs.mkdir(tempProjPath); + await fs.ensureDir(tempProjPath); newProject.workspaceDir = dirName; log.debug(`Creating directory in ${dirName} and ${tempDirName}`); @@ -209,19 +217,19 @@ async function uploadEnd(req, res) { const timeStamp = req.sanitizeBody('timeStamp'); const IFileChangeEvent = []; const user = req.cw_user; - + let project; let pathToTempProj; let directoriesToDelete; let filesToDelete; - + try { project = user.projectList.retrieveProject(projectID); if (!project) { res.sendStatus(404); return; } - + pathToTempProj = path.join(global.codewind.CODEWIND_WORKSPACE, global.codewind.CODEWIND_TEMP_WORKSPACE, project.name); const tempProjectExists = await fs.pathExists(pathToTempProj); if (modifiedList.length === 0 && !tempProjectExists) { @@ -255,13 +263,13 @@ async function uploadEnd(req, res) { } res.sendStatus(200); - + } catch (err) { log.error(err); res.status(500).send(err); return; } - + try { const wasProjectChanged = directoriesToDelete.length > 0 || filesToDelete.length > 0 @@ -529,7 +537,7 @@ router.get('/api/v1/projects/:id/fileList', validateReq, async (req, res) => { return; } const pathToTempProj = path.join(global.codewind.CODEWIND_WORKSPACE, global.codewind.CODEWIND_TEMP_WORKSPACE, project.name); - + const files = await recursivelyListFilesOrDirectories(false, pathToTempProj); res.status(200).send(files); } catch (err) { @@ -539,4 +547,14 @@ router.get('/api/v1/projects/:id/fileList', validateReq, async (req, res) => { }); +function getSubDirectoryFromTemplate(templates, projectType, language) { + // Use the first template that matches the filter + const [{ subDirectory }] = templates.filter(template => ( + template.projectType === projectType && + template.language === language + )); + + return subDirectory; +} + module.exports = router; diff --git a/test/src/unit/routes/projects/bind.route.test.js b/test/src/unit/routes/projects/bind.route.test.js index 266520637..9242ce4ba 100644 --- a/test/src/unit/routes/projects/bind.route.test.js +++ b/test/src/unit/routes/projects/bind.route.test.js @@ -252,6 +252,42 @@ describe('bind.route.js', () => { }); }); }); + describe('getSubDirectoryFromTemplate(templates, projectType, language)', () => { + const getSubDirectoryFromTemplate = bind.__get__('getSubDirectoryFromTemplate'); + const templates = [ + { + label: 'OpenShift Devfiles NodeJS Runtime', + description: 'Stack with NodeJS 12', + language: 'nodejs', + url: 'https://github.com/odo-devfiles/nodejs-ex', + projectType: 'odo-devfile', + subDirectory: '', + projectStyle: 'OpenShift Devfiles', + source: 'OpenShift Devfile templates', + sourceURL: 'file:///codewind-workspace/.extensions/codewind-odo-extension-devfile/templates/index.json', + }, + { + label: 'OpenShift Devfiles Open Liberty', + description: 'Open Liberty microservice in Java', + language: 'java-openliberty', + url: 'https://github.com/OpenLiberty/application-stack', + projectType: 'odo-devfile', + subDirectory: '/templates/default', + projectStyle: 'OpenShift Devfiles', + source: 'OpenShift Devfile templates', + sourceURL: 'file:///codewind-workspace/.extensions/codewind-odo-extension-devfile/templates/index.json', + }, + ]; + + it('returns the subDirectory when one exists', () => { + const subDirectory = getSubDirectoryFromTemplate(templates, 'odo-devfile', 'java-openliberty'); + subDirectory.should.equal('/templates/default'); + }); + it('returns an empty string when the subDirectory is empty', () => { + const subDirectory = getSubDirectoryFromTemplate(templates, 'odo-devfile', 'nodejs'); + subDirectory.should.equal(''); + }); + }); }); function createFilesFromArray(directory, fileArray) {