mirror of
https://github.com/kvz/bash3boilerplate.git
synced 2025-06-25 00:13:23 +00:00
Compare commits
24 Commits
Author | SHA1 | Date | |
---|---|---|---|
0001bfe30c | |||
2b46168792 | |||
1271bf807d | |||
583efe734b | |||
07ab2a95b4 | |||
7fbf9ea8e5 | |||
707583a93c | |||
e538a2be34 | |||
c3f5bcf8c9 | |||
180282d97d | |||
b404c87999 | |||
f2823681d0 | |||
67f2eafc81 | |||
c8773b999b | |||
591642cb38 | |||
c3297e4a7a | |||
619688bb0f | |||
1557e9d66a | |||
72cea95865 | |||
33887625a7 | |||
c4b4f44676 | |||
f114dea34d | |||
0c4a6c78e5 | |||
980a5950d6 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,4 @@
|
||||
npm-debug.log
|
||||
node_modules
|
||||
|
||||
test/scenario/templater/break.cfg
|
||||
|
22
.travis.yml
22
.travis.yml
@ -1,7 +1,15 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- "4.2.1"
|
||||
script: npm run test
|
||||
# For some reason, `sudo: false` broke nvm. Tried this build two times:
|
||||
# https://s3.amazonaws.com/archive.travis-ci.org/jobs/109619626/log.txt
|
||||
sudo: false
|
||||
language: generic
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
sudo: false
|
||||
- os: osx
|
||||
install:
|
||||
# Install acceptance test dependencies for OSX
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then which gsed || brew install gnu-sed; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then which gtimeout || brew install coreutils; fi
|
||||
# Show versions used
|
||||
- bash --version
|
||||
- awk --version
|
||||
script: test/acceptance.sh
|
||||
|
72
README.md
72
README.md
@ -14,17 +14,23 @@ me) programs.
|
||||
|
||||
## Goals
|
||||
|
||||
Delete-key-friendly. I propose people use `main.sh` as a base and remove the
|
||||
parts they don't need, rather than introducing a ton of packages, includes, compilers, etc.
|
||||
Delete-key-friendly. I propose using `main.sh` as a base and removing the
|
||||
parts you don't need, rather than introducing a ton of packages, includes, compilers, etc.
|
||||
|
||||
Aiming for portability, I'm targeting Bash 3 (OSX still ships
|
||||
with 3 for instance). If you're going to ask people to install
|
||||
Bash 4 first, you might as well pick a more advanced language as a
|
||||
dependency.
|
||||
|
||||
We're automatically testing bash3boilerplate and it's proven to work on:
|
||||
|
||||
- [Linux](https://travis-ci.org/kvz/bash3boilerplate/jobs/109804166#L91) `GNU bash, version 4.2.25(1)-release (x86_64-pc-linux-gnu)`
|
||||
- [OSX](https://travis-ci.org/kvz/bash3boilerplate/jobs/109804167#L2453) `GNU bash, version 3.2.51(1)-release (x86_64-apple-darwin13)`
|
||||
|
||||
## Features
|
||||
|
||||
- Structure
|
||||
- Safe defaults (break on error, pipefail, etc)
|
||||
- Configuration by environment variables
|
||||
- Configuration by command-line arguments (definitions parsed from help info,
|
||||
so no duplication needed)
|
||||
@ -39,35 +45,35 @@ There are 3 ways you can install (parts of) b3bp:
|
||||
2. Clone the entire project: `git clone git@github.com:kvz/bash3boilerplate.git`
|
||||
3. As of `v1.0.3`, b3bp can be installed as a `package.json` dependency via: `npm install --save bash3boilerplate`
|
||||
|
||||
Although `3` introduces a node.js dependency, this does allow for easy version pinning & distrubtions in environments that already have this prerequisite. But nothing prevents you from just using `curl` and keep your project or build system low on external dependencies.
|
||||
|
||||
## Versioning
|
||||
|
||||
This project implements the Semantic Versioning guidelines.
|
||||
|
||||
Releases will be numbered with the following format:
|
||||
|
||||
`<major>.<minor>.<patch>`
|
||||
|
||||
And constructed with the following guidelines:
|
||||
|
||||
- Breaking backward compatibility bumps the major (and resets the minor and patch)
|
||||
- New additions without breaking backward compatibility bumps the minor (and resets the patch)
|
||||
- Bug fixes and misc changes bumps the patch
|
||||
|
||||
For more information on SemVer, please visit [http://semver.org](http://semver.org).
|
||||
Although *3* introduces a node.js dependency, this does allow for easy version pinning and distribution in environments that already have this prerequisite. But nothing prevents you from just using `curl` and keep your project or build system low on external dependencies.
|
||||
|
||||
## Changelog
|
||||
|
||||
### v1.2.0 (Unreleased)
|
||||
### master (Unreleased)
|
||||
|
||||
### v2.0.0 (Unreleased)
|
||||
|
||||
- Add tests for `templater` and follow Library export best practices
|
||||
- Add tests for `ini_val` and follow Library export best practices
|
||||
- Add tests for `parse_url` and follow Library export best practices
|
||||
- Add tests for `megamount` and follow Library export best practices
|
||||
- Remove `bump` from `src` (BREAKING)
|
||||
- Remove `semver` from `src` (BREAKING)
|
||||
|
||||
### v1.2.1 (2016-02-17)
|
||||
|
||||
- Add Travis CI automated testing for OSX (thanks @zbeekman)
|
||||
|
||||
### v1.2.0 (2016-02-16)
|
||||
|
||||
- Allow disabling colors via `NO_COLOR` environment variable
|
||||
- Enable errexit, nounset and pipefail at the top
|
||||
- Enable `errexit`, `nounset` and `pipefail` options at the top of the script already
|
||||
- More refined colors (thanks @arathai)
|
||||
- Add Changelog
|
||||
- Add `__os` magic var
|
||||
- Add `__base` magic var
|
||||
- Add a changelog to the README
|
||||
- Add `__os` magic var (limited to discovering OSX and defaulting to Linux for now)
|
||||
- Add `__base` magic var (`main`, if the source script is `main.sh`)
|
||||
- Enable long, GNU style options (thanks @zbeekman)
|
||||
- Add Travis CI automated testing for Linux
|
||||
|
||||
### v1.1.0 (2015-06-29)
|
||||
|
||||
@ -79,7 +85,7 @@ For more information on SemVer, please visit [http://semver.org](http://semver.o
|
||||
|
||||
- Add `ini_val`, `megamount`, `parse_url`
|
||||
- Add re-usable libraries in `./src`
|
||||
- Use npm for distribution
|
||||
- Use npm as an additional distribution channel
|
||||
|
||||
## Best practices
|
||||
|
||||
@ -110,19 +116,21 @@ $ my_script some more args --blah
|
||||
|
||||
(taken from the [bpkg](https://raw.githubusercontent.com/bpkg/bpkg/master/README.md) project)
|
||||
|
||||
## Todo
|
||||
### Miscellaneous
|
||||
|
||||
- [ ] Make `src` libs adhere to Best practices
|
||||
- [ ] `make build` system for generating custom builds
|
||||
- [ ] tests & releases via Travis
|
||||
- In functions, use `local` before every variable declaration
|
||||
- This project settles on two spaces for tabs
|
||||
|
||||
## Authors
|
||||
|
||||
- Kevin van Zonneveld (<http://kvz.io>)
|
||||
- Izaak Beekman (<https://izaakbeekman.com/>)
|
||||
- Alexander Rathai (<Alexander.Rathai@gmail.com>)
|
||||
|
||||
## Sponsoring
|
||||
|
||||
<!-- badges/ -->
|
||||
[](https://www.gittip.com/kvz/ "Sponsor the development of bash3boilerplate via Gittip")
|
||||
[](https://flattr.com/submit/auto?user_id=kvz&url=https://github.com/kvz/bash3boilerplate&title=bash3boilerplate&language=&tags=github&category=software "Sponsor the development of bash3boilerplate via Flattr")
|
||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=kevin%40vanzonneveld%2enet&lc=NL&item_name=Open%20source%20donation%20to%20Kevin%20van%20Zonneveld¤cy_code=USD&bn=PP-DonationsBF%3abtn_donate_SM%2egif%3aNonHosted "Sponsor the development of bash3boilerplate via Paypal")
|
||||
[](https://coinbase.com/checkouts/19BtCjLCboRgTAXiaEvnvkdoRyjd843Dg2 "Sponsor the development of bash3boilerplate via BitCoin")
|
||||
<!-- /badges -->
|
||||
|
||||
## License
|
||||
|
2
main.sh
2
main.sh
@ -9,7 +9,7 @@
|
||||
# - https://github.com/kvz/bash3boilerplate
|
||||
# - http://kvz.io/blog/2013/02/26/introducing-bash3boilerplate/
|
||||
#
|
||||
# Version 1.2.0
|
||||
# Version: 1.2.1
|
||||
#
|
||||
# Authors:
|
||||
# - Kevin van Zonneveld (http://kvz.io)
|
||||
|
@ -1,14 +1,16 @@
|
||||
{
|
||||
"name": "bash3boilerplate",
|
||||
"description": "Copypastable templates to write better bash scripts",
|
||||
"version": "1.2.0",
|
||||
"version": "2.0.0",
|
||||
"scripts": {
|
||||
"release:major": "env SEMANTIC=major npm run release",
|
||||
"release:minor": "env SEMANTIC=minor npm run release",
|
||||
"release:patch": "env SEMANTIC=patch npm run release",
|
||||
"test": "test/acceptance.sh",
|
||||
"version:current": "node -e 'console.log(require(\"./package.json\").version)'",
|
||||
"version:replace": "replace 'Version: \\d+\\.\\d+\\.\\d+' \"Version: $(npm run --silent version:current)\" main.sh src/*.sh",
|
||||
"release": "npm version ${SEMANTIC:-patch} -m \"Release %s\" && npm run version:replace && git commit main.sh -m 'Update version' && git push && git push --tags && npm publish",
|
||||
"save:fixtures": "cross-env SAVE_FIXTURES=true npm run test",
|
||||
"release": "npm version ${SEMANTIC:-patch} -m \"Release %s\" && git push --tags && npm publish"
|
||||
"test": "test/acceptance.sh"
|
||||
},
|
||||
"dependencies": {
|
||||
"fakefile": "0.0.6"
|
||||
|
131
src/bump.sh
131
src/bump.sh
@ -1,131 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) 2014, Transloadit Ltd.
|
||||
#
|
||||
# This file:
|
||||
#
|
||||
# - Bumps a semantic version as specified in first argument
|
||||
# - Or: Bumps a semantic version in a file as specified in first argument
|
||||
# - Returns the version if no levelName is provided in second argument
|
||||
# - Only supports Go files ending in 'var Version = ...'
|
||||
#
|
||||
# Run as:
|
||||
#
|
||||
# ./bump.sh 0.0.1 patch
|
||||
# ./bump.sh ./VERSION patch
|
||||
# ./bump.sh ./VERSION patch
|
||||
# ./bump.sh ./VERSION major 1
|
||||
# ./bump.sh ./version.go patch 2
|
||||
#
|
||||
# Returns:
|
||||
#
|
||||
# v0.0.1
|
||||
#
|
||||
# Requires:
|
||||
#
|
||||
# - gsed on OSX (brew install gnu-sed)
|
||||
#
|
||||
# Authors:
|
||||
#
|
||||
# - Kevin van Zonneveld <kevin@transloadit.com>
|
||||
|
||||
set -o pipefail
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
# set -o xtrace
|
||||
|
||||
# Set magic variables for current FILE & DIR
|
||||
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
__root="$(cd "$(dirname "${__dir}")" && pwd)"
|
||||
__file="${__dir}/$(basename "${BASH_SOURCE[0]}")"
|
||||
__base="$(basename ${__file} .sh)"
|
||||
|
||||
gsed=""
|
||||
[ -n "$(which sed)" ] && gsed="$(which sed)"
|
||||
[ -n "$(which gsed)" ] && gsed="$(which gsed)"
|
||||
|
||||
|
||||
. ${__dir}/semver.sh
|
||||
|
||||
function readFromFile() {
|
||||
local filepath="${1}"
|
||||
local extension="${filepath##*.}"
|
||||
|
||||
if [ "${extension}" = "go" ]; then
|
||||
curVersion="$(awk -F'"' '/^var Version = / {print $2}' "${filepath}" | tail -n1)" || true
|
||||
else
|
||||
curVersion="$(echo $(cat "${filepath}"))" || true
|
||||
fi
|
||||
|
||||
if [ -z "${curVersion}" ]; then
|
||||
curVersion="v0.0.0"
|
||||
fi
|
||||
|
||||
echo "${curVersion}"
|
||||
}
|
||||
|
||||
function writeToFile() {
|
||||
local filepath="${1}"
|
||||
local newVersion="${2}"
|
||||
local extension="${filepath##*.}"
|
||||
|
||||
if [ "${extension}" = "go" ]; then
|
||||
buf="$(cat "${filepath}" |egrep -v '^var Version = ')" || true
|
||||
echo -e "${buf}\nvar Version = \"${newVersion}\"" > "${filepath}"
|
||||
else
|
||||
echo "${newVersion}" > "${filepath}"
|
||||
fi
|
||||
}
|
||||
|
||||
function bump() {
|
||||
local version="${1}"
|
||||
local levelName="${2}"
|
||||
local bump="${3}"
|
||||
|
||||
local major=0
|
||||
local minor=0
|
||||
local patch=0
|
||||
local special=""
|
||||
|
||||
local newVersion=""
|
||||
|
||||
semverParseInto "${version}" major minor patch special
|
||||
|
||||
if [ "${levelName}" = "major" ]; then
|
||||
let "major = major + ${bump}"
|
||||
minor=0
|
||||
patch=0
|
||||
special=""
|
||||
fi
|
||||
if [ "${levelName}" = "minor" ]; then
|
||||
let "minor = minor + ${bump}"
|
||||
patch=0
|
||||
special=""
|
||||
fi
|
||||
if [ "${levelName}" = "patch" ]; then
|
||||
let "patch = patch + ${bump}"
|
||||
special=""
|
||||
fi
|
||||
if [ "${levelName}" = "special" ]; then
|
||||
special="${bump}"
|
||||
fi
|
||||
|
||||
newVersion="v${major}.${minor}.${patch}"
|
||||
if [ -n "${special}" ]; then
|
||||
newVersion=".${newVersion}"
|
||||
fi
|
||||
echo "${newVersion}"
|
||||
}
|
||||
|
||||
if [ -f "${1}" ]; then
|
||||
filepath="${1}"
|
||||
curVersion="$(readFromFile "${filepath}")"
|
||||
else
|
||||
curVersion="${1}"
|
||||
fi
|
||||
|
||||
newVersion=$(bump "${curVersion}" "${2:-}" "${3:-1}")
|
||||
echo "${newVersion}"
|
||||
|
||||
if [ -n "${filepath:-}" ]; then
|
||||
writeToFile "${filepath}" "${newVersion}"
|
||||
fi
|
@ -1,8 +1,40 @@
|
||||
#!/usr/bin/env bash
|
||||
# BASH3 Boilerplate: ini_val
|
||||
#
|
||||
# This file:
|
||||
#
|
||||
# - Can read and write .ini files using pure bash
|
||||
#
|
||||
# Limitations:
|
||||
#
|
||||
# - All keys inside the .ini file must be unique, regardless of the use of sections
|
||||
#
|
||||
# More info:
|
||||
#
|
||||
# - https://github.com/kvz/bash3boilerplate
|
||||
# - http://kvz.io/blog/2013/02/26/introducing-bash3boilerplate/
|
||||
#
|
||||
# Version: 1.2.1
|
||||
#
|
||||
# Authors:
|
||||
# - Kevin van Zonneveld (http://kvz.io)
|
||||
#
|
||||
# Usage as a function:
|
||||
#
|
||||
# source ini_val.sh
|
||||
# ini_val data.ini connection.host 127.0.0.1
|
||||
#
|
||||
# Usage as a command:
|
||||
#
|
||||
# ini_val.sh data.ini connection.host 127.0.0.1
|
||||
#
|
||||
# Licensed under MIT
|
||||
# Copyright (c) 2016 Kevin van Zonneveld (http://kvz.io)
|
||||
|
||||
function ini_val() {
|
||||
local file="${1}"
|
||||
local sectionkey="${2}"
|
||||
local val="${3}"
|
||||
local file="${1:-}"
|
||||
local sectionkey="${2:-}"
|
||||
local val="${3:-}"
|
||||
local delim=" = "
|
||||
local section=""
|
||||
local key=""
|
||||
@ -14,7 +46,7 @@ function ini_val() {
|
||||
section=""
|
||||
fi
|
||||
|
||||
local current=$(awk -F"${delim}" "/^${key}${delim}/ {for (i=2; i<NF; i++) printf \$i \" \"; print \$NF}" "${file}")
|
||||
local current=$(awk -F "${delim}" "/^${key}${delim}/ {for (i=2; i<NF; i++) printf \$i \" \"; print \$NF}" "${file}")
|
||||
if [ -z "${val}" ]; then
|
||||
# get a value
|
||||
echo "${current}"
|
||||
@ -28,11 +60,22 @@ function ini_val() {
|
||||
echo "${key}${delim}${val}" >> "${file}"
|
||||
else
|
||||
# add to section
|
||||
sed "/\[${section}\]/a ${key}${delim}${val}" -i "${file}"
|
||||
sed -i.bak -e "/\[${section}\]/a ${key}${delim}${val}" "${file}"
|
||||
# this .bak dance is done for BSD/GNU portability: http://stackoverflow.com/a/22084103/151666
|
||||
rm -f "${file}.bak"
|
||||
fi
|
||||
else
|
||||
# replace existing
|
||||
sed "/^${key}${delim}/s/${delim}.*/${delim}${val}/" -i "${file}"
|
||||
sed -i.bak -e "/^${key}${delim}/s/${delim}.*/${delim}${val}/" "${file}"
|
||||
# this .bak dance is done for BSD/GNU portability: http://stackoverflow.com/a/22084103/151666
|
||||
rm -f "${file}.bak"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "${BASH_SOURCE[0]}" != ${0} ]; then
|
||||
export -f ini_val
|
||||
else
|
||||
ini_val "${@}"
|
||||
exit ${?}
|
||||
fi
|
||||
|
@ -1,18 +1,54 @@
|
||||
__dir=$(cd `dirname "${BASH_SOURCE[0]}"` && pwd)
|
||||
#!/usr/bin/env bash
|
||||
# BASH3 Boilerplate: megamount
|
||||
#
|
||||
# This file:
|
||||
#
|
||||
# - Takes a URL (smb, nfs, afs) and tries to mount it at a given target directory
|
||||
# - Forceully unmounts any active mount at the target directory first
|
||||
# - Displays the mounts contents for verification
|
||||
#
|
||||
# Depends on:
|
||||
#
|
||||
# - ./parse_url.sh
|
||||
#
|
||||
# More info:
|
||||
#
|
||||
# - https://github.com/kvz/bash3boilerplate
|
||||
# - http://kvz.io/blog/2013/02/26/introducing-bash3boilerplate/
|
||||
#
|
||||
# Version: 1.2.1
|
||||
#
|
||||
# Authors:
|
||||
#
|
||||
# - Kevin van Zonneveld (http://kvz.io)
|
||||
#
|
||||
# Usage as a function:
|
||||
#
|
||||
# source megamount.sh
|
||||
# megamount smb://janedoe:abc123@192.168.0.1/documents /mnt/documents
|
||||
#
|
||||
# Usage as a command:
|
||||
#
|
||||
# megamount.sh smb://janedoe:abc123@192.168.0.1/documents /mnt/documents
|
||||
#
|
||||
# Licensed under MIT
|
||||
# Copyright (c) 2016 Kevin van Zonneveld (http://kvz.io)
|
||||
|
||||
__dir=$(cd `dirname "${BASH_SOURCE[0]}"` && pwd)
|
||||
source "${__dir}/parse_url.sh"
|
||||
|
||||
function megamount () {
|
||||
local url="${1}"
|
||||
local target="${2}"
|
||||
|
||||
proto=$(parse_url "${url}" "proto")
|
||||
user=$(parse_url "${url}" "user")
|
||||
pass=$(parse_url "${url}" "pass")
|
||||
host=$(parse_url "${url}" "host")
|
||||
port=$(parse_url "${url}" "port")
|
||||
path=$(parse_url "${url}" "path")
|
||||
local proto=$(parse_url "${url}" "proto")
|
||||
local user=$(parse_url "${url}" "user")
|
||||
local pass=$(parse_url "${url}" "pass")
|
||||
local host=$(parse_url "${url}" "host")
|
||||
local port=$(parse_url "${url}" "port")
|
||||
local path=$(parse_url "${url}" "path")
|
||||
|
||||
umount -lf "${target}" || true
|
||||
(umount -lf "${target}" || umount -f "${target}") > /dev/null 2>&1 || true
|
||||
mkdir -p "${target}"
|
||||
if [ "${proto}" = "smb://" ]; then
|
||||
mount -t cifs --verbose -o "username=${user},password=${pass},hard" "//${host}/${path}" "${target}"
|
||||
@ -21,12 +57,19 @@ function megamount () {
|
||||
# afpfsd || echo "Unable to run afpfsd. Does /dev/log exist?" && exit 1
|
||||
mount_afp "${url}" "${target}"
|
||||
elif [ "${proto}" = "nfs://" ]; then
|
||||
mount -t nfs --verbose -o "vers=3,nolock,soft,intr,rsize=32768,wsize=32768" ${host}:/${path} ${target}
|
||||
mount -t nfs --verbose -o "vers=3,nolock,soft,intr,rsize=32768,wsize=32768" "${host}:/${path}" "${target}"
|
||||
else
|
||||
echo "ERR: Unknown protocol ${proto}"
|
||||
echo "ERR: Unknown protocol: '${proto}'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# chmod 777 "${target}"
|
||||
ls -al "${target}/"
|
||||
}
|
||||
|
||||
if [ "${BASH_SOURCE[0]}" != ${0} ]; then
|
||||
export -f megamount
|
||||
else
|
||||
megamount "${@}"
|
||||
exit ${?}
|
||||
fi
|
||||
|
@ -1,8 +1,38 @@
|
||||
#!/usr/bin/env bash
|
||||
# BASH3 Boilerplate: parse_url
|
||||
#
|
||||
# This file:
|
||||
#
|
||||
# - Takes a URL and parses protocol, user, pass, host, port, path.
|
||||
#
|
||||
# More info:
|
||||
#
|
||||
# - https://github.com/kvz/bash3boilerplate
|
||||
#
|
||||
# Based on:
|
||||
#
|
||||
# - http://stackoverflow.com/a/6174447/151666
|
||||
#
|
||||
# Version: 1.2.1
|
||||
#
|
||||
# Authors:
|
||||
# - Kevin van Zonneveld (http://kvz.io)
|
||||
#
|
||||
# Usage as a function:
|
||||
#
|
||||
# source parse_url.sh
|
||||
# parse_url 'http://johndoe:abc123@example.com:8080/index.html' pass
|
||||
#
|
||||
# Usage as a command:
|
||||
#
|
||||
# parse_url.sh 'http://johndoe:abc123@example.com:8080/index.html'
|
||||
#
|
||||
# Licensed under MIT
|
||||
# Copyright (c) 2016 Kevin van Zonneveld (http://kvz.io)
|
||||
|
||||
function parse_url() {
|
||||
# Based on http://stackoverflow.com/a/6174447/151666
|
||||
local parse="${1}"
|
||||
local need="${2}"
|
||||
local need="${2:-}"
|
||||
|
||||
local proto="$(echo $parse | grep :// | sed -e's,^\(.*://\).*,\1,g')"
|
||||
local url="$(echo ${parse/$proto/})"
|
||||
@ -39,3 +69,10 @@ function parse_url() {
|
||||
echo ""
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "${BASH_SOURCE[0]}" != ${0} ]; then
|
||||
export -f parse_url
|
||||
else
|
||||
parse_url "${@}"
|
||||
exit ${?}
|
||||
fi
|
||||
|
132
src/semver.sh
132
src/semver.sh
@ -1,132 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
# From: https://github.com/cloudflare/semver_bash
|
||||
# https://raw.githubusercontent.com/cloudflare/semver_bash/master/semver.sh
|
||||
|
||||
function semverParseInto() {
|
||||
local RE='[^0-9]*\([0-9]*\)[.]\([0-9]*\)[.]\([0-9]*\)\([0-9A-Za-z-]*\)'
|
||||
#MAJOR
|
||||
eval $2=`echo $1 | sed -e "s#$RE#\1#"`
|
||||
#MINOR
|
||||
eval $3=`echo $1 | sed -e "s#$RE#\2#"`
|
||||
#MINOR
|
||||
eval $4=`echo $1 | sed -e "s#$RE#\3#"`
|
||||
#SPECIAL
|
||||
eval $5=`echo $1 | sed -e "s#$RE#\4#"`
|
||||
}
|
||||
|
||||
function semverEQ() {
|
||||
local MAJOR_A=0
|
||||
local MINOR_A=0
|
||||
local PATCH_A=0
|
||||
local SPECIAL_A=0
|
||||
|
||||
local MAJOR_B=0
|
||||
local MINOR_B=0
|
||||
local PATCH_B=0
|
||||
local SPECIAL_B=0
|
||||
|
||||
semverParseInto $1 MAJOR_A MINOR_A PATCH_A SPECIAL_A
|
||||
semverParseInto $2 MAJOR_B MINOR_B PATCH_B SPECIAL_B
|
||||
|
||||
if [ $MAJOR_A -ne $MAJOR_B ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ $MINOR_A -ne $MINOR_B ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ $PATCH_A -ne $PATCH_B ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ "_$SPECIAL_A" != "_$SPECIAL_B" ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
|
||||
return 0
|
||||
|
||||
}
|
||||
|
||||
function semverLT() {
|
||||
local MAJOR_A=0
|
||||
local MINOR_A=0
|
||||
local PATCH_A=0
|
||||
local SPECIAL_A=0
|
||||
|
||||
local MAJOR_B=0
|
||||
local MINOR_B=0
|
||||
local PATCH_B=0
|
||||
local SPECIAL_B=0
|
||||
|
||||
semverParseInto $1 MAJOR_A MINOR_A PATCH_A SPECIAL_A
|
||||
semverParseInto $2 MAJOR_B MINOR_B PATCH_B SPECIAL_B
|
||||
|
||||
if [ $MAJOR_A -lt $MAJOR_B ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ $MAJOR_A -le $MAJOR_B && $MINOR_A -lt $MINOR_B ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ $MAJOR_A -le $MAJOR_B && $MINOR_A -le $MINOR_B && $PATCH_A -lt $PATCH_B ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ "_$SPECIAL_A" == "_" ]] && [[ "_$SPECIAL_B" == "_" ]] ; then
|
||||
return 1
|
||||
fi
|
||||
if [[ "_$SPECIAL_A" == "_" ]] && [[ "_$SPECIAL_B" != "_" ]] ; then
|
||||
return 1
|
||||
fi
|
||||
if [[ "_$SPECIAL_A" != "_" ]] && [[ "_$SPECIAL_B" == "_" ]] ; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ "_$SPECIAL_A" < "_$SPECIAL_B" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
|
||||
}
|
||||
|
||||
function semverGT() {
|
||||
semverEQ $1 $2
|
||||
local EQ=$?
|
||||
|
||||
semverLT $1 $2
|
||||
local LT=$?
|
||||
|
||||
if [ $EQ -ne 0 ] && [ $LT -ne 0 ]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "___semver.sh" == "___`basename $0`" ]; then
|
||||
|
||||
MAJOR=0
|
||||
MINOR=0
|
||||
PATCH=0
|
||||
SPECIAL=""
|
||||
|
||||
semverParseInto $1 MAJOR MINOR PATCH SPECIAL
|
||||
echo "$1 -> M: $MAJOR m:$MINOR p:$PATCH s:$SPECIAL"
|
||||
|
||||
semverParseInto $2 MAJOR MINOR PATCH SPECIAL
|
||||
echo "$2 -> M: $MAJOR m:$MINOR p:$PATCH s:$SPECIAL"
|
||||
|
||||
semverEQ $1 $2
|
||||
echo "$1 == $2 -> $?."
|
||||
|
||||
semverLT $1 $2
|
||||
echo "$1 < $2 -> $?."
|
||||
|
||||
semverGT $1 $2
|
||||
echo "$1 > $2 -> $?."
|
||||
|
||||
fi
|
@ -1,48 +1,71 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) 2014, Transloadit Ltd.
|
||||
# BASH3 Boilerplate: templater
|
||||
#
|
||||
# This file:
|
||||
# - takes a source (template) & destination (config) filepath argument
|
||||
# - and then replaces placeholders with variables found in the environment
|
||||
#
|
||||
# Run as:
|
||||
# - takes a source (template) & destination (config) filepath argument
|
||||
# - then replaces placeholders with variables found in the environment
|
||||
#
|
||||
# More info:
|
||||
#
|
||||
# - https://github.com/kvz/bash3boilerplate
|
||||
# - http://kvz.io/blog/2013/02/26/introducing-bash3boilerplate/
|
||||
#
|
||||
# Version: 1.2.1
|
||||
#
|
||||
# Authors:
|
||||
#
|
||||
# - Kevin van Zonneveld (http://kvz.io)
|
||||
#
|
||||
# Usage as a function:
|
||||
#
|
||||
# source templater.sh
|
||||
# NAME=kevin templater input.cfg output.cfg
|
||||
#
|
||||
# Usage as a command:
|
||||
#
|
||||
# ALLOW_REMAINDERS=1 templater.sh input.cfg output.cfg
|
||||
#
|
||||
# Authors:
|
||||
# - Kevin van Zonneveld <kevin@transloadit.com>
|
||||
# Licensed under MIT
|
||||
# Copyright (c) 2016 Kevin van Zonneveld (http://kvz.io)
|
||||
|
||||
set -o pipefail
|
||||
set -o errexit
|
||||
# set -o xtrace
|
||||
# set -o nounset
|
||||
function templater() {
|
||||
sed=""
|
||||
[ -n "$(which sed)" ] && sed="$(which sed)"
|
||||
[ -n "$(which gsed)" ] && sed="$(which gsed)"
|
||||
|
||||
sed=""
|
||||
[ -n "$(which sed)" ] && sed="$(which sed)"
|
||||
[ -n "$(which gsed)" ] && sed="$(which gsed)"
|
||||
ALLOW_REMAINDERS="${ALLOW_REMAINDERS:-0}"
|
||||
|
||||
ALLOW_REMAINDERS="${ALLOW_REMAINDERS:-0}"
|
||||
templateSrc="${1:-}"
|
||||
templateDst="${2:-}"
|
||||
|
||||
templateSrc="${1}"
|
||||
templateDst="${2}"
|
||||
if [ ! -f "${templateSrc}" ]; then
|
||||
echo "ERROR: Template source '${templateSrc}' needs to exist"
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -n "${templateDst}" ]; then
|
||||
echo "ERROR: Template destination '${templateDst}' needs to be specified"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "${templateSrc}" ]; then
|
||||
echo "ERROR: Template source '${templateSrc}' needs to exist"
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -n "${templateDst}" ]; then
|
||||
echo "ERROR: Template destination '${templateDst}' needs to exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cp -f "${templateSrc}" "${templateDst}"
|
||||
for var in $(env |awk -F= '{print $1}' |egrep '^[A-Z0-9_]+$'); do
|
||||
${sed} "s#\${${var}}#${!var}#g" -i "${templateDst}"
|
||||
done
|
||||
|
||||
# cat "${templateDst}"
|
||||
|
||||
if grep '${' ${templateDst} && [ "${ALLOW_REMAINDERS}" == "0" ]; then
|
||||
echo "ERROR: Unable to replace the above template vars"
|
||||
exit 1
|
||||
cp -f "${templateSrc}" "${templateDst}"
|
||||
for var in $(env |awk -F= '{print $1}' |egrep '^[A-Z0-9_]+$'); do
|
||||
${sed} -i.bak -e "s#\${${var}}#${!var}#g" "${templateDst}"
|
||||
# this .bak dance is done for BSD/GNU portability: http://stackoverflow.com/a/22084103/151666
|
||||
rm -f "${templateDst}.bak"
|
||||
done
|
||||
|
||||
# cat "${templateDst}"
|
||||
|
||||
if grep '${' ${templateDst} && [ "${ALLOW_REMAINDERS}" = "0" ]; then
|
||||
echo "ERROR: Unable to replace the above template vars"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "${BASH_SOURCE[0]}" != ${0} ]; then
|
||||
export -f templater
|
||||
else
|
||||
templater "${@}"
|
||||
exit ${?}
|
||||
fi
|
||||
|
24
test/fixture/ini_val.stdio
Normal file
24
test/fixture/ini_val.stdio
Normal file
@ -0,0 +1,24 @@
|
||||
--> command: Read 3 values
|
||||
exists
|
||||
127.0.0.1
|
||||
nginx, nodejs
|
||||
--> command: Replace three values in-place and show result
|
||||
orphan = no more
|
||||
|
||||
[connection]
|
||||
host = 192.168.0.1
|
||||
|
||||
[software]
|
||||
packages = vim
|
||||
--> function: Read 3 values
|
||||
exists
|
||||
127.0.0.1
|
||||
nginx, nodejs
|
||||
--> function: Replace three values in-place and show result
|
||||
orphan = no more
|
||||
|
||||
[connection]
|
||||
host = 192.168.0.1
|
||||
|
||||
[software]
|
||||
packages = vim
|
1
test/fixture/main-longopt.exitcode
Normal file
1
test/fixture/main-longopt.exitcode
Normal file
@ -0,0 +1 @@
|
||||
0
|
1
test/fixture/megamount.exitcode
Normal file
1
test/fixture/megamount.exitcode
Normal file
@ -0,0 +1 @@
|
||||
1
|
2
test/fixture/megamount.stdio
Normal file
2
test/fixture/megamount.stdio
Normal file
@ -0,0 +1,2 @@
|
||||
ERR: Unknown protocol: 'foobarfs://'
|
||||
ERR: Unknown protocol: 'foobarfs://'
|
1
test/fixture/parse_url.exitcode
Normal file
1
test/fixture/parse_url.exitcode
Normal file
@ -0,0 +1 @@
|
||||
0
|
24
test/fixture/parse_url.stdio
Normal file
24
test/fixture/parse_url.stdio
Normal file
@ -0,0 +1,24 @@
|
||||
abc123
|
||||
|
||||
Use second argument to return just 1 variable.
|
||||
parse_url() demo:
|
||||
|
||||
proto: http://
|
||||
user: johndoe
|
||||
pass: abc123
|
||||
host: example.com
|
||||
port: 8080
|
||||
path: index.html
|
||||
|
||||
abc123
|
||||
|
||||
Use second argument to return just 1 variable.
|
||||
parse_url() demo:
|
||||
|
||||
proto: http://
|
||||
user: johndoe
|
||||
pass: abc123
|
||||
host: example.com
|
||||
port: 8080
|
||||
path: index.html
|
||||
|
1
test/fixture/templater.exitcode
Normal file
1
test/fixture/templater.exitcode
Normal file
@ -0,0 +1 @@
|
||||
1
|
14
test/fixture/templater.stdio
Normal file
14
test/fixture/templater.stdio
Normal file
@ -0,0 +1,14 @@
|
||||
--
|
||||
[connection]
|
||||
host = 127.0.0.1
|
||||
--
|
||||
[connection]
|
||||
host = 127.0.0.1
|
||||
--
|
||||
port = ${I_DONT_EXIST}
|
||||
[connection]
|
||||
host = 127.0.0.1
|
||||
port = ${I_DONT_EXIST}
|
||||
--
|
||||
port = ${I_DONT_EXIST}
|
||||
ERROR: Unable to replace the above template vars
|
7
test/scenario/ini_val/data.ini
Normal file
7
test/scenario/ini_val/data.ini
Normal file
@ -0,0 +1,7 @@
|
||||
orphan = exists
|
||||
|
||||
[connection]
|
||||
host = 127.0.0.1
|
||||
|
||||
[software]
|
||||
packages = nginx, nodejs
|
43
test/scenario/ini_val/run.sh
Normal file
43
test/scenario/ini_val/run.sh
Normal file
@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env bash
|
||||
set -o pipefail
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
# set -o xtrace
|
||||
|
||||
# Set magic variables for current FILE & DIR
|
||||
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
__file="${__dir}/$(basename "${BASH_SOURCE[0]}")"
|
||||
__base="$(basename ${__file} .sh)"
|
||||
__root="$(cd "$(dirname $(dirname $(dirname "${__dir}")))" && pwd)"
|
||||
|
||||
# echo "B3BP:STDIO_REPLACE_DATETIMES"
|
||||
|
||||
|
||||
# Use as standalone:
|
||||
cp -f data.ini dummy.ini
|
||||
echo "--> command: Read 3 values"
|
||||
bash "${__root}/src/ini_val.sh" ./dummy.ini orphan
|
||||
bash "${__root}/src/ini_val.sh" ./dummy.ini connection.host
|
||||
bash "${__root}/src/ini_val.sh" ./dummy.ini software.packages
|
||||
|
||||
echo "--> command: Replace three values in-place and show result"
|
||||
bash "${__root}/src/ini_val.sh" ./dummy.ini orphan "no more"
|
||||
bash "${__root}/src/ini_val.sh" ./dummy.ini connection.host "192.168.0.1"
|
||||
bash "${__root}/src/ini_val.sh" ./dummy.ini software.packages "vim"
|
||||
cat dummy.ini
|
||||
rm -f dummy.ini
|
||||
|
||||
# Use as include:
|
||||
cp -f data.ini dummy.ini
|
||||
source ${__root}/src/ini_val.sh
|
||||
echo "--> function: Read 3 values"
|
||||
ini_val ./dummy.ini orphan
|
||||
ini_val ./dummy.ini connection.host
|
||||
ini_val ./dummy.ini software.packages
|
||||
|
||||
echo "--> function: Replace three values in-place and show result"
|
||||
ini_val ./dummy.ini orphan "no more"
|
||||
ini_val ./dummy.ini connection.host "192.168.0.1"
|
||||
ini_val ./dummy.ini software.packages "vim"
|
||||
cat dummy.ini
|
||||
rm -f dummy.ini
|
22
test/scenario/megamount/run.sh
Normal file
22
test/scenario/megamount/run.sh
Normal file
@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
set -o pipefail
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
# set -o xtrace
|
||||
|
||||
# Set magic variables for current FILE & DIR
|
||||
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
__file="${__dir}/$(basename "${BASH_SOURCE[0]}")"
|
||||
__base="$(basename ${__file} .sh)"
|
||||
__root="$(cd "$(dirname $(dirname $(dirname "${__dir}")))" && pwd)"
|
||||
|
||||
__sysTmpDir="${TMPDIR:-/tmp}"
|
||||
__sysTmpDir="${__sysTmpDir%/}" # <-- remove trailing slash on macosx
|
||||
|
||||
# Currently I only know how to test a failing condition here since
|
||||
# it's too invasive to create actual mounts to play with on a system
|
||||
|
||||
bash "${__root}/src/megamount.sh" 'foobarfs://janedoe:abc123@192.168.0.1/documents' "${__sysTmpDir}/mnt/documents" || true
|
||||
|
||||
source ${__root}/src/megamount.sh
|
||||
megamount 'foobarfs://janedoe:abc123@192.168.0.1/documents' "${__sysTmpDir}/mnt/documents"
|
18
test/scenario/parse_url/run.sh
Normal file
18
test/scenario/parse_url/run.sh
Normal file
@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
set -o pipefail
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
# set -o xtrace
|
||||
|
||||
# Set magic variables for current FILE & DIR
|
||||
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
__file="${__dir}/$(basename "${BASH_SOURCE[0]}")"
|
||||
__base="$(basename ${__file} .sh)"
|
||||
__root="$(cd "$(dirname $(dirname $(dirname "${__dir}")))" && pwd)"
|
||||
|
||||
bash "${__root}/src/parse_url.sh" 'http://johndoe:abc123@example.com:8080/index.html' pass
|
||||
bash "${__root}/src/parse_url.sh" 'http://johndoe:abc123@example.com:8080/index.html'
|
||||
|
||||
source ${__root}/src/parse_url.sh
|
||||
parse_url 'http://johndoe:abc123@example.com:8080/index.html' pass
|
||||
parse_url 'http://johndoe:abc123@example.com:8080/index.html'
|
2
test/scenario/templater/app.template.cfg
Normal file
2
test/scenario/templater/app.template.cfg
Normal file
@ -0,0 +1,2 @@
|
||||
[connection]
|
||||
host = ${TARGET_HOST}
|
3
test/scenario/templater/break.template.cfg
Normal file
3
test/scenario/templater/break.template.cfg
Normal file
@ -0,0 +1,3 @@
|
||||
[connection]
|
||||
host = ${TARGET_HOST}
|
||||
port = ${I_DONT_EXIST}
|
33
test/scenario/templater/run.sh
Normal file
33
test/scenario/templater/run.sh
Normal file
@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env bash
|
||||
set -o pipefail
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
# set -o xtrace
|
||||
|
||||
# Set magic variables for current FILE & DIR
|
||||
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
__file="${__dir}/$(basename "${BASH_SOURCE[0]}")"
|
||||
__base="$(basename ${__file} .sh)"
|
||||
__root="$(cd "$(dirname $(dirname $(dirname "${__dir}")))" && pwd)"
|
||||
|
||||
echo "--"
|
||||
env TARGET_HOST="127.0.0.1" bash "${__root}/src/templater.sh" ./app.template.cfg ./app.cfg
|
||||
cat app.cfg
|
||||
rm -f app.cfg
|
||||
|
||||
echo "--"
|
||||
export TARGET_HOST="127.0.0.1"
|
||||
source ${__root}/src/templater.sh
|
||||
templater ./app.template.cfg ./app.cfg
|
||||
cat app.cfg
|
||||
rm -f app.cfg
|
||||
|
||||
echo "--"
|
||||
env ALLOW_REMAINDERS="1" TARGET_HOST="127.0.0.1" bash "${__root}/src/templater.sh" ./break.template.cfg ./break.cfg
|
||||
cat break.cfg
|
||||
rm -f break.cfg
|
||||
|
||||
echo "--"
|
||||
env TARGET_HOST="127.0.0.1" bash "${__root}/src/templater.sh" ./break.template.cfg ./break.cfg
|
||||
cat break.cfg
|
||||
rm -f break.cfg
|
Reference in New Issue
Block a user