Why do I get this error "git rev-parse --abbrev-ref HEAD was unexpected at this time"? - node.js

I have a Node application and I'm running a sonar scan locally by running npm run sonar-scanner. Below is my mackage.json code.
// package.json
...
"scripts": {
"sonar_scanner_branch": "node_modules/sonarqube-scanner/dist/bin/sonar-scanner -Dsonar.branch.name=\"$(git rev-parse --abbrev-ref HEAD)\"",
"sonar_scanner_develop": "node_modules/sonarqube-scanner/dist/bin/sonar-scanner",
"sonar-scanner": "sh updateSonarProps.sh && if [ \"$(git rev-parse --abbrev-ref HEAD)\" = develop ] || [ \"$(git rev-parse --abbrev-ref HEAD)\" = master ] ; then npm run sonar_scanner_develop ; else npm run sonar_scanner_branch ; exit 0 ; fi"
.
.
.
}
This was working fine in my ubuntu 20.0 machine. But it's not working on my windows machine even if I use the same Node version. Below is the error
sh updateSonarProps.sh && if [ "$(git rev-parse --abbrev-ref HEAD)" = develop ] || [ "$(git rev-parse --abbrev-ref HEAD)" = master ] ; then npm run sonar_scanner_develop ; else npm run sonar_scanner_branch ; exit 0 ; fi
"$(git rev-parse --abbrev-ref HEAD)" was unexpected at this time.
What may be the reason for it?

Related

How to fix node.js using sails error: Failed to lift app

