diff --git a/assertions/index.ts b/assertions/index.ts index 76febd25..ed95714c 100644 --- a/assertions/index.ts +++ b/assertions/index.ts @@ -7,6 +7,7 @@ import { DirectoryExist } from "./directoryExist"; import { FileExist } from "./fileExist"; import { DirectoryNotEmpty } from "./directoryNotEmpty"; import { FileContains } from "./fileContains"; +import { RepositoryIsClean } from "./repositoryIsClean"; export class Assertions { @@ -40,4 +41,9 @@ export class Assertions { FileContains.run(filepath, content); return this; } + + public repositoryIsClean(directory: string): Assertions { + RepositoryIsClean.run(directory); + return this; + } } \ No newline at end of file diff --git a/assertions/repositoryIsClean.ts b/assertions/repositoryIsClean.ts new file mode 100644 index 00000000..83e45ae2 --- /dev/null +++ b/assertions/repositoryIsClean.ts @@ -0,0 +1,12 @@ +import * as child_process from "child_process"; + +export class RepositoryIsClean { + public static run(directory: string): void { + let process = child_process.spawnSync("git status -s", { shell: true, cwd: directory }); + if(process.status != 0) { + throw new Error("'git status -s' execution in directory " + directory + " returned error.") + } else if(process.stdout.toString()) { + throw new Error("Repository in directory " + directory + " is not clean. Current Status: " + process.stdout.toString()); + } + } +} diff --git a/documentation/Functions.md b/documentation/Functions.md index 49b93ea6..7f34a462 100644 --- a/documentation/Functions.md +++ b/documentation/Functions.md @@ -6,6 +6,7 @@ The following functions are already implemented: * createDevon4jProject * buildJava * createFile +* cloneRepository *** @@ -105,4 +106,17 @@ A placeholder is optional. If you do not define a placeholder, the content in th Please try not to use custom placeholders. Keep in mind that you might want to build the project before changing them. Custom placeholders with a comment-syntax (e.g. "//PLACEHOLDER") will be removed by the console-environment and others might cause errors. + +*** + +### cloneRepository +#### parameter +1. Path into which the repository is to be cloned, relative to workspace. +2. Git repository URL +#### example +cloneRepository("", "https://github.com/devonfw-forge/tutorial-compiler.git") +Repository will be cloned directly into the workspace directory. + +cloneRepository("devonfw-forge", "https://github.com/devonfw-forge/tutorial-compiler.git") +Repository will be cloned into a newly created subdirectory devonfw-forge. *** \ No newline at end of file diff --git a/runners/console/index.ts b/runners/console/index.ts index ae6a4341..18fca0f4 100644 --- a/runners/console/index.ts +++ b/runners/console/index.ts @@ -148,6 +148,18 @@ export class Console extends Runner { return result; } + runCloneRepository(step: Step, command: Command): RunResult { + let result = new RunResult(); + result.returnCode = 0; + + let directorypath = path.join(this.getWorkingDirectory(), "devonfw", "workspaces", "main", command.parameters[0]); + + this.createFolder(directorypath, true); + this.executeCommandSync("git clone " + command.parameters[1], directorypath, result); + + return result; + } + async assertInstallDevonfwIde(step: Step, command: Command, result: RunResult) { let installedTools = command.parameters[0]; @@ -231,6 +243,19 @@ export class Console extends Runner { .fileContains(filepath, content); } + async assertCloneRepository(step: Step, command: Command, result: RunResult) { + let repository = command.parameters[1]; + let repoName = repository.slice(repository.lastIndexOf("/"), -4); + let directorypath = path.join(this.getWorkingDirectory(), "devonfw", "workspaces", "main", command.parameters[0], repoName); + + new Assertions() + .noErrorCode(result) + .noException(result) + .directoryExits(path.join(this.getWorkingDirectory(), "devonfw", "workspaces", "main", command.parameters[0], repoName)) + .directoryNotEmpty(path.join(this.getWorkingDirectory(), "devonfw", "workspaces", "main", command.parameters[0], repoName)) + .repositoryIsClean(directorypath); + } + private executeCommandSync(command: string, directory: string, result: RunResult, input?: string) { if(result.returnCode != 0) return; diff --git a/runners/katacoda/index.ts b/runners/katacoda/index.ts index fd7fdc54..8bac4436 100644 --- a/runners/katacoda/index.ts +++ b/runners/katacoda/index.ts @@ -228,6 +228,25 @@ export class Katacoda extends Runner { } + runCloneRepository(step: Step, command: Command): RunResult { + + let cdCommand = this.changeCurrentDir(path.join("/root", "devonfw", "workspaces", "main")); + let directoryPath = ""; + if(command.parameters[0].trim()) { + directoryPath = path.join(command.parameters[0]).replace(/\\/g, "/"); + this.currentDir = path.join(this.currentDir, directoryPath); + } + + + this.steps.push({ + "title": "Clones Repository " + command.parameters[1], + "text": "step" + this.stepsCount + ".md" + }); + + this.renderTemplate("cloneRepository.md", this.outputPathTutorial + "step" + (this.stepsCount++) + ".md", { text: step.text, textAfter: step.textAfter, cdCommand: cdCommand, directoryPath: directoryPath, repository: command.parameters[1] }); + return null; + } + private renderTemplate(name: string, targetPath: string, variables) { let template = fs.readFileSync(path.join(this.getRunnerDirectory(),"templates", name), 'utf8'); let result = ejs.render(template, variables); diff --git a/runners/katacoda/templates/cloneRepository.md b/runners/katacoda/templates/cloneRepository.md new file mode 100644 index 00000000..626111ca --- /dev/null +++ b/runners/katacoda/templates/cloneRepository.md @@ -0,0 +1,17 @@ +<%= text; %> + +<%= cdCommand; %> + +<% if (directoryPath) { %> +If the parent directories aren't already in the project, 'mkdir -p' will create them for you. + +`mkdir -p <%= directoryPath; %>`{{execute}} + +`cd <%= directoryPath; %>`{{execute}} +<% } %> + +Now clone the repository to your local directory. + +`git clone <%= repository; %>`{{execute}} + +<%= textAfter; %> \ No newline at end of file