diff --git a/.vscode/license.code-snippets b/.vscode/license.code-snippets index c08aeabd54..954523a241 100644 --- a/.vscode/license.code-snippets +++ b/.vscode/license.code-snippets @@ -9,9 +9,7 @@ " *", " * Licensed under the Apache License, Version 2.0.", " * you may not use this file except in compliance with the License.", - " */", - "", - "" + " */" ] } } diff --git a/webapp/.husky/pre-commit b/webapp/.husky/pre-commit index 1ecb8d812c..038b7be6dc 100755 --- a/webapp/.husky/pre-commit +++ b/webapp/.husky/pre-commit @@ -1,10 +1 @@ -#!/usr/bin/env sh -source ./webapp/scripts/license.sh - -validate_missed_license "/* - * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0. - * you may not use this file except in compliance with the License. - */" "^.+\.(ts|tsx|css|scss)$" \ No newline at end of file +node ./webapp/scripts/license-check.mjs ./.vscode/license.code-snippets license \ No newline at end of file diff --git a/webapp/scripts/license-check.mjs b/webapp/scripts/license-check.mjs new file mode 100644 index 0000000000..efbb0548df --- /dev/null +++ b/webapp/scripts/license-check.mjs @@ -0,0 +1,65 @@ +import { exec, execSync } from 'child_process'; +import fs from 'fs'; +import { resolve } from 'path'; +import { createInterface } from 'readline'; + +const snippetPath = resolve(process.argv[2]); +const snippetName = process.argv[3]; +const snippets = JSON.parse(fs.readFileSync(snippetPath, 'utf8')); +const licenseSnippet = snippets[snippetName]; + +const scopes = licenseSnippet.scope.split(','); +const license = licenseSnippet.body; +const extensions = new Set(); + +for (const scope of scopes) { + switch (scope.trim()) { + case 'typescript': + extensions.add('.ts'); + break; + case 'typescriptreact': + extensions.add('.tsx'); + break; + case 'javascript': + extensions.add('.js'); + break; + case 'javascriptreact': + extensions.add('.jsx'); + break; + case 'css': + extensions.add('.css'); + break; + case 'scss': + extensions.add('.scss'); + break; + } +} + +const output = exec('git diff --cached --name-only --diff-filter=ACMR'); +const rl = createInterface(output.stdout); +const invalidFiles = []; + +for await (const line of rl) { + const extension = line.slice(line.lastIndexOf('.')); + if (extensions.has(extension)) { + const fileRl = createInterface(fs.createReadStream(line)); + + let fileLineIndex = 0; + for await (const fileLine of fileRl) { + if (fileLine !== license[fileLineIndex]) { + invalidFiles.push(line); + break; + } + fileLineIndex++; + if (fileLineIndex === license.length) { + break; + } + } + } +} + +if (invalidFiles.length > 0) { + execSync('git restore --staged ' + invalidFiles.join(' ')); + process.stdout.write('Found files without license header. Please add license to all unstaged files.'); + process.exit(1); +} diff --git a/webapp/scripts/license.sh b/webapp/scripts/license.sh deleted file mode 100644 index 9c20150a6a..0000000000 --- a/webapp/scripts/license.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -validate_missed_license() { - local TEXT="$1" - local FILES_PATH="$2" - TEXT=$(echo "$TEXT" | tr '\n' '\0' | xargs -0 -n1) - STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACMR | grep -E "$FILES_PATH" || true) - HAS_FILES_WITHOUT_LICENSE=false - - for FILE in $STAGED_FILES; do - while IFS= read -r LINE; do - if ! grep -Fxq "$LINE" "$FILE"; then - HAS_FILES_WITHOUT_LICENSE=true - git restore --staged "$FILE" - break - fi - done <<< "$TEXT" - done - - if [ "$HAS_FILES_WITHOUT_LICENSE" = true ]; then - echo "Found files without license header. Please add license to all unstaged files." - exit 1 - fi -} \ No newline at end of file