I’m trying to deploy a node.js app using the framework Sails in production mode.
I’m using the command npm start which runs NODE_ENV=production node app.js. In package.json I have the following content:
{
"name": "myapp",
"private": true,
"version": "0.0.0",
"description": "a Sails application",
"keywords": [],
"dependencies": {
"sails": "^1.2.3",
"grunt": "1.0.4",
"sails-hook-apianalytics": "^2.0.3",
"sails-hook-grunt": "^3.0.2",
"sails-hook-organics": "^0.16.0",
"sails-hook-orm": "^2.1.1",
"sails-hook-sockets": "^2.0.0",
"#sailshq/connect-redis": "^3.2.1",
"#sailshq/socket.io-redis": "^5.2.0",
"#sailshq/lodash": "^3.10.3"
},
"devDependencies": {
"eslint": "5.16.0",
"htmlhint": "0.11.0",
"lesshint": "6.3.6",
"#sailshq/eslint": "^4.19.3",
"sails-hook-grunt": "^4.0.0"
},
"scripts": {
"start": "NODE_ENV=production node app.js",
"test": "npm run lint && npm run custom-tests && echo 'Done.'",
"lint": "./node_modules/eslint/bin/eslint.js . --max-warnings=0 --report-unused-disable-directives && echo '✔ Your .js files look so good.' && ./node_modules/htmlhint/bin/htmlhint -c ./.htmlhintrc views/*.ejs && ./node_modules/htmlhint/bin/htmlhint -c ./.htmlhintrc views/**/*.ejs && ./node_modules/htmlhint/bin/htmlhint -c ./.htmlhintrc views/**/**/*.ejs && ./node_modules/htmlhint/bin/htmlhint -c ./.htmlhintrc views/**/**/**/*.ejs && ./node_modules/htmlhint/bin/htmlhint -c ./.htmlhintrc views/**/**/**/**/*.ejs && ./node_modules/htmlhint/bin/htmlhint -c ./.htmlhintrc views/**/**/**/**/**/*.ejs && ./node_modules/htmlhint/bin/htmlhint -c ./.htmlhintrc views/**/**/**/**/**/**/*.ejs && echo '✔ So do your .ejs files.' && ./node_modules/lesshint/bin/lesshint assets/styles/ --max-warnings=0 && echo '✔ Your .less files look good, too.'",
"custom-tests": "echo \"(No other custom tests yet.)\" && echo",
"deploy": "echo 'This script assumes a dead-simple, opinionated setup on Heroku.' && echo 'But, of course, you can deploy your app anywhere you like.' && echo '(Node.js/Sails.js apps are supported on all modern hosting platforms.)' && echo && echo 'Warning: Specifically, this script assumes you are on the master branch, and that your app can be deployed simply by force-pushing on top of the *deploy* branch. It will also temporarily use a local *predeploy* branch for preparing assets, that it will delete after it finishes. Please make sure there is nothing you care about on either of these two branches!!!' && echo '' && echo '' && echo 'Preparing to deploy...' && echo '--' && git status && echo '' && echo '--' && echo 'I hope you are on the master branch and have everything committed/pulled/pushed and are completely up to date and stuff.' && echo '********************************************' && echo '** IF NOT THEN PLEASE PRESS <CTRL+C> NOW! **' && echo '********************************************' && echo 'Press CTRL+C to cancel.' && echo '(you have five seconds)' && sleep 1 && echo '...4' && sleep 1 && echo '...3' && sleep 1 && echo '...2' && sleep 1 && echo '...1' && sleep 1 && echo '' && echo 'Alright, here we go. No turning back now!' && echo 'Trying to switch to master branch...' && git checkout master && echo && echo 'OK. Now wiping node_modules/ and running npm install...' && rm -rf node_modules && rm -rf package-lock.json && npm install && (git add package-lock.json && git commit -am 'AUTOMATED COMMIT: Did fresh npm install before deploying, and it caused something relevant (probably the package-lock.json file) to change! This commit tracks that change.' || true) && echo 'Deploying as version:' && npm version patch && echo '' && git push origin master && git push --tags && (git branch -D predeploy > /dev/null 2>&1 || true) && git checkout -b predeploy && (echo 'Now building+minifying assets for production...' && echo '(Hang tight, this could take a while.)' && echo && node node_modules/grunt/bin/grunt buildProd || (echo && echo '------------------------------------------' && echo 'IMPORTANT! IMPORTANT! IMPORTANT!' && echo 'ERROR: Could not compile assets for production!' && echo && echo 'Attempting to recover automatically by stashing, ' && echo 'switching back to the master branch, and then ' && echo 'deleting the predeploy branch... ' && echo && echo 'After this, please fix the issues logged above' && echo 'and push that up. Then, try deploying again.' && echo '------------------------------------------' && echo && echo 'Staging, deleting the predeploy branch, and switching back to master...' && git stash && git checkout master && git branch -D predeploy && false)) && mv www .www && git add .www && node -e 'sailsrc = JSON.parse(require(\"fs\").readFileSync(\"./.sailsrc\", \"utf8\")); if (sailsrc.paths&&sailsrc.paths.public !== undefined || sailsrc.hooks&&sailsrc.hooks.grunt !== undefined) { throw new Error(\"Cannot complete deployment script: .sailsrc file has conflicting contents! Please throw away this midway-complete deployment, switch back to your original branch (master), remove the conflicting stuff from .sailsrc, then commit and push that up.\"); } sailsrc.paths = sailsrc.paths || {}; sailsrc.paths.public = \"./.www\"; sailsrc.hooks = sailsrc.hooks || {}; sailsrc.hooks.grunt = false; require(\"fs\").writeFileSync(\"./.sailsrc\", JSON.stringify(sailsrc))' && git commit -am 'AUTOMATED COMMIT: Automatically bundling compiled assets as part of deploy, updating the EJS layout and .sailsrc file accordingly.' && git push origin predeploy && git checkout master && git push origin +predeploy:deploy && git push --tags && git branch -D predeploy && git push origin :predeploy && echo '' && echo '--' && echo 'OK, done. It should be live momentarily on your staging environment.' && echo '(if you get impatient, check the Heroku dashboard for status)' && echo && echo 'Staging environment:' && echo ' 🌐–• https://staging.example.com' && echo ' (hold ⌘ and click to open links in the terminal)' && echo && echo 'Please review that to make sure it looks good.' && echo 'When you are ready to go to production, visit your pipeline on Heroku and press the PROMOTE TO PRODUCTION button.'"
},
"main": "app.js",
"repository": {
"type": "git",
"url": "git://github.com/xxxxxx.git"
},
"author": "me",
"license": "",
"engines": {
"node": "^10.16"
}
}
If I run sails lift all gone right.
And when run npm start I get following error:
error: Failed to lift app: Error: Should not specify a trailing slash, but instead got: https://myapp.herokuapp.com/
at checkOriginUrl (/home/me/Documents/prog/myapp/node_modules/sails-hook-sockets/lib/util/check-origin-url.js:57:40)
at /home/me/Documents/prog/myapp/node_modules/sails-hook-sockets/lib/configure.js:86:9
at arrayEach (/home/me/Documents/prog/myapp/node_modules/#sailshq/lodash/lib/index.js:1470:13)
at Function.<anonymous> (/home/me/Documents/prog/myapp/node_modules/#sailshq/lodash/lib/index.js:3532:13)
at Hook.configure (/home/me/Documents/prog/myapp/node_modules/sails-hook-sockets/lib/configure.js:85:9)
at Hook.wrapper [as configure] (/home/me/Documents/prog/myapp/node_modules/#sailshq/lodash/lib/index.js:3282:19)
at /home/me/Documents/prog/myapp/node_modules/sails/lib/app/private/loadHooks.js:331:20
at /home/me/Documents/prog/myapp/node_modules/sails/node_modules/async/dist/async.js:3083:16
at eachOfArrayLike (/home/me/Documents/prog/myapp/node_modules/sails/node_modules/async/dist/async.js:1003:9)
at eachOf (/home/me/Documents/prog/myapp/node_modules/sails/node_modules/async/dist/async.js:1051:5)
at Object.eachLimit (/home/me/Documents/prog/myapp/node_modules/sails/node_modules/async/dist/async.js:3145:5)
at configure (/home/me/Documents/prog/myapp/node_modules/sails/lib/app/private/loadHooks.js:328:17)
at /home/me/Documents/prog/myapp/node_modules/sails/node_modules/async/dist/async.js:3853:24
at replenish (/home/me/Documents/prog/myapp/node_modules/sails/node_modules/async/dist/async.js:946:17)
at iterateeCallback (/home/me/Documents/prog/myapp/node_modules/sails/node_modules/async/dist/async.js:931:17)
at /home/me/Documents/prog/myapp/node_modules/sails/node_modules/async/dist/async.js:906:16
I’m trying to use heroku to deploy the app. For this reason I added this in production.js inside sockets object:
onlyAllowOrigins:[
'https://myapp.herokuapp.com/',
],
I think this problem could be caused by any missed configuration in production.js but I couldn’t identify what.

"( foo && bar && baz ); finally-code" <- how can finally-code not be run?

I have this node.js code which generates a bash script:
const k = cp.spawn('bash');
let cmd = [
`cd ${v.path}`,
`git checkout "${releaseName}"`,
`git add .`,
`git commit -am "modified package.json"`,
`git checkout master`,
`( git branch -D -f master_copy_npp_tool &> /dev/null || echo "" ) `,
`git checkout -b master_copy_npp_tool`,
`git merge --no-commit -m "This release branch should be merged into master and integration." "${releaseName}"`,
`git checkout ${releaseName}`,
`git push -u origin ${releaseName}`
]
.join(' && ');
cmd = `( ${cmd} ); git checkout -f master; `; // always checkout the integration branch again, at the end
k.stdin.end(cmd);
For some reason, the script leaves the git repo on the releaseName branch, not master.
The command as a string looks like:
( cd /home/rolo/foo
&& git checkout "oleg/npp_tool/release/1531621240127"
&& git add . && git commit -am "modified package.json"
&& git checkout master
&& ( git branch -D -f master_copy_npp_tool &> /dev/null || echo "" )
&& git checkout -b master_copy_npp_tool
&& git merge --no-commit -m "(shortened)." "oleg/npp_tool/release/1531621240127"
&& git checkout oleg/npp_tool/release/1531621240127
&& git push -u origin oleg/npp_tool/release/1531621240127 );
git checkout -f master;
I am trying to use the last clause:
git checkout -f master;
as a "finally" block. I want to always checkout the master branch in the end no matter way. Anyone know what's going wrong? Like I said it remains on the release branch.
Basically what I tried to do is this pattern:
( foo && bar && star ); finally-clause;

Only build projects if something has changed

We want to split up our project into smaller pieces. Our current CI process goes through a short test phase and then runs a deployment script. However, if nothing has changed in one of the sub project, we do not want to go through the build for this.
Jenkins without pipelines supports exclusions in the SCM configuration (we use git) and based on this, you can configure a specific job to run. However, when using a pipeline, how can I know, if I should build this part or not? How do I get access to the paths that were affected by the last push?
At the moment our script is very simple, and we would like to keep it as simple as possible.
We were playing around with the scripted and the declarative syntax, but could not find a good solution.
Declarative:
#!groovy​
pipeline {
agent any
tools {
nodejs '8.1'
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
# Only continue, if something has changed
stage('Install') {
steps {
sh 'npm install'
}
}
stage('Test') {
steps {
sh 'npm run test-jenkins'
}
post {
always {
junit "artifacts/test/report.xml"
}
}
}
}
}
Scripted:
#!groovy​
node {
def nodejs = tool name: '8.1', type: 'jenkins.plugins.nodejs.tools.NodeJSInstallation'
env.PATH = "${nodejs}/bin:${env.PATH}"
stage('Checkout') {
checkout scm
}
# Only continue, if something has changed
stage('Install') {
sh 'npm install'
}
stage('Test') {
try {
sh 'npm run test-jenkins'
} finally {
junit "artifacts/test/report.xml"
}
}
}
Thanks to ElpieKay's fast comment on my question, we now have an elegant solution:
Make a tag to the current commit on a successful build
In the next build compare the new commit and the tag for changes
We are using a multi-branch pipeline and a parallel build for the multiple projects we have under the same source root. We iterate through the projects (serviceX) and check in the corresponding directory for a change:
def projects = ['service1', 'service2']
def builders = [:]
for (p in projects) {
def label = p
builders[label] = {
def tag = "${BRANCH_NAME}_last"
node {
echo "Checking for changes compared to ${tag} in directory ${label}"
try {
sh "./check-for-changes ${tag} ${label}"
} catch (ignored) {
echo "Nothing to do"
return
}
dir (label) {
stage(label + ": Install") {
sh "npm install"
}
stage(label + ": Test") {
try {
sh "npm run test-jenkins"
} finally {
junit 'artifacts/test/report.xml'
}
}
echo "Setting tag for the last build on this branch"
sh "git tag -f ${tag}"
}
}
}
}
parallel builders
... and the script to check for changes:
#!/bin/bash
SHA_PREV=$1
if [ -z ${SHA_PREV} ]; then
echo "Usage: `basename $0` <tag> <path>"
exit 1
fi
CHECK_PATH=$2
if [ -z ${CHECK_PATH} ]; then
echo "Usage: `basename $0` <tag> <path>"
exit 1
fi
if `git rev-parse ${SHA_PREV} >/dev/null 2>&1`; then
echo "Found previous tag: ${SHA_PREV}"
else
SHA_PREV=`git rev-list --max-parents=0 HEAD`
echo "Using initial commit: ${SHA_PREV}"
fi
changes=`git diff --name-only ${SHA_PREV} HEAD | grep ${CHECK_PATH}/`
if [ ! -n "${changes}" ]; then
echo "No changes found"
exit 2 # no changes found
fi

Getting Typescript 2 paths mapping (aliases) working

I am trying to reference custom modules shortcuts (ie use ts paths mapping feature) for my typescript app, with the following config.
Project structure
dist/
src/
lyrics/
... ts files
app/
... ts files
Full project structure is here: github.com/adadgio/npm-lyrics-ts, dist folder is not commited of course)
tsconfig.json
{
"compilerOptions": {
"outDir": "dist",
"module": "commonjs",
"target": "es6",
"sourceMap": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"removeComments": true,
"noImplicitAny": false,
"baseUrl": ".",
"paths": {
"*": ["src/lyrics/*"], // to much here !! but none work
"zutils/*": ["./src/lyrics/*", "src/lyrics/utils/*", "dist/lyrics/utils/*"]
},
"rootDir": "."
},
"exclude": [
"dist",
"node_modules"
],
"include": [
"src/**/*.ts"
]
}
When i run my npm start/compile or watch script, i get no Typescript errors. The following works (Atom is my IDE)
// string-utils.ts does exist, no IDE error, typescript DOES compile
`import { StringUtils } from 'zutils/string-utils';`
But i then get the NodeJS following error:
Error: Cannot find module 'zutils/string-utils'
at Function.Module._resolveFilename (module.js:470:15)
at Function.Module._load (module.js:418:25)
at Module.require (module.js:498:17)
at require (internal/module.js:20:19)
at Object.<anonymous> (/home/adadgio/WebServer/projects/adadgio/npm-lyrics-ts/src/index.ts:7:1)
at Module._compile (module.js:571:32)
at Module.m._compile (/home/adadgio/WebServer/projects/adadgio/npm-lyrics-ts/node_modules/ts-node/src/index.ts:413:23)
at Module._extensions..js (module.js:580:10)
at Object.require.extensions.(anonymous function) [as .ts] (/home/adadgio/WebServer/projects/adadgio/npm-lyrics-ts/node_modules/ts-node/src/index.ts:416:12)
at Module.load (module.js:488:32)
It looks like the module is trying to be resolved from the node_modules folder. I've read docs about Typescript paths mapping but i cannot get it to work.
I was doing lot of research on this.
I am using atom, typescript and nodejs.
The thing is, when you compile typescript, it does search for paths (the path to a .ts file to include). However, the final compiled .js file does not get path substituted.
The solution:
Compile ts files, use paths in tsconfig
Use script to substitute path token in final .js files
Run node application
So essentially, part of tsconfig will look like this
"baseUrl": "./app",
"paths" : {
"#GameInstance" : ["model/game/GameInstance"],
"#Map" : ["model/game/map/Map"],
"#MapCreator" : ["model/game/map/creator/MapCreator"],
"#GameLoop" : ["model/game/GameLoop"],
"#Point" : ["model/other/math/geometry/Point"],
"#Rectangle" : ["model/other/math/geometry/Rectangle"],
"#Functions" : ["model/other/Functions"]
}
And consider Rectangle.ts file
import { Point } from '#Point';
import { Vector } from '#Vector';
/**
* Represents a rectangle.
* You can query it for collisions or whether rectangles are touching
*/
export class Rectangle {
//more code
Where Rectangle.ts is in
./src/app/model/other/math/geometry/Rectangle/Rectangle.ts
We run
tsc
which will compile all .ts files we set up. There, the paths will be substituted in runtime, if you get error, run
tsc --traceResolution > tmp && gedit tmp
and search for the fiel wehere is undefined path include. You will be able to see substitution log
Then we are left with Rectangle.js (builded)
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var _Point_1 = require("#Point");
//more code
As you see, the #Point will not exist and we can not run node application like this.
For that, however, I created a script, that recursivelly searches js files and replaces the tokens by going up to root and then to target path.
There is requirePaths.data file where you define token and the path.
'#GameLoop' : "./app/model/game/GameLoop"
'#GameInstance' : "./app/model/game/GameInstance"
"#Map" : "./app/model/game/map/Map"
"#MapCreator" : "./app/model/game/map/creator/MapCreator"
"#Point" : "./app/model/other/math/geometry/Point"
"#Rectangle" : "./app/model/other/math/geometry/Point"
Now, this is NOT universal, it is just my hot script. Please, take a note, that structure is
src
|-app
| |-model
-build
|-src
|-app
|-model
|-test
Technically, the app/model... structure in src, is just copied to the src/build
The tsc takes source from /src/app and compiles it. Compiled result is in /src/build
Then, there is the substitutePathsInJS.sh script.
This scand for build path, and whenever it finds token #Rectangle, it replaces it (more explanation below...) Code:
#!/bin/bash
function testreqLevel()
{
local srcPath="$1"
local replacingIn="$2"
local expectedLevel=$3
getPathLevel "$replacingIn"
local res=$?
if [ ! $res -eq $expectedLevel ]; then
echo "[-] test $srcPath , $replacingIn FAILED. ($res != $expectedLevel)"
fi
}
function assertreqPath()
{
local input="$1"
local expected="$2"
if [ ! "$input" = "$expected" ]; then
echo "[-] test $expected FAILED"
echo "computed: $input"
echo "expected: $expected"
fi
}
function testGetPathLevel()
{
testreqLevel "./build/src" "./build/src/app/model/game/GameObject.js" 4
testreqLevel "./build/src" "./build/src/file.js" 1
testreqLevel "./build/src" "./build/src/app/model/game/GameObject.js" 4
}
function testGetPathToRoot()
{
local path=$(getPathToRoot "./build/src" "./build/src/app/model/game/GameObject.js")
assertreqPath "$path" "../../../../../"
path=$(getPathToRoot "./" "./server.js")
assertreqPath "$path" "./"
path=$(getPathToRoot "./" "./app/model/game/GameInstance.js")
assertreqPath "$path" "../../../"
}
function err()
{
echo "[-] $1"
}
function getPathLevel()
{
#get rid of starting ./
local input=$(echo "$1" | sed "s/^\.\///")
local contains=$(echo "$input" | grep '/')
if [ -z "$contains" ]; then
return 0
fi
#echo "$input"
local slashInput=$(echo "$input" | awk -F/ '{print NF-1}')
return $(($slashInput - 1))
}
#given ROOT, and PATH, returns a path P such as being in directory PATH, from there using P we get to root
#example:
#ROOT=./src
#PATH=./src/model/game/objects/a.js
#returns ../../
function getPathToRoot()
{
local root="$1"
local input="$2"
getPathLevel "$input"
local level=$?
if [ $level -eq 0 ]; then
echo "./"
return 0
fi
for ((i=1; i <= level + 1; i++)); do
echo -n '../'
done
#echo "$root" | sed 's/^\.\///'
}
function parseData()
{
echo "**************"
echo "**************"
local data="$1"
let lineNum=1
while read -r line; do
parseLine "$line" $lineNum
if [ $? -eq 1 ]; then
return 1
fi
let lineNum++
done <<< "$data"
echo 'Parsing ok'
echo "**************"
echo "**************"
return 0
}
function parseLine()
{
if [[ "$1" =~ ^\#.*$ ]] || [[ "$1" =~ ^\ *$ ]]; then
#comment line
return 0
fi
local line=$(echo "$1" | sed "s/\"/'/g")
let lineNum=$2
local QUOTE=\'
local WORD_IN_QUOTES=$QUOTE[^:$QUOTE]*$QUOTE
if [[ "$line" =~ ^\ *$WORD_IN_QUOTES\ *:\ *$WORD_IN_QUOTES\ *$ ]]; then
# valid key : value pair
local key=$(echo "$line" | awk -F: '{print $1}' | sed 's/^ *//g' \
| sed 's/ *$//g' | sed 's/\//\\\//g' | sed "s/'//g" | sed "s/\./\\\./g")
local val=$(echo "$line" | awk -F: '{print $2}' | sed 's/^ *//g' \
| sed 's/ *$//g' | sed "s/'//g")
echo "[+] Found substitution from '$key' : '$val'"
if [ -z "$REPLACEMENT_KEY_VAL" ]; then
REPLACEMENT_KEY_VAL="$key|$val"
else
REPLACEMENT_KEY_VAL="$REPLACEMENT_KEY_VAL;$key|$val"
fi
else
err "Parse error on line $lineNum"
echo "Expecting lines 'token' : 'value'"
return 1
fi
return 0
}
function replaceInFiles()
{
cd "$WHERE_SUBSTITUTE"
echo "substitution root $WHERE_SUBSTITUTE"
local fileList=`find . -type f -name "*.js" | grep -v "$EXCLUDE"`
echo "$fileList"| while read fname; do
export IFS=";"
echo "Replacing in file '$WHERE_SUBSTITUTE$fname'"
for line in $REPLACEMENT_KEY_VAL; do
local key=`echo "$line" | awk -F\| '{print $1}'`
local val=`echo "$line" | awk -F\| '{print $2}'`
local finalPath=$(getPathToRoot "./" "$fname")"$val"
if [ $VERBOSE -eq 1 ]; then
echo -e "\tsubstitute '$key' => '$val'"
#echo -e "\t$finalPath"
echo -e "\treplacing $key -> $finalPath"
fi
#escape final path for sed
#slashes, dots
finalPath=$(echo "$finalPath" | sed 's/\//\\\//g'| sed 's/\./\\\./g')
if [ $VERBOSE -eq 1 ]; then
echo -e '\t\tsed -i.bak '"s/require(\(.\)$key/require(\1$finalPath/g"\ "$fname"
fi
sed -i.bak "s/require(\(.\)$key\(.\))/require(\1$finalPath\2)/g" "$fname"
done
done
return 0
}
function quit()
{
echo "*************************************"
echo "*****SUBSTITUTING PATHS EXITING******"
echo "*************************************"
echo
exit $1
}
#######################################
CURRENTDIR=`dirname "$(realpath $0)"`
WHERE_SUBSTITUTE='./build/src'
REPLACEMENT_KEY_VAL="";
VERBOSE=0
FILE="$CURRENTDIR/requirePaths.data"
EXCLUDE='./app/view'
if [ "$1" = "-t" ]; then
testGetPathLevel
testGetPathToRoot
echo "[+] tests done"
exit 0
fi
if [ "$1" = "-v" ]; then
VERBOSE=1
fi
echo "*************************************"
echo "********SUBSTITUTING PATHS***********"
echo "*************************************"
if [ ! -f "$FILE" ]; then
err "File $FILE does not exist"
quit 1
fi
DATA=`cat "$FILE"`
parseData "$DATA"
if [ $? -eq 1 ]; then
quit 1
fi
replaceInFiles
quit $?
This seems confusing, but consider excample.
We have Rectangle.js file.
The script loads bunch of input tokens from requirePaths.data file, in this case, lets focus on line
"#Point" : "./app/model/other/math/geometry/Point"
Script runs from ./src, and is given root directory ./src/build/src
Script does cd ./src/build/src
Executes find. There, it will receive
./model/other/math/geometry/Rectangle/Rectangle.ts
The absolute path of that is
./src/build/src/app/model/other/math/geometry/Rectangle/Rectangle.ts
But we do not care about absolute path now.
Calculates path such as he gets from the directory up
Whis will result is something like
./../../../../
Where he will like that get from directory
/src/build/app/model/other/math/geometry/Rectangle
to directory
/src/build/app
Then, behind that string, we add the path provided from the data file
./../../../.././app/model/other/math/geometry/Point
So the final substitution for file Rectangle.js (in BUILD folder somewhere) is
before
require("#Point")
after
require("./../../../.././app/model/other/math/geometry/Point")
Which is terrible, but we do not care about what is in js anyway. Main thing is that it works.
Drawbacks
You can NOT combine it with code monitor. Monitoring tsc and then, when change in code is done, do automatic tsc compile, then automatically run the shell path substitution and then tun nodeJS upon final js files is possible, BUT for some reason, then the sh script substitutes paths, the monitoring software considers is as change in code (no idea why, it has build excluded from monitor) and compiles again. Therefore, you gen an infinite loop
You must compile it manually, step by step, or JUST use monitor on tsc compilation. When you write some code, go and run substitution and test the nodeJS functionality.
When adding new Class Food, you must define a token for it (#Food) and path to file in 2 places (tsconfig) and the input for shell script
You make entire compilation process longer. To be honest, tsc takes most of time anyway, and the bash script is not so time consuming surprisingly....
When implementing tests with mocha, you must again do step by step compilation and when finished, run mocha above final js files. But for that you can write scripts....
Some people usually substitute only like #app or some directories. The problem with that is, whenever you move source file around, you have to do lot of changes...
The good sides
When moving file around, you change one string (in two places....)
No more relative paths that make big project impossible to maintain
It is interesting, but it really works, and I did not encounter major problems (if used properly)

Intercepting exit

I'm writing unit tests for bash script and want to check if script quits on error (I use exit with errorcode).
Is there any way to catch exit (I know about trap), but don't interrupt command flow (something like exception catching)?
My test script:
do_smth1 && echo OK || echo Fail
do_smth2 && echo OK || echo Fail
do_smth3 && echo OK || echo Fail
my main script:
do_smth1(){
...
...
[ $? -eq 0 ] && success || error_exit
}
and so on.
I'd like to execute all tests one after another. Now flow interrupts after first command.
You can write:
success=0
error_code=1
do_smth1(){
...
...
[ $? -eq 0 ] && return $success || return $error_code
}
do_smth1 && echo OK || echo Fail
do_smth2 && echo OK || echo Fail
do_smth3 && echo OK || echo Fail
Refer the man pages for exit and return, to know when to use which.

Resources