diff --git a/.gitignore b/.gitignore index 7e558da..9f89664 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ **/themes/ demo/ resources/ +.hugo/* +!.hugo/version diff --git a/Makefile b/Makefile index 7c874d5..57945c0 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,10 @@ -.PHONY: demo clear +.PHONY: demo clean demo: mkdir -p demo/themes/hugo-coder - rsync -av exampleSite/* demo + rsync -av exampleSite/ demo rsync -av --exclude='demo' --exclude='exampleSite' --exclude='.git' . demo/themes/hugo-coder - cd demo && hugo serve -D + cd demo && ./hugow serve -D clean: rm -rf demo diff --git a/exampleSite/.hugo/version b/exampleSite/.hugo/version new file mode 100644 index 0000000..ef69c2a --- /dev/null +++ b/exampleSite/.hugo/version @@ -0,0 +1 @@ +0.48/extended diff --git a/exampleSite/hugow b/exampleSite/hugow new file mode 100755 index 0000000..2d0b693 --- /dev/null +++ b/exampleSite/hugow @@ -0,0 +1,430 @@ +#!/usr/bin/env sh +# ------------------------------------------------------------------------------ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ------------------------------------------------------------------------------ + +# ------------------------------------------------------------------------------ +# Hugo Wrapper (v1.1.0) +# +# Hugo Wrapper is a POSIX-style shell script which acts as a wrapper to download +# and execute Hugo binary for your platform. It can be executed in variety of +# Operating Systems and Command Shells. As a result, hugow has very minimal +# number of dependencies: +# +# downloader: wget or curl +# checksum : sha256sum or shasum or cksum +# tarball : tar +# +# https://github.com/khos2ow/hugo-wrapper +# ------------------------------------------------------------------------------ + +set -e + +VERSION_NUMBER="v1.1.0" + +# hugo-wrapper command available flags +get_version="" +get_latest=false +get_extended=false +upgrade=false +version=false +show_help=false + +# hugo related commands to pass through the actual binary +HUGO_ARGS="" + +while [ -n "$1" ]; do + case "$1" in + --get-version) get_version=$2; shift 2 ;; + --get-latest) get_latest=true; shift 1 ;; + --get-extended) get_extended=true; shift 1 ;; + --upgrade) upgrade=true; shift 1 ;; + --version) version=true; shift 1 ;; + -h | --help) show_help=true; shift 1 ;; + + *) HUGO_ARGS="$HUGO_ARGS $1"; shift 1 ;; + esac +done + +set -- $HUGO_ARGS + +if [ "$upgrade" = true ]; then + if [ "$get_extended" = true -o "$get_latest" = true -o -n "$get_version" ]; then + echo "Error: Flag --upgrade cannot be used together with --get-extended, --get-version or --get-latest" + exit 1 + fi +else + if [ "$get_latest" = true -a -n "$get_version" ]; then + echo "Error: Flags --get-version and --get-latest cannot be used together" + exit 1 + fi +fi + +# normalizing get_version +get_version_base="$(echo "$get_version" | cut -d "/" -f1)" +get_version_extended="$(echo "$get_version" | cut -d "/" -f2)" + +get_version="$get_version_base" + +if [ "$get_version_extended" = "extended" ]; then + get_extended=true +fi + +# check which download command (wget or curl) is available. +DOWNLOAD_COMMAND="" +DOWNLOAD_OUTPUT="" +DOWNLOAD_SILENT="" +DOWNLOAD_REDIRECT="" + +if command -v wget > /dev/null; then + DOWNLOAD_COMMAND="wget" + DOWNLOAD_OUTPUT="-O" + DOWNLOAD_SILENT="-q" + DOWNLOAD_REDIRECT="" +elif command -v curl > /dev/null; then + DOWNLOAD_COMMAND="curl" + DOWNLOAD_OUTPUT="-o" + DOWNLOAD_SILENT="-s" + DOWNLOAD_REDIRECT="-L" +else + echo "Error: Unable to find 'wget' or 'curl' command." + exit 1 +fi + +# OS type +os_type="" + +case "`uname -s`" in + Darwin) os_type="macOS" ;; + Linux) os_type="Linux" ;; + DragonFly) os_type="DragonFlyBSD" ;; + FreeBSD) os_type="FreeBSD" ;; + NetBSD) os_type="NetBSD" ;; + OpenBSD) os_type="OpenBSD" ;; + # CYGWIN* os_type="Windows" ;; + # MINGW*) os_type="Windows" ;; + # Windows_NT) os_type="Windows" ;; +esac + +# OS architecture +os_arch="" + +case "`uname -m`" in + x86) os_arch="32bit" ;; + x86_64) os_arch="64bit" ;; + amd64) os_arch="64bit" ;; + armv7l) os_arch="ARM" ;; + armv8) os_arch="ARM64" ;; +esac + +if [ -z "$os_type" -o -z "$os_arch" ]; then + echo "Error: Unknown OS type or architecture" + exit 1 +fi + +# ------------------------------------------------------------------------------ +# traverses directory structure from process work directory to filesystem root +# first directory with .hugo subdirectory is considered project base directory +# ------------------------------------------------------------------------------ +find_basedir() { + if [ -z "$1" ]; then + echo "Error: Path not specified to find_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ]; do + if [ -d "$wdir"/.hugo ]; then + basedir=$wdir + break + fi + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + done + echo "${basedir}" +} + +BASE_DIR=`find_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + echo "Error: Unable to find base directory." + exit 1 +fi + +if [ ! -d "$BASE_DIR/.hugo" ]; then + mkdir -p "$BASE_DIR/.hugo" +else + if [ -r "$BASE_DIR/.hugo/hugo" -a ! -s "$BASE_DIR/.hugo/hugo" ]; then + rm "$BASE_DIR/.hugo/hugo" + fi + if [ -r "$BASE_DIR/.hugo/version" -a ! -s "$BASE_DIR/.hugo/version" ]; then + rm "$BASE_DIR/.hugo/version" + fi +fi + +parse_json() { + local json="$1" + local field="$2" + + if [ -z "$json" ]; then + echo "" + elif [ -z "$field" ]; then + echo "" + fi + + temp=`echo $json | sed 's/\\\\\//\//g' | sed 's/[{}]//g' | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}' | sed 's/\"\:\"/\|/g' | sed 's/[\,]/ /g' | sed 's/\"//g' | grep -w $field` + + echo ${temp##*|} | sed "s/${field}: //g" +} + +perform_checksum() { + if [ -n "$1" ]; then + if command -v sha256sum > /dev/null; then + echo "$1" | sha256sum --check > /dev/null + elif command -v shasum > /dev/null; then + echo "$1" | shasum --algorithm 256 --check > /dev/null + elif command -v cksum > /dev/null; then + echo "$1" | cksum -a SHA256 -c > /dev/null + else + echo "Error: cannot find any checksum command" + exit 1 + fi + fi +} + +remove_file() { + if [ -n "$1" -a "$1" != "/" -a -f "$1" -a -r "$1" ] ; then + rm "$1" + fi +} + +download_version() { + local versionToDownload="$1" + local isExtended="$2" + + if [ -n "$versionToDownload" ]; then + local filenamePrefix="hugo" + local versionDownloadSuffix="" + + if [ "$isExtended" = true ]; then + filenamePrefix="hugo_extended" + versionDownloadSuffix="/extended" + fi + + if [ "$versionToDownload" = "LATEST" ]; then + latest_release=`$DOWNLOAD_COMMAND $DOWNLOAD_SILENT $DOWNLOAD_REDIRECT ${DOWNLOAD_OUTPUT}- https://api.github.com/repos/gohugoio/hugo/releases/latest` + versionToDownload=`parse_json "$latest_release" "tag_name"` + fi + + # strip down 'v' from begining of the string if exists + versionToDownload=`echo $versionToDownload | sed -ne 's/[^0-9]*\(\([0-9]*\.\)\{0,4\}[0-9]*\(\/extended\)*\).*/\1/p'` + + printf "downloading hugo binary version v${versionToDownload}${versionDownloadSuffix} ... " + + # download for specific OS and architecture + local binaryUrl="https://github.com/gohugoio/hugo/releases/download/v${versionToDownload}/${filenamePrefix}_${versionToDownload}_${os_type}-${os_arch}.tar.gz" + local checksumUrl="https://github.com/gohugoio/hugo/releases/download/v${versionToDownload}/${filenamePrefix}_${versionToDownload}_checksums.txt" + + local tarballName="${filenamePrefix}_${versionToDownload}_${os_type}-${os_arch}.tar.gz" + local tarballPath="$BASE_DIR/.hugo/${tarballName}" + local checksumName="checksum.txt" + local checksumPath="$BASE_DIR/.hugo/${checksumName}" + + $DOWNLOAD_COMMAND $DOWNLOAD_SILENT $DOWNLOAD_REDIRECT $DOWNLOAD_OUTPUT "$tarballPath" "$binaryUrl" & + $DOWNLOAD_COMMAND $DOWNLOAD_SILENT $DOWNLOAD_REDIRECT $DOWNLOAD_OUTPUT "$checksumPath" "$checksumUrl" & + wait + + if [ -s "$tarballPath" -a -s "$checksumPath" ]; then + printf "[done]\n" + else + printf "[failed]\n" + remove_file "$checksumPath" + remove_file "$tarballPath" + exit 1 + fi + + printf "verifying hugo binary version v${versionToDownload}${versionDownloadSuffix} ..... " + cd $BASE_DIR/.hugo/ + grep "${tarballName}" "$BASE_DIR/.hugo/$checksumName" | perform_checksum + cd - > /dev/null 2>&1 + wait + printf "[done]\n" + + printf "unzipping hugo binary version v${versionToDownload}${versionDownloadSuffix} ..... " + if [ -f "${tarballPath}" -a -r "${tarballPath}" ]; then + tar --directory="$BASE_DIR/.hugo/" -xzf "${tarballPath}" 2>&1 + wait + printf "[done]\n" + else + printf "[failed]\n" + remove_file "$checksumPath" + remove_file "$tarballPath" + exit 1 + fi + + # save the downloaded binary version into $BASE_DIR/.hugo/version + echo "${versionToDownload}${versionDownloadSuffix}" > $BASE_DIR/.hugo/version + + # cleanup after extraction + remove_file "$checksumPath" + remove_file "$tarballPath" + remove_file "$BASE_DIR/.hugo/LICENSE" + remove_file "$BASE_DIR/.hugo/README.md" + fi +} + +# ------------------------------------------------------------------------------ +# upgrade hugo wrapper binary and save it as ${BASE_DIR}/hugow +# ------------------------------------------------------------------------------ +if [ "$version" = true ]; then + echo "Hugo Wrapper $VERSION_NUMBER" + exit +fi + +# ------------------------------------------------------------------------------ +# upgrade hugo wrapper binary and save it as ${BASE_DIR}/hugow +# ------------------------------------------------------------------------------ +if [ "$upgrade" = true ]; then + printf "downloading hugow binary ... " + + latest_release=`$DOWNLOAD_COMMAND $DOWNLOAD_SILENT $DOWNLOAD_REDIRECT ${DOWNLOAD_OUTPUT}- https://api.github.com/repos/khos2ow/hugo-wrapper/releases/latest` + versionToDownload=`parse_json "$latest_release" "tag_name"` + + $DOWNLOAD_COMMAND $DOWNLOAD_SILENT $DOWNLOAD_REDIRECT $DOWNLOAD_OUTPUT "hugow" "https://github.com/khos2ow/hugo-wrapper/releases/download/${versionToDownload}/hugow" & + wait + printf "[done]\n" + chmod +x hugow + exit +fi + +# ------------------------------------------------------------------------------ +# download hugo binary and save it as ${BASE_DIR}/.hugo/hugo +# ------------------------------------------------------------------------------ +if [ -r "$BASE_DIR/.hugo/hugo" ]; then + current_binary_version="$($BASE_DIR/.hugo/hugo version | sed -ne 's/[^0-9]*\(\([0-9]*\.\)\{0,4\}[0-9]*\(\/extended\)*\).*/\1/p' | sed 's/^ *//;s/ *$//')" + + if [ "$get_extended" = true ]; then + suffix_extended_version="/extended" + fi + + # download hugo binary and save it as ${BASE_DIR}/.hugo/hugo + if [ -n "$get_version" ]; then + if [ "${get_version}${suffix_extended_version}" != "$current_binary_version" ]; then + # specified hugo version + download_version "$get_version" $get_extended + else + echo "hugo binary version ${get_version}${suffix_extended_version} already exists" + echo "${get_version}${suffix_extended_version}" > $BASE_DIR/.hugo/version + fi + elif [ $get_latest = true ]; then + latest_release=`$DOWNLOAD_COMMAND $DOWNLOAD_SILENT $DOWNLOAD_REDIRECT ${DOWNLOAD_OUTPUT}- https://api.github.com/repos/gohugoio/hugo/releases/latest` + latest_version=`parse_json "$latest_release" "tag_name" | sed -ne 's/[^0-9]*\(\([0-9]*\.\)\{0,4\}[0-9]*\(\/extended\)*\).*/\1/p'` + + if [ "${latest_version}${suffix_extended_version}" != "$current_binary_version" ]; then + # latest hugo version + download_version "$latest_version" $get_extended + else + echo "latest hugo binary version ${latest_version}${suffix_extended_version} already exists" + echo "${latest_version}${suffix_extended_version}" > $BASE_DIR/.hugo/version + fi + elif [ -r "$BASE_DIR/.hugo/version" ]; then + current_file_version="$(cat "$BASE_DIR/.hugo/version")" + + if [ "$current_file_version" != "$current_binary_version" ]; then + version_from_file="$(echo "$current_file_version" | cut -d "/" -f1)" + extended_from_file="$(echo "$current_file_version" | cut -d "/" -f2)" + + if [ "${extended_from_file}" = "extended" ]; then + isExtended=true + else + isExtended=false + fi + + # specified hugo version + download_version "$version_from_file" $isExtended + fi + else + # save the current binary version into $BASE_DIR/.hugo/version + echo "$current_binary_version" > $BASE_DIR/.hugo/version + fi +else + if [ -n "$get_version" ]; then + # specified hugo version + download_version "$get_version" $get_extended + elif [ $get_latest = true ]; then + # latest hugo version + download_version "LATEST" $get_extended + elif [ -r "$BASE_DIR/.hugo/version" ]; then + # specified hugo version + version_from_file="$(cat "$BASE_DIR/.hugo/version" | cut -d "/" -f1)" + extended_from_file="$(cat "$BASE_DIR/.hugo/version" | cut -d "/" -f2)" + + if [ "${extended_from_file}" = "extended" ]; then + isExtended=true + else + isExtended=false + fi + + download_version "${version_from_file}" $isExtended + else + # latest hugo version + download_version "LATEST" $get_extended + fi +fi + +# ------------------------------------------------------------------------------ +# only download binary and not execute hugo related command +# ------------------------------------------------------------------------------ +if [ "$get_latest" = true -o -n "$get_version" ]; then + ${BASE_DIR}/.hugo/hugo version + exit +fi + +# ------------------------------------------------------------------------------ +# Show help, both from hugow and ${BASE_DIR}/.hugo/hugo +# ------------------------------------------------------------------------------ +if [ $show_help = true ]; then + help=$(${BASE_DIR}/.hugo/hugo --help) + cat << USAGE +hugow is the universal wrapper for hugo main command. + +Hugo is a Fast and Flexible Static Site Generator +built with love by spf13 and friends in Go. + +Complete documentation is available at http://gohugo.io/. + +Flags: + --get-extended get hugo extended binary + --get-latest get latest version of hugo binary + --get-version string get specified version of hugo binary + --upgrade upgrade hugo wrapper binary itself + --version show version of hugo wrapper binary itself + -h, --help help for hugo-wrapper + +-------- + +$help +USAGE + exit 0 +fi + +# ------------------------------------------------------------------------------ +# pass commands and flags to actual hugo binary +# ------------------------------------------------------------------------------ +${BASE_DIR}/.hugo/hugo "$@"