1
0

hugow 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. #!/usr/bin/env sh
  2. # ------------------------------------------------------------------------------
  3. # Licensed to the Apache Software Foundation (ASF) under one
  4. # or more contributor license agreements. See the NOTICE file
  5. # distributed with this work for additional information
  6. # regarding copyright ownership. The ASF licenses this file
  7. # to you under the Apache License, Version 2.0 (the
  8. # "License"); you may not use this file except in compliance
  9. # with the License. You may obtain a copy of the License at
  10. #
  11. # http://www.apache.org/licenses/LICENSE-2.0
  12. #
  13. # Unless required by applicable law or agreed to in writing,
  14. # software distributed under the License is distributed on an
  15. # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  16. # KIND, either express or implied. See the License for the
  17. # specific language governing permissions and limitations
  18. # under the License.
  19. # ------------------------------------------------------------------------------
  20. # ------------------------------------------------------------------------------
  21. # Hugo Wrapper (v1.1.0)
  22. #
  23. # Hugo Wrapper is a POSIX-style shell script which acts as a wrapper to download
  24. # and execute Hugo binary for your platform. It can be executed in variety of
  25. # Operating Systems and Command Shells. As a result, hugow has very minimal
  26. # number of dependencies:
  27. #
  28. # downloader: wget or curl
  29. # checksum : sha256sum or shasum or cksum
  30. # tarball : tar
  31. #
  32. # https://github.com/khos2ow/hugo-wrapper
  33. # ------------------------------------------------------------------------------
  34. set -e
  35. VERSION_NUMBER="v1.1.0"
  36. # hugo-wrapper command available flags
  37. get_version=""
  38. get_latest=false
  39. get_extended=false
  40. upgrade=false
  41. version=false
  42. show_help=false
  43. # hugo related commands to pass through the actual binary
  44. HUGO_ARGS=""
  45. while [ -n "$1" ]; do
  46. case "$1" in
  47. --get-version) get_version=$2; shift 2 ;;
  48. --get-latest) get_latest=true; shift 1 ;;
  49. --get-extended) get_extended=true; shift 1 ;;
  50. --upgrade) upgrade=true; shift 1 ;;
  51. --version) version=true; shift 1 ;;
  52. -h | --help) show_help=true; shift 1 ;;
  53. *) HUGO_ARGS="$HUGO_ARGS $1"; shift 1 ;;
  54. esac
  55. done
  56. set -- $HUGO_ARGS
  57. if [ "$upgrade" = true ]; then
  58. if [ "$get_extended" = true -o "$get_latest" = true -o -n "$get_version" ]; then
  59. echo "Error: Flag --upgrade cannot be used together with --get-extended, --get-version or --get-latest"
  60. exit 1
  61. fi
  62. else
  63. if [ "$get_latest" = true -a -n "$get_version" ]; then
  64. echo "Error: Flags --get-version and --get-latest cannot be used together"
  65. exit 1
  66. fi
  67. fi
  68. # normalizing get_version
  69. get_version_base="$(echo "$get_version" | cut -d "/" -f1)"
  70. get_version_extended="$(echo "$get_version" | cut -d "/" -f2)"
  71. get_version="$get_version_base"
  72. if [ "$get_version_extended" = "extended" ]; then
  73. get_extended=true
  74. fi
  75. # check which download command (wget or curl) is available.
  76. DOWNLOAD_COMMAND=""
  77. DOWNLOAD_OUTPUT=""
  78. DOWNLOAD_SILENT=""
  79. DOWNLOAD_REDIRECT=""
  80. if command -v wget > /dev/null; then
  81. DOWNLOAD_COMMAND="wget"
  82. DOWNLOAD_OUTPUT="-O"
  83. DOWNLOAD_SILENT="-q"
  84. DOWNLOAD_REDIRECT=""
  85. elif command -v curl > /dev/null; then
  86. DOWNLOAD_COMMAND="curl"
  87. DOWNLOAD_OUTPUT="-o"
  88. DOWNLOAD_SILENT="-s"
  89. DOWNLOAD_REDIRECT="-L"
  90. else
  91. echo "Error: Unable to find 'wget' or 'curl' command."
  92. exit 1
  93. fi
  94. # OS type
  95. os_type=""
  96. case "`uname -s`" in
  97. Darwin) os_type="macOS" ;;
  98. Linux) os_type="Linux" ;;
  99. DragonFly) os_type="DragonFlyBSD" ;;
  100. FreeBSD) os_type="FreeBSD" ;;
  101. NetBSD) os_type="NetBSD" ;;
  102. OpenBSD) os_type="OpenBSD" ;;
  103. # CYGWIN* os_type="Windows" ;;
  104. # MINGW*) os_type="Windows" ;;
  105. # Windows_NT) os_type="Windows" ;;
  106. esac
  107. # OS architecture
  108. os_arch=""
  109. case "`uname -m`" in
  110. x86) os_arch="32bit" ;;
  111. x86_64) os_arch="64bit" ;;
  112. amd64) os_arch="64bit" ;;
  113. armv7l) os_arch="ARM" ;;
  114. armv8) os_arch="ARM64" ;;
  115. esac
  116. if [ -z "$os_type" -o -z "$os_arch" ]; then
  117. echo "Error: Unknown OS type or architecture"
  118. exit 1
  119. fi
  120. # ------------------------------------------------------------------------------
  121. # traverses directory structure from process work directory to filesystem root
  122. # first directory with .hugo subdirectory is considered project base directory
  123. # ------------------------------------------------------------------------------
  124. find_basedir() {
  125. if [ -z "$1" ]; then
  126. echo "Error: Path not specified to find_basedir"
  127. return 1
  128. fi
  129. basedir="$1"
  130. wdir="$1"
  131. while [ "$wdir" != '/' ]; do
  132. if [ -d "$wdir"/.hugo ]; then
  133. basedir=$wdir
  134. break
  135. fi
  136. if [ -d "${wdir}" ]; then
  137. wdir=`cd "$wdir/.."; pwd`
  138. fi
  139. done
  140. echo "${basedir}"
  141. }
  142. BASE_DIR=`find_basedir "$(pwd)"`
  143. if [ -z "$BASE_DIR" ]; then
  144. echo "Error: Unable to find base directory."
  145. exit 1
  146. fi
  147. if [ ! -d "$BASE_DIR/.hugo" ]; then
  148. mkdir -p "$BASE_DIR/.hugo"
  149. else
  150. if [ -r "$BASE_DIR/.hugo/hugo" -a ! -s "$BASE_DIR/.hugo/hugo" ]; then
  151. rm "$BASE_DIR/.hugo/hugo"
  152. fi
  153. if [ -r "$BASE_DIR/.hugo/version" -a ! -s "$BASE_DIR/.hugo/version" ]; then
  154. rm "$BASE_DIR/.hugo/version"
  155. fi
  156. fi
  157. parse_json() {
  158. local json="$1"
  159. local field="$2"
  160. if [ -z "$json" ]; then
  161. echo ""
  162. elif [ -z "$field" ]; then
  163. echo ""
  164. fi
  165. 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`
  166. echo ${temp##*|} | sed "s/${field}: //g"
  167. }
  168. perform_checksum() {
  169. if [ -n "$1" ]; then
  170. if command -v sha256sum > /dev/null; then
  171. echo "$1" | sha256sum --check > /dev/null
  172. elif command -v shasum > /dev/null; then
  173. echo "$1" | shasum --algorithm 256 --check > /dev/null
  174. elif command -v cksum > /dev/null; then
  175. echo "$1" | cksum -a SHA256 -c > /dev/null
  176. else
  177. echo "Error: cannot find any checksum command"
  178. exit 1
  179. fi
  180. fi
  181. }
  182. remove_file() {
  183. if [ -n "$1" -a "$1" != "/" -a -f "$1" -a -r "$1" ] ; then
  184. rm "$1"
  185. fi
  186. }
  187. download_version() {
  188. local versionToDownload="$1"
  189. local isExtended="$2"
  190. if [ -n "$versionToDownload" ]; then
  191. local filenamePrefix="hugo"
  192. local versionDownloadSuffix=""
  193. if [ "$isExtended" = true ]; then
  194. filenamePrefix="hugo_extended"
  195. versionDownloadSuffix="/extended"
  196. fi
  197. if [ "$versionToDownload" = "LATEST" ]; then
  198. latest_release=`$DOWNLOAD_COMMAND $DOWNLOAD_SILENT $DOWNLOAD_REDIRECT ${DOWNLOAD_OUTPUT}- https://api.github.com/repos/gohugoio/hugo/releases/latest`
  199. versionToDownload=`parse_json "$latest_release" "tag_name"`
  200. fi
  201. # strip down 'v' from begining of the string if exists
  202. versionToDownload=`echo $versionToDownload | sed -ne 's/[^0-9]*\(\([0-9]*\.\)\{0,4\}[0-9]*\(\/extended\)*\).*/\1/p'`
  203. printf "downloading hugo binary version v${versionToDownload}${versionDownloadSuffix} ... "
  204. # download for specific OS and architecture
  205. local binaryUrl="https://github.com/gohugoio/hugo/releases/download/v${versionToDownload}/${filenamePrefix}_${versionToDownload}_${os_type}-${os_arch}.tar.gz"
  206. local checksumUrl="https://github.com/gohugoio/hugo/releases/download/v${versionToDownload}/${filenamePrefix}_${versionToDownload}_checksums.txt"
  207. local tarballName="${filenamePrefix}_${versionToDownload}_${os_type}-${os_arch}.tar.gz"
  208. local tarballPath="$BASE_DIR/.hugo/${tarballName}"
  209. local checksumName="checksum.txt"
  210. local checksumPath="$BASE_DIR/.hugo/${checksumName}"
  211. $DOWNLOAD_COMMAND $DOWNLOAD_SILENT $DOWNLOAD_REDIRECT $DOWNLOAD_OUTPUT "$tarballPath" "$binaryUrl" &
  212. $DOWNLOAD_COMMAND $DOWNLOAD_SILENT $DOWNLOAD_REDIRECT $DOWNLOAD_OUTPUT "$checksumPath" "$checksumUrl" &
  213. wait
  214. if [ -s "$tarballPath" -a -s "$checksumPath" ]; then
  215. printf "[done]\n"
  216. else
  217. printf "[failed]\n"
  218. remove_file "$checksumPath"
  219. remove_file "$tarballPath"
  220. exit 1
  221. fi
  222. printf "verifying hugo binary version v${versionToDownload}${versionDownloadSuffix} ..... "
  223. cd $BASE_DIR/.hugo/
  224. grep "${tarballName}" "$BASE_DIR/.hugo/$checksumName" | perform_checksum
  225. cd - > /dev/null 2>&1
  226. wait
  227. printf "[done]\n"
  228. printf "unzipping hugo binary version v${versionToDownload}${versionDownloadSuffix} ..... "
  229. if [ -f "${tarballPath}" -a -r "${tarballPath}" ]; then
  230. tar --directory="$BASE_DIR/.hugo/" -xzf "${tarballPath}" 2>&1
  231. wait
  232. printf "[done]\n"
  233. else
  234. printf "[failed]\n"
  235. remove_file "$checksumPath"
  236. remove_file "$tarballPath"
  237. exit 1
  238. fi
  239. # save the downloaded binary version into $BASE_DIR/.hugo/version
  240. echo "${versionToDownload}${versionDownloadSuffix}" > $BASE_DIR/.hugo/version
  241. # cleanup after extraction
  242. remove_file "$checksumPath"
  243. remove_file "$tarballPath"
  244. remove_file "$BASE_DIR/.hugo/LICENSE"
  245. remove_file "$BASE_DIR/.hugo/README.md"
  246. fi
  247. }
  248. # ------------------------------------------------------------------------------
  249. # upgrade hugo wrapper binary and save it as ${BASE_DIR}/hugow
  250. # ------------------------------------------------------------------------------
  251. if [ "$version" = true ]; then
  252. echo "Hugo Wrapper $VERSION_NUMBER"
  253. exit
  254. fi
  255. # ------------------------------------------------------------------------------
  256. # upgrade hugo wrapper binary and save it as ${BASE_DIR}/hugow
  257. # ------------------------------------------------------------------------------
  258. if [ "$upgrade" = true ]; then
  259. printf "downloading hugow binary ... "
  260. latest_release=`$DOWNLOAD_COMMAND $DOWNLOAD_SILENT $DOWNLOAD_REDIRECT ${DOWNLOAD_OUTPUT}- https://api.github.com/repos/khos2ow/hugo-wrapper/releases/latest`
  261. versionToDownload=`parse_json "$latest_release" "tag_name"`
  262. $DOWNLOAD_COMMAND $DOWNLOAD_SILENT $DOWNLOAD_REDIRECT $DOWNLOAD_OUTPUT "hugow" "https://github.com/khos2ow/hugo-wrapper/releases/download/${versionToDownload}/hugow" &
  263. wait
  264. printf "[done]\n"
  265. chmod +x hugow
  266. exit
  267. fi
  268. # ------------------------------------------------------------------------------
  269. # download hugo binary and save it as ${BASE_DIR}/.hugo/hugo
  270. # ------------------------------------------------------------------------------
  271. if [ -r "$BASE_DIR/.hugo/hugo" ]; then
  272. 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/ *$//')"
  273. if [ "$get_extended" = true ]; then
  274. suffix_extended_version="/extended"
  275. fi
  276. # download hugo binary and save it as ${BASE_DIR}/.hugo/hugo
  277. if [ -n "$get_version" ]; then
  278. if [ "${get_version}${suffix_extended_version}" != "$current_binary_version" ]; then
  279. # specified hugo version
  280. download_version "$get_version" $get_extended
  281. else
  282. echo "hugo binary version ${get_version}${suffix_extended_version} already exists"
  283. echo "${get_version}${suffix_extended_version}" > $BASE_DIR/.hugo/version
  284. fi
  285. elif [ $get_latest = true ]; then
  286. latest_release=`$DOWNLOAD_COMMAND $DOWNLOAD_SILENT $DOWNLOAD_REDIRECT ${DOWNLOAD_OUTPUT}- https://api.github.com/repos/gohugoio/hugo/releases/latest`
  287. latest_version=`parse_json "$latest_release" "tag_name" | sed -ne 's/[^0-9]*\(\([0-9]*\.\)\{0,4\}[0-9]*\(\/extended\)*\).*/\1/p'`
  288. if [ "${latest_version}${suffix_extended_version}" != "$current_binary_version" ]; then
  289. # latest hugo version
  290. download_version "$latest_version" $get_extended
  291. else
  292. echo "latest hugo binary version ${latest_version}${suffix_extended_version} already exists"
  293. echo "${latest_version}${suffix_extended_version}" > $BASE_DIR/.hugo/version
  294. fi
  295. elif [ -r "$BASE_DIR/.hugo/version" ]; then
  296. current_file_version="$(cat "$BASE_DIR/.hugo/version")"
  297. if [ "$current_file_version" != "$current_binary_version" ]; then
  298. version_from_file="$(echo "$current_file_version" | cut -d "/" -f1)"
  299. extended_from_file="$(echo "$current_file_version" | cut -d "/" -f2)"
  300. if [ "${extended_from_file}" = "extended" ]; then
  301. isExtended=true
  302. else
  303. isExtended=false
  304. fi
  305. # specified hugo version
  306. download_version "$version_from_file" $isExtended
  307. fi
  308. else
  309. # save the current binary version into $BASE_DIR/.hugo/version
  310. echo "$current_binary_version" > $BASE_DIR/.hugo/version
  311. fi
  312. else
  313. if [ -n "$get_version" ]; then
  314. # specified hugo version
  315. download_version "$get_version" $get_extended
  316. elif [ $get_latest = true ]; then
  317. # latest hugo version
  318. download_version "LATEST" $get_extended
  319. elif [ -r "$BASE_DIR/.hugo/version" ]; then
  320. # specified hugo version
  321. version_from_file="$(cat "$BASE_DIR/.hugo/version" | cut -d "/" -f1)"
  322. extended_from_file="$(cat "$BASE_DIR/.hugo/version" | cut -d "/" -f2)"
  323. if [ "${extended_from_file}" = "extended" ]; then
  324. isExtended=true
  325. else
  326. isExtended=false
  327. fi
  328. download_version "${version_from_file}" $isExtended
  329. else
  330. # latest hugo version
  331. download_version "LATEST" $get_extended
  332. fi
  333. fi
  334. # ------------------------------------------------------------------------------
  335. # only download binary and not execute hugo related command
  336. # ------------------------------------------------------------------------------
  337. if [ "$get_latest" = true -o -n "$get_version" ]; then
  338. ${BASE_DIR}/.hugo/hugo version
  339. exit
  340. fi
  341. # ------------------------------------------------------------------------------
  342. # Show help, both from hugow and ${BASE_DIR}/.hugo/hugo
  343. # ------------------------------------------------------------------------------
  344. if [ $show_help = true ]; then
  345. help=$(${BASE_DIR}/.hugo/hugo --help)
  346. cat << USAGE
  347. hugow is the universal wrapper for hugo main command.
  348. Hugo is a Fast and Flexible Static Site Generator
  349. built with love by spf13 and friends in Go.
  350. Complete documentation is available at http://gohugo.io/.
  351. Flags:
  352. --get-extended get hugo extended binary
  353. --get-latest get latest version of hugo binary
  354. --get-version string get specified version of hugo binary
  355. --upgrade upgrade hugo wrapper binary itself
  356. --version show version of hugo wrapper binary itself
  357. -h, --help help for hugo-wrapper
  358. --------
  359. $help
  360. USAGE
  361. exit 0
  362. fi
  363. # ------------------------------------------------------------------------------
  364. # pass commands and flags to actual hugo binary
  365. # ------------------------------------------------------------------------------
  366. ${BASE_DIR}/.hugo/hugo "$@"