diff --git a/bpkg-init b/bpkg-init new file mode 120000 index 0000000..8814ae0 --- /dev/null +++ b/bpkg-init @@ -0,0 +1 @@ +lib/init/init.sh \ No newline at end of file diff --git a/lib/init/LICENSE.md b/lib/init/LICENSE.md new file mode 100644 index 0000000..2089872 --- /dev/null +++ b/lib/init/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Ben Kogan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/lib/init/Makefile b/lib/init/Makefile new file mode 100644 index 0000000..871bd75 --- /dev/null +++ b/lib/init/Makefile @@ -0,0 +1,15 @@ + +BIN ?= bpkg-init +PREFIX ?= /usr/local + +install: + cp bpkg-init.sh $(PREFIX)/bin/$(BIN) + +uninstall: + rm -f $(PREFIX)/bin/$(BIN) + +bpkg-init.sh: + ./bpkg-init.sh + +.PHONY: bpkg-init.sh + diff --git a/lib/init/README.md b/lib/init/README.md new file mode 100644 index 0000000..3aacf30 --- /dev/null +++ b/lib/init/README.md @@ -0,0 +1,66 @@ +bpkg-init +========= + +Interactively generate a `package.json` for your [bpkg][bp]. Code, format, +and instructions based heavily on [jwerle's][jw] [clib-init][cb]. + +[bp]: https://github.com/bpkg/bpkg/ +[jw]: https://github.com/jwerle/ +[cb]: https://github.com/jwerle/clib-init/ + +install +------- + +With [bpkg](https://github.com/bpkg/bpkg): + +```sh +$ bpkg install benkogan/bpkg-init +``` + +From source: + +```sh +$ git clone git@github.com:benkogan/bpkg-init.git /tmp/bpkg-init +$ cd /tmp/bpkg-init +$ make install +``` + +usage +----- + +Simply invoke `bpkg init` and you wil be prompted with a series +of questions about the generation of your `package.json`. Most options +have sane defaults. + +This will walk you through initializing the bpkg `package.json` file. +It will prompt you for the bare minimum that is needed and provide +defaults. + +See github.com/bpkg/bpkg for more information on defining the bpkg +`package.json` file. + +You can press `^C` anytime to quit this prompt. The `package.json` file +will only be written upon completion. + +```sh +$ bpkg init + +This will walk you through initializing the bpkg `package.json` file. +It will prompt you for the bare minimum that is needed and provide +defaults. + +See github.com/bpkg/bpkg for more information on defining the bpkg +`package.json` file. + +You can press ^C anytime to quit this prompt. The `package.json` file +will only be written upon completion. + +name: (bpkg-init) + +... +``` + +license +------- + +MIT diff --git a/lib/init/init.sh b/lib/init/init.sh new file mode 100755 index 0000000..01fe727 --- /dev/null +++ b/lib/init/init.sh @@ -0,0 +1,240 @@ +#!/bin/bash + +## sets optional variable from environment +opt () { eval "if [ -z "\${$1}" ]; then ${1}=${2}; fi"; } + +## output usage +usage () { + echo "" + echo " usage: bpkg-init [-hV]" + echo "" +} + +## prompt with question and store result in variable +prompt () { + local var="$1" + local q="$2" + local value="" + printf "%s" "${q}" + + { + trap "exit -1" SIGINT SIGTERM + read -r value; + value="${value//\"/\'}"; + } > /dev/null 2>&1 + if [ ! -z "${value}" ]; then + eval "${var}"=\"${value}\" + fi +} + +## alert user of hint +hint () { + { + echo + printf " hint: %s\n" "$@" + echo + } >&2 +} + +## output error +error () { + { + printf "error: %s\n" "${@}" + } >&2 +} + +## append line to buffer +append () { + appendf '%s' "${@}" + buf+=$'\n' +} + +## append formatted string to buffer +appendf () { + local fmt="$1" + shift + buf+="`printf "${fmt}" "${@}"`" +} + +## wraps each argument in quotes +wrap () { + printf '"%s" ' "${@}"; + echo ""; +} + +intro () { + echo + echo "This will walk you through initialzing the bpkg \`package.json' file." + echo "It will prompt you for the bare minimum that is needed and provide" + echo "defaults." + echo + echo "See github.com/bpkg/bpkg for more information on defining the bpkg" + echo "\`package.json' file." + echo + echo "You can press ^C anytime to quit this prompt. The \`package.json' file" + echo "will only be written upon completion." + echo +} + +options () { + opt NAME "$(basename `pwd`)" + opt VERSION "0.0.1" + opt DESCRIPTION "" + opt GLOBAL "" + opt INSTALL "" + opt SCRIPTS "${NAME}.sh" +} + +prompts () { + prompt NAME "name: (${NAME}) " + prompt VERSION "version: (${VERSION}) " + prompt DESCRIPTION "description: " + prompt GLOBAL "global: " + prompt INSTALL "install: " + prompt SCRIPTS "scripts: (${SCRIPTS}) " +} + +## handle required fields +required () { + for key in \ + "NAME" \ + "SCRIPTS" + do + eval local val="\${${key}}" + [ -z "${val}" ] && error "Missing \`${key}' property" + done +} + +## convert scripts to quoted csv +csv () { + if [ ! -z "${SCRIPTS}" ]; then + { + local TMP="" + SCRIPTS="${SCRIPTS//,/ }" + SCRIPTS="${SCRIPTS//\"/}" + SCRIPTS="${SCRIPTS//\'/}" + SCRIPTS=($(wrap ${SCRIPTS})) + let len=${#SCRIPTS[@]} + for (( i = 0; i < len; i++ )); do + word=${SCRIPTS[$i]} + if (( i + 1 != len )); then + TMP+="${word}, " + else + TMP+="${word}" + fi + done + SCRIPTS="${TMP}" + } + fi +} + +## delimit object and key-value pairs +delimit () { + append "{" + + for key in \ + "NAME" \ + "VERSION" \ + "DESCRIPTION" \ + "GLOBAL" \ + "INSTALL" \ + "SCRIPTS" + do + local lowercase="$(echo ${key} | tr '[:upper:]' '[:lower:]')" + + eval local val="\${${key}}" + if [ ! -z "${val}" ]; then + + ## swap leading/trailing quotes for brackets in arrays + local before="\"" + local after="\"" + [ "$key" == "SCRIPTS" ] && before="[ " && after=" ]" + + appendf " \"${lowercase}\": ${before}%s${after}" "${val}" + append "," + fi + done + + ## remove final trailing newline and comma + buf="${buf%?}" + buf="${buf%?}" + + append "" + append "}" +} + +## validate completed contents with user +validate () { + prompt ANSWER "${buf}(yes) ? " + if [ "n" = "${ANSWER:0:1}" ]; then + exit 1 + fi +} + +## if package file already exists, ensure user wants to clobber +clobber () { + if test -f "${file}"; then + prompt ANSWER "A \`package.json' already exists. Would you like to replace it? (yes): " + if [ "n" = "${ANSWER:0:1}" ]; then + exit 1 + else + rm -f "${file}" + fi + fi +} + +## main +bpkg_init () { + local version="0.0.1" + local cwd="`pwd`" + local buf="" ## output buffer + local file="${cwd}/package.json" ## output file + local arg="$1" + shift + + case "${arg}" in + + ## flags + -V|--version) + echo "${version}" + exit 0 + ;; + + -h|--help) + usage + exit 0 + ;; + + *) + if [ ! -z "${arg}" ]; then + error "Unknown option: \`${arg}'" + usage + exit 1 + fi + ;; + esac + + ## set up package file + intro + options + prompts + required + csv + delimit + validate + clobber + + ## create and write package file + touch "${file}" + echo "${buf}" > "${file}" + return 0 +} + +## export or run +if [[ ${BASH_SOURCE[0]} != $0 ]]; then + export -f bpkg-init +else + bpkg_init "${@}" + exit $? +fi + diff --git a/lib/init/package.json b/lib/init/package.json new file mode 100644 index 0000000..4a7d1ff --- /dev/null +++ b/lib/init/package.json @@ -0,0 +1,9 @@ +{ + "name": "bpkg-init", + "version": "0.0.1", + "description": "Initialize a bpkg package.json", + "global": "true", + "install": "make install", + "scripts": [ "bpkg-init.sh" ] +} +