2016-06-07 15:08:52 +00:00
package installer
2016-03-06 20:37:49 +00:00
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"os"
"os/exec"
"path/filepath"
2016-06-07 18:00:07 +00:00
"regexp"
2016-03-06 20:37:49 +00:00
"runtime"
"github.com/mitchellh/go-homedir"
"github.com/pivotal-golang/archiver/extractor"
)
const (
2016-06-07 18:00:07 +00:00
version = "0.16"
2016-03-06 20:37:49 +00:00
baseurl = "https://github.com/spf13/hugo/releases/download/v" + version + "/"
)
2016-06-07 18:00:07 +00:00
var caddy , bin , temp , hugo , tempfile , zipname , exename string
2016-03-06 20:37:49 +00:00
// GetPath retrives the Hugo path for the user or install it if it's not found
func GetPath ( ) string {
initializeVariables ( )
var err error
// Check if Hugo is already on $PATH
2016-06-07 15:27:42 +00:00
if hugo , err = exec . LookPath ( "hugo" ) ; err == nil {
2016-06-07 18:00:07 +00:00
if checkVersion ( ) {
return hugo
}
2016-03-06 20:37:49 +00:00
}
// Check if Hugo is on $HOME/.caddy/bin
if _ , err = os . Stat ( hugo ) ; err == nil {
2016-06-07 18:00:07 +00:00
if checkVersion ( ) {
return hugo
}
2016-03-06 20:37:49 +00:00
}
fmt . Println ( "Unable to find Hugo on your computer." )
// Create the neccessary folders
os . MkdirAll ( caddy , 0774 )
os . Mkdir ( bin , 0774 )
if temp , err = ioutil . TempDir ( "" , "caddy-hugo" ) ; err != nil {
fmt . Println ( err )
os . Exit ( - 1 )
}
downloadHugo ( )
checkSHA256 ( )
fmt . Print ( "Unzipping... " )
// Unzip or Ungzip the file
switch runtime . GOOS {
case "darwin" , "windows" :
zp := extractor . NewZip ( )
err = zp . Extract ( tempfile , temp )
default :
gz := extractor . NewTgz ( )
err = gz . Extract ( tempfile , temp )
}
if err != nil {
fmt . Println ( err )
os . Exit ( - 1 )
}
fmt . Println ( "done." )
var exetorename string
err = filepath . Walk ( temp , func ( path string , f os . FileInfo , err error ) error {
if f . Name ( ) == exename {
exetorename = path
}
return nil
} )
// Copy the file
fmt . Print ( "Moving Hugo executable... " )
2016-06-21 15:35:42 +00:00
err = CopyFile ( exetorename , hugo )
2016-03-06 20:37:49 +00:00
if err != nil {
fmt . Println ( err )
os . Exit ( - 1 )
}
err = os . Chmod ( hugo , 0755 )
if err != nil {
fmt . Println ( err )
os . Exit ( - 1 )
}
fmt . Println ( "done." )
fmt . Println ( "Hugo installed at " + hugo )
defer os . RemoveAll ( temp )
return hugo
}
func initializeVariables ( ) {
2016-06-07 18:00:07 +00:00
var arch string
switch runtime . GOARCH {
case "amd64" :
arch = "64bit"
case "386" :
arch = "32bit"
case "arm" :
arch = "arm32"
default :
arch = runtime . GOARCH
}
var ops = runtime . GOOS
if runtime . GOOS == "darwin" && runtime . GOARCH != "arm" {
ops = "osx"
}
exename = "hugo"
zipname = "hugo_" + version + "_" + ops + "-" + arch
2016-03-06 20:37:49 +00:00
homedir , err := homedir . Dir ( )
if err != nil {
fmt . Println ( err )
os . Exit ( - 1 )
}
caddy = filepath . Join ( homedir , ".caddy" )
bin = filepath . Join ( caddy , "bin" )
hugo = filepath . Join ( bin , "hugo" )
switch runtime . GOOS {
case "windows" :
zipname += ".zip"
exename += ".exe"
hugo += ".exe"
default :
2016-06-07 18:00:07 +00:00
zipname += ".tgz"
2016-03-06 20:37:49 +00:00
}
}
2016-06-07 18:00:07 +00:00
func checkVersion ( ) bool {
out , _ := exec . Command ( "hugo" , "version" ) . Output ( )
r := regexp . MustCompile ( ` v\d\.\d { 2} ` )
v := r . FindStringSubmatch ( string ( out ) ) [ 0 ]
v = v [ 1 : len ( v ) ]
return ( v == version )
}
2016-03-06 20:37:49 +00:00
func downloadHugo ( ) {
tempfile = filepath . Join ( temp , zipname )
fmt . Print ( "Downloading Hugo from GitHub releases... " )
// Create the file
out , err := os . Create ( tempfile )
out . Chmod ( 0774 )
if err != nil {
defer os . RemoveAll ( temp )
fmt . Println ( err )
os . Exit ( - 1 )
}
defer out . Close ( )
// Get the data
resp , err := http . Get ( baseurl + zipname )
if err != nil {
fmt . Println ( "An error ocurred while downloading. If this error persists, try downloading Hugo from \"https://github.com/spf13/hugo/releases/\" and put the executable in " + bin + " and rename it to 'hugo' or 'hugo.exe' if you're on Windows." )
fmt . Println ( err )
os . Exit ( - 1 )
}
defer resp . Body . Close ( )
// Writer the body to file
_ , err = io . Copy ( out , resp . Body )
if err != nil {
fmt . Println ( err )
os . Exit ( - 1 )
}
fmt . Println ( "downloaded." )
}
func checkSHA256 ( ) {
fmt . Print ( "Checking SHA256..." )
hasher := sha256 . New ( )
f , err := os . Open ( tempfile )
if err != nil {
log . Fatal ( err )
}
defer f . Close ( )
if _ , err := io . Copy ( hasher , f ) ; err != nil {
log . Fatal ( err )
}
if hex . EncodeToString ( hasher . Sum ( nil ) ) != sha256Hash [ zipname ] {
fmt . Println ( "can't verify SHA256." )
os . Exit ( - 1 )
}
fmt . Println ( "checked!" )
}
2016-06-21 15:35:42 +00:00
// CopyFile is used to copy a file
func CopyFile ( old , new string ) error {
// Open the file and create a new one
r , err := os . Open ( old )
if err != nil {
return err
}
defer r . Close ( )
w , err := os . Create ( new )
if err != nil {
return err
}
defer w . Close ( )
// Copy the content
_ , err = io . Copy ( w , r )
if err != nil {
return err
}
return nil
}