<commit_before>package main

import (
	"fmt"
	gltext "github.com/4ydx/gltext"
	glfw "github.com/go-gl/glfw3"
	gl32 "github.com/go-gl/glow/gl-core/3.2/gl"
	"github.com/go-gl/glow/gl-core/3.3/gl"
	"os"
	"runtime"
)

var useStrictCoreProfile = (runtime.GOOS == "darwin")

func errorCallback(err glfw.ErrorCode, desc string) {
	fmt.Printf("%v: %v\n", err, desc)
}

func main() {
	runtime.LockOSThread()

	glfw.SetErrorCallback(errorCallback)
	if !glfw.Init() {
		panic("glfw error")
	}
	defer glfw.Terminate()

	glfw.WindowHint(glfw.Resizable, glfw.False)
	glfw.WindowHint(glfw.ContextVersionMajor, 3)
	glfw.WindowHint(glfw.ContextVersionMinor, 3)
	if useStrictCoreProfile {
		glfw.WindowHint(glfw.OpenglForwardCompatible, glfw.True)
		glfw.WindowHint(glfw.OpenglProfile, glfw.OpenglCoreProfile)
	}
	glfw.WindowHint(glfw.OpenglDebugContext, glfw.True)

	window, err := glfw.CreateWindow(640, 480, "Testing", nil, nil)
	if err != nil {
		panic(err)
	}
	window.MakeContextCurrent()

	if err := gl.Init(); err != nil {
		panic(err)
	}
	if err := gl32.Init(); err != nil {
		fmt.Println("could not initialize GL 3.2")
	}
	version := gl.GoStr(gl.GetString(gl.VERSION))
	fmt.Println("Opengl version", version)

	fd, err := os.Open("font/luximr.ttf")
	if err != nil {
		panic(err)
	}
	defer fd.Close()

	scale := int32(32)
	font, err := gltext.LoadTruetype(fd, scale, 32, 127)
	if err != nil {
		panic(err)
	}
	width, height := window.GetSize()

	font.ResizeWindow(float32(width), float32(height))
	font.SetTextLowerBound(0.5)

	text := gltext.LoadText(font)
	str := "ABCDEFG"
	text.SetString(str)

	xPos := float32(-width)
	flow := float32(1)
	color := float32(0)
	gl.ClearColor(0.4, 0.4, 0.4, 0.0)
	for !window.ShouldClose() {
		gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)

		color += flow * 0.01
		if color > 1.0 {
			color = 1
			flow = -1
		}
		if color < 0.0 {
			color = 0
			flow = +1
		}
		xPos = flow * float32(width) * color
		text.SetPosition(xPos, 0)
		text.SetColor(color, color, color)
		text.SetScale(color + 0.5)
		text.Draw()

		window.SwapBuffers()
		glfw.PollEvents()
	}
	text.Release()
	font.Release()
}
<commit_msg>No longer required.<commit_after>package main

import (
	"fmt"
	gltext "github.com/4ydx/gltext"
	glfw "github.com/go-gl/glfw3"
	gl32 "github.com/go-gl/glow/gl-core/3.2/gl"
	"github.com/go-gl/glow/gl-core/3.3/gl"
	"os"
	"runtime"
)

var useStrictCoreProfile = (runtime.GOOS == "darwin")

func errorCallback(err glfw.ErrorCode, desc string) {
	fmt.Printf("%v: %v\n", err, desc)
}

func main() {
	runtime.LockOSThread()

	glfw.SetErrorCallback(errorCallback)
	if !glfw.Init() {
		panic("glfw error")
	}
	defer glfw.Terminate()

	glfw.WindowHint(glfw.Resizable, glfw.False)
	glfw.WindowHint(glfw.ContextVersionMajor, 3)
	glfw.WindowHint(glfw.ContextVersionMinor, 3)
	if useStrictCoreProfile {
		glfw.WindowHint(glfw.OpenglForwardCompatible, glfw.True)
		glfw.WindowHint(glfw.OpenglProfile, glfw.OpenglCoreProfile)
	}
	glfw.WindowHint(glfw.OpenglDebugContext, glfw.True)

	window, err := glfw.CreateWindow(640, 480, "Testing", nil, nil)
	if err != nil {
		panic(err)
	}
	window.MakeContextCurrent()

	if err := gl.Init(); err != nil {
		panic(err)
	}
	if err := gl32.Init(); err != nil {
		fmt.Println("could not initialize GL 3.2")
	}
	version := gl.GoStr(gl.GetString(gl.VERSION))
	fmt.Println("Opengl version", version)

	fd, err := os.Open("font/luximr.ttf")
	if err != nil {
		panic(err)
	}
	defer fd.Close()

	scale := int32(32)
	font, err := gltext.LoadTruetype(fd, scale, 32, 127)
	if err != nil {
		panic(err)
	}
	width, height := window.GetSize()

	font.ResizeWindow(float32(width), float32(height))

	text := gltext.LoadText(font)
	str := "ABCDEFG"
	text.SetString(str)

	xPos := float32(-width)
	flow := float32(1)
	color := float32(0)
	gl.ClearColor(0.4, 0.4, 0.4, 0.0)
	for !window.ShouldClose() {
		gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)

		color += flow * 0.01
		if color > 1.0 {
			color = 1
			flow = -1
		}
		if color < 0.0 {
			color = 0
			flow = +1
		}
		xPos = flow * float32(width) * color
		text.SetPosition(xPos, 0)
		text.SetColor(color, color, color)
		text.SetScale(color + 0.5)
		text.Draw()

		window.SwapBuffers()
		glfw.PollEvents()
	}
	text.Release()
	font.Release()
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"runtime"
	"time"

	"github.com/cespare/window"
	"github.com/jeanfric/goembed/countingwriter"
)

const Version = "0.1.0"

var (
	toFlag      = flag.String("to", "", "email address to send output to")
	subjectFlag = flag.String("s", "", "subject of email (optional)")
	maxFlag     = flag.Int("max", 10000, "max bytes to capture for stdout/stderr")
	onErrorFlag = flag.Bool("on-error", false, "only notify on a non-0 exit code")
)

func usageAndExit(s string) {
	fmt.Printf("!! %s\n", s)
	flag.Usage()
	fmt.Println()
	fmt.Printf("%s version: %s (%s on %s/%s; %s)\n", os.Args[0], Version, runtime.Version(), runtime.GOOS, runtime.GOARCH, runtime.Compiler)
	os.Exit(1)
}

func init() {
	runtime.GOMAXPROCS(1)
	runtime.LockOSThread()

	flag.Usage = func() {
		fmt.Fprint(os.Stderr, "usage: email-me [flags] [command]\n")
		flag.PrintDefaults()
	}
	flag.Parse()
}

func main() {
	if *toFlag == "" {
		usageAndExit("missing -to=[address]")
	}

	args := flag.Args()
	if len(args) == 0 {
		usageAndExit("missing [command]")
	}

	truncStdout := window.NewWriter(*maxFlag)
	truncStderr := window.NewWriter(*maxFlag)
	countedStdout := countingwriter.New(truncStdout)
	countedStderr := countingwriter.New(truncStderr)
	child := exec.Command(args[0], args[1:]...)
	child.Stdout = io.MultiWriter(os.Stdout, countedStdout)
	child.Stderr = io.MultiWriter(os.Stderr, countedStderr)
	child.Stdin = os.Stdin

	start := time.Now()
	err := child.Run()
	end := time.Now()

	stdout := truncStdout.Bytes()
	stderr := truncStderr.Bytes()

	r := &Result{
		Cmd:         child,
		Error:       err,
		Start:       start,
		End:         end,
		Duration:    end.Sub(start),
		Stdout:      string(stdout),
		Stderr:      string(stderr),
		StdoutExtra: countedStdout.BytesWritten() - len(stdout),
		StderrExtra: countedStderr.BytesWritten() - len(stderr),
	}

	me := identity()
	subject := *subjectFlag
	if subject == "" {
		subject = fmt.Sprintf("%s", child.Args)
	}

	m := &Message{
		To:      *toFlag,
		From:    me,
		Subject: subject,
		Result:  r,
	}

	success := child.ProcessState.Success()

	if *onErrorFlag && success {
		os.Exit(0)
	}

	if err := findMailer().Send([]string{*toFlag}, me, m.Bytes()); err != nil {
		log.Fatal(err)
	}

	if !success {
		os.Exit(1)
	}
}
<commit_msg>main: version 0.2.0<commit_after>package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"runtime"
	"time"

	"github.com/cespare/window"
	"github.com/jeanfric/goembed/countingwriter"
)

const Version = "0.2.0"

var (
	toFlag      = flag.String("to", "", "email address to send output to")
	subjectFlag = flag.String("s", "", "subject of email (optional)")
	maxFlag     = flag.Int("max", 10000, "max bytes to capture for stdout/stderr")
	onErrorFlag = flag.Bool("on-error", false, "only notify on a non-0 exit code")
)

func usageAndExit(s string) {
	fmt.Printf("!! %s\n", s)
	flag.Usage()
	fmt.Println()
	fmt.Printf("%s version: %s (%s on %s/%s; %s)\n", os.Args[0], Version, runtime.Version(), runtime.GOOS, runtime.GOARCH, runtime.Compiler)
	os.Exit(1)
}

func init() {
	runtime.GOMAXPROCS(1)
	runtime.LockOSThread()

	flag.Usage = func() {
		fmt.Fprint(os.Stderr, "usage: email-me [flags] [command]\n")
		flag.PrintDefaults()
	}
	flag.Parse()
}

func main() {
	if *toFlag == "" {
		usageAndExit("missing -to=[address]")
	}

	args := flag.Args()
	if len(args) == 0 {
		usageAndExit("missing [command]")
	}

	truncStdout := window.NewWriter(*maxFlag)
	truncStderr := window.NewWriter(*maxFlag)
	countedStdout := countingwriter.New(truncStdout)
	countedStderr := countingwriter.New(truncStderr)
	child := exec.Command(args[0], args[1:]...)
	child.Stdout = io.MultiWriter(os.Stdout, countedStdout)
	child.Stderr = io.MultiWriter(os.Stderr, countedStderr)
	child.Stdin = os.Stdin

	start := time.Now()
	err := child.Run()
	end := time.Now()

	stdout := truncStdout.Bytes()
	stderr := truncStderr.Bytes()

	r := &Result{
		Cmd:         child,
		Error:       err,
		Start:       start,
		End:         end,
		Duration:    end.Sub(start),
		Stdout:      string(stdout),
		Stderr:      string(stderr),
		StdoutExtra: countedStdout.BytesWritten() - len(stdout),
		StderrExtra: countedStderr.BytesWritten() - len(stderr),
	}

	me := identity()
	subject := *subjectFlag
	if subject == "" {
		subject = fmt.Sprintf("%s", child.Args)
	}

	m := &Message{
		To:      *toFlag,
		From:    me,
		Subject: subject,
		Result:  r,
	}

	success := child.ProcessState.Success()

	if *onErrorFlag && success {
		os.Exit(0)
	}

	if err := findMailer().Send([]string{*toFlag}, me, m.Bytes()); err != nil {
		log.Fatal(err)
	}

	if !success {
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>/**
* Welcome to Beacon; an application for keeping teams in sync with breaking changes in their codebases.
* This application is built with Golang! The Maintainer (yours truly) has not written much Golang so
* Refactors, tips, and working things out together is greatly appreciated.
* Please refer to our github issues page for working on this project! https://github.com/the-heap/beacon/issues
*
*** ======== Useful links, Resources, etc: ============ ***
  * 🗯 Join our Slack group:              https://slackin-onxcmypksl.now.sh/
  * 🎒 Learn about the Heap:              http://theheap.us/page/about/
  * 🎩 New to Open source resoures:       https://theheap.us/page/resources/
  * 🐹 Golang tips:                       https://gobyexample.com/
  * 🎧 Cool Golang podcast:               http://gotime.fm/
*** =================================================== ***
*
*/

package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
)

// ============================
// Types
// ============================

// BeaconLog represents the entire blob of json from the beacon file
type BeaconLog struct {
	Logs []Log
}

// Log is a single entry in the BeaconLog;
//
// _Example_: a user submits a breaking change to the database,
// in which they would fill out all the info in this struct.
type Log struct {
	ID      string
	Date    string
	Email   string
	Author  string
	Message string
}

// ============================
// Vars and Constants
// ============================

var beaconLogData BeaconLog

// ============================
// FUNCS
// ============================

func checkError(e error) {
	if e != nil {
		panic(e)
	}
}

// Print the beacon log to the terminal
func printLog(data BeaconLog) {
	for _, element := range data.Logs {
		fmt.Println("")
		fmt.Println("==========================================")
		fmt.Println("Date: ", element.Date)
		fmt.Println("Author: ", element.Author+" ("+element.Email+")") // I bet there's a nicer way to do this.
		fmt.Println("Message: ", element.Message)
		fmt.Println("==========================================")
	}
}

// loadConfig loads the .beaconrc file into the beaconConfig
func loadConfig(config *beaconConfig) error {
	configFile, err := ioutil.ReadFile("./.beaconrc")
	if err != nil {
		return err
	}

	return json.Unmarshal(configFile, &config)
}

// ============================
// MAIN!
// ============================
func main() {
	var config beaconConfig

	if err := loadConfig(&config); err != nil {
		log.Fatal(err)
	}

	// read JSON file from disk
	beaconLogFile, err := ioutil.ReadFile("./beacon_log.json")

	checkError(err)

	// unmarshal json and store it in the pointer to beaconLogData {?}
	// NOTE: figure out if you can use `checkError` here; don't yet understand golang's idiomatic errors handling.
	if err := json.Unmarshal(beaconLogFile, &beaconLogData); err != nil {
		panic(err)
	}

	// Print the beacon log!
	printLog(beaconLogData)
}

type beaconConfig struct {
	Author string `json:"author"`
	Email  string `json:"email"`
}
<commit_msg>Move beaconConfig to TYPES section<commit_after>/**
* Welcome to Beacon; an application for keeping teams in sync with breaking changes in their codebases.
* This application is built with Golang! The Maintainer (yours truly) has not written much Golang so
* Refactors, tips, and working things out together is greatly appreciated.
* Please refer to our github issues page for working on this project! https://github.com/the-heap/beacon/issues
*
*** ======== Useful links, Resources, etc: ============ ***
  * 🗯 Join our Slack group:              https://slackin-onxcmypksl.now.sh/
  * 🎒 Learn about the Heap:              http://theheap.us/page/about/
  * 🎩 New to Open source resoures:       https://theheap.us/page/resources/
  * 🐹 Golang tips:                       https://gobyexample.com/
  * 🎧 Cool Golang podcast:               http://gotime.fm/
*** =================================================== ***
*
*/

package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
)

// ============================
// Types
// ============================

// BeaconLog represents the entire blob of json from the beacon file
type BeaconLog struct {
	Logs []Log
}

// Log is a single entry in the BeaconLog;
//
// _Example_: a user submits a breaking change to the database,
// in which they would fill out all the info in this struct.
type Log struct {
	ID      string
	Date    string
	Email   string
	Author  string
	Message string
}

type beaconConfig struct {
	Author string `json:"author"`
	Email  string `json:"email"`
}

// ============================
// Vars and Constants
// ============================

var beaconLogData BeaconLog

// ============================
// FUNCS
// ============================

func checkError(e error) {
	if e != nil {
		panic(e)
	}
}

// Print the beacon log to the terminal
func printLog(data BeaconLog) {
	for _, element := range data.Logs {
		fmt.Println("")
		fmt.Println("==========================================")
		fmt.Println("Date: ", element.Date)
		fmt.Println("Author: ", element.Author+" ("+element.Email+")") // I bet there's a nicer way to do this.
		fmt.Println("Message: ", element.Message)
		fmt.Println("==========================================")
	}
}

// loadConfig loads the .beaconrc file into the beaconConfig
func loadConfig(config *beaconConfig) error {
	configFile, err := ioutil.ReadFile("./.beaconrc")
	if err != nil {
		return err
	}

	return json.Unmarshal(configFile, &config)
}

// ============================
// MAIN!
// ============================
func main() {
	var config beaconConfig

	if err := loadConfig(&config); err != nil {
		log.Fatal(err)
	}

	// read JSON file from disk
	beaconLogFile, err := ioutil.ReadFile("./beacon_log.json")

	checkError(err)

	// unmarshal json and store it in the pointer to beaconLogData {?}
	// NOTE: figure out if you can use `checkError` here; don't yet understand golang's idiomatic errors handling.
	if err := json.Unmarshal(beaconLogFile, &beaconLogData); err != nil {
		panic(err)
	}

	// Print the beacon log!
	printLog(beaconLogData)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/http"
	"io"
	"flag"
	"os"
	"os/exec"
	"log"
	"math"
	"strings"
)

const BYTES = 2048
const NAME = "goGet"

func main() {

	continued := false
    flag.Usage = usage

    // Set the flag to the variable
	flag.BoolVar(&continued ,"continue", false, NAME + " --continue [url]")
    flag.Parse()

    args := flag.Args()
    if len(args) < 1 {
        fmt.Printf("Input URL is missing.\n");
        os.Exit(1);
    }
	url_reader(args[0], continued)
}

func usage() {

    fmt.Fprintf(os.Stderr, "Usage: %s [url]\n", NAME)

    flag.PrintDefaults()
    os.Exit(2)
}

// Function to get the size of the local file, used when the downloading is continued
func file_size(file_name string) int64 {

	file, err := os.Open(file_name)
	if err != nil {
		return 0
	}
	defer file.Close()

	file_stat, err := file.Stat()
	return file_stat.Size()
}

// Showing the status of the download in console
func show_data(url string, file_name string, remote_size int64, file_part int64, percent *float64) {

	new_percent := math.Floor((float64(file_part) / float64(remote_size)) * 100.00)
	// Only refresh the data with integers
	if new_percent > *percent {
		clear := exec.Command("clear")
		clear.Stdout = os.Stdout
		clear.Run()
		fmt.Printf("Downloading file from %s\n", url);
		fmt.Printf("Saving file to: %s\n", file_name);
		fmt.Printf("%.0f%% of 100%%\n", new_percent)
		fmt.Printf("%d of %d bytes\n", file_part, remote_size)
	}
	*percent = new_percent
}

// Function for retrieve the data of the file from URL
func get_url(url string, continued bool) (string, int64, int64, *http.Response, error) {

	remote_size := int64(0)
	file_part := int64(0)
	file_name := string("")

	resp, err := http.Get(url)
	if err != nil {
		return  file_name, remote_size, file_part, resp, err
	}
	last_slash := strings.LastIndex(resp.Request.URL.Path, "/") // Getting the index of the last slash
	file_name = resp.Request.URL.Path[last_slash+1:] // Saving the name of the file

	if continued {
		file_part = file_size(file_name) // Getting size of the local file

		// If local file and remote has diferent size, then set the range to download
		if file_part != resp.ContentLength {
			range_part := fmt.Sprintf("bytes=%d-%d", file_part, resp.ContentLength)
			resp.Request.Header.Add("Range", range_part)
			// Doing a new request with the set range
			client := &http.Client{}
			resp, err = client.Do(resp.Request)
			if err != nil {
				return  file_name, remote_size, file_part, resp, err
			}
		}
		// Saving the size of the remote file
		if file_part == resp.ContentLength {
			remote_size = resp.ContentLength
		} else if file_part != resp.ContentLength {
			remote_size = resp.ContentLength + file_part
		}
	} else {
 		os.Remove(file_name) // If there is a previous file, this is deleted
		file, err := os.OpenFile(file_name, os.O_RDWR|os.O_CREATE, 0666) // Create a new file
		if err != nil {
			return file_name, remote_size, file_part, resp, err
		}
		file.Close()
		remote_size = resp.ContentLength
	}
	return file_name, remote_size, file_part, resp, err
}
// Function to get the file from URL and save it in to disc
func url_reader(url string, continued bool) int64 {

	file_name, remote_size, file_part, resp, err := get_url(url, continued)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	accum := int64(file_part) // read bytes
	percent := float64(0)
	buffer := make([]byte, BYTES)

	// loop to read the remote file and write the local file
	for {
		n, err := resp.Body.Read(buffer)
		if err != nil && err != io.EOF {
			log.Fatal(err)
		}
		if n == 0 {
			return accum
		}
		if remote_size == accum {
			fmt.Printf("File is already on disc\n")
			return accum
		}
		accum += int64(n)
		err = file_writer(file_name, buffer[0:n], accum)
		if err != nil {
			log.Fatal(err)
		}
		// Refresh data in console
		show_data(url, file_name, remote_size, accum, &percent)
	}
	return accum
}

// Function to write the buffer in to the local file
func file_writer(file_name string, buffer []byte, offset int64) (error) {
	// For read and write access, if file don't exist this is created.
	file, err := os.OpenFile(file_name, os.O_RDWR|os.O_CREATE, 0660)
	if err != nil {
		return err
	}
	defer file.Close()
	// The write begin with an offset
	_, err = file.WriteAt(buffer, offset)
	if err != nil {
		return err
	}
	return nil
}
<commit_msg>When file is complete on disc, --continue is stopped<commit_after>package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"math"
	"net/http"
	"os"
	"os/exec"
	"strings"
)

const BYTES = 2048
const NAME = "goGet"

func main() {

	continued := false
	flag.Usage = usage

	// Set the flag to the variable
	flag.BoolVar(&continued, "continue", false, NAME+" --continue [url]")
	flag.Parse()

	args := flag.Args()
	if len(args) < 1 {
		fmt.Printf("Input URL is missing.\n")
		os.Exit(1)
	}
	url_reader(args[0], continued)
}

func usage() {

	fmt.Fprintf(os.Stderr, "Usage: %s [url]\n", NAME)

	flag.PrintDefaults()
	os.Exit(2)
}

// Function to get the size of the local file, used when the downloading is continued
func file_size(file_name string) int64 {

	file, err := os.Open(file_name)
	if err != nil {
		return 0
	}
	defer file.Close()

	file_stat, err := file.Stat()
	return file_stat.Size()
}

// Showing the status of the download in console
func show_data(url string, file_name string, remote_size int64, file_part int64, percent *float64) {

	new_percent := math.Floor((float64(file_part) / float64(remote_size)) * 100.00)
	// Only refresh the data with integers
	if new_percent > *percent {
		clear := exec.Command("clear")
		clear.Stdout = os.Stdout
		clear.Run()
		fmt.Printf("Downloading file from %s\n", url)
		fmt.Printf("Saving file to: %s\n", file_name)
		fmt.Printf("%.0f%% of 100%%\n", new_percent)
		fmt.Printf("%d of %d bytes\n", file_part, remote_size)
	}
	*percent = new_percent
}

// Function for retrieve the data of the file from URL
func get_url(url string, continued bool) (string, int64, int64, *http.Response, error) {

	remote_size := int64(0)
	file_part := int64(0)
	file_name := string("")

	resp, err := http.Get(url)
	if err != nil {
		return file_name, remote_size, file_part, resp, err
	}
	last_slash := strings.LastIndex(resp.Request.URL.Path, "/") // Getting the index of the last slash
	file_name = resp.Request.URL.Path[last_slash+1:]            // Saving the name of the file

	if continued {
		file_part = file_size(file_name) // Getting size of the local file

		// Saving the size of the remote file
		if file_part == resp.ContentLength {
			remote_size = resp.ContentLength
			// If local file and remote has diferent size, then set the range to download
		} else if file_part != resp.ContentLength {
			range_part := fmt.Sprintf("bytes=%d-%d", file_part, resp.ContentLength)
			resp.Request.Header.Add("Range", range_part)
			// Doing a new request with the set range
			client := &http.Client{}
			resp, err = client.Do(resp.Request)
			if err != nil {
				return file_name, remote_size, file_part, resp, err
			}
			remote_size = resp.ContentLength + file_part
		}
	} else {
		os.Remove(file_name)                                             // If there is a previous file, this is deleted
		file, err := os.OpenFile(file_name, os.O_RDWR|os.O_CREATE, 0666) // Create a new file
		if err != nil {
			return file_name, remote_size, file_part, resp, err
		}
		file.Close()
		remote_size = resp.ContentLength
	}
	return file_name, remote_size, file_part, resp, err
}

// Function to get the file from URL and save it in to disc
func url_reader(url string, continued bool) int64 {

	file_name, remote_size, file_part, resp, err := get_url(url, continued)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	accum := int64(file_part) // read bytes
	percent := float64(0)
	buffer := make([]byte, BYTES)

	// loop to read the remote file and write the local file
	for {
		n, err := resp.Body.Read(buffer)
		if err != nil && err != io.EOF {
			log.Fatal(err)
		}
		if n == 0 {
			return accum
		}
		if remote_size == accum {
			fmt.Printf("File is already on disc\n")
			return accum
		}
		err = file_writer(file_name, buffer[0:n], accum)
		if err != nil {
			log.Fatal(err)
		}
		accum += int64(n)
		// Refresh data in console
		show_data(url, file_name, remote_size, accum, &percent)
	}
	return accum
}

// Function to write the buffer in to the local file
func file_writer(file_name string, buffer []byte, offset int64) error {
	// For read and write access, if file don't exist this is created.
	file, err := os.OpenFile(file_name, os.O_RDWR|os.O_CREATE, 0660)
	if err != nil {
		return err
	}
	defer file.Close()
	// The write begin with an offset
	_, err = file.WriteAt(buffer, offset)
	if err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/dimfeld/httptreemux"
	"github.com/kabukky/httpscerts"
	"github.com/kabukky/journey/configuration"
	"github.com/kabukky/journey/database"
	"github.com/kabukky/journey/filenames"
	"github.com/kabukky/journey/flags"
	"github.com/kabukky/journey/plugins"
	"github.com/kabukky/journey/server"
	"github.com/kabukky/journey/structure/methods"
	"github.com/kabukky/journey/templates"
	"log"
	"net/http"
	"os"
	"runtime"
	"strings"
)

func httpsRedirect(w http.ResponseWriter, r *http.Request, _ map[string]string) {
	http.Redirect(w, r, configuration.Config.HttpsUrl+r.RequestURI, http.StatusMovedPermanently)
	return
}

func checkHttpsCertificates() {
	// Check https certificates. If they are not available generate temporary ones for testing.
	err := httpscerts.Check(filenames.HttpsCertFilename, filenames.HttpsKeyFilename)
	if err != nil {
		log.Println("Warning: couldn't load https certs. Generating new ones. Replace " + filenames.HttpsCertFilename + " and " + filenames.HttpsKeyFilename + " with your own certificates as soon as possible!")
		err := httpscerts.Generate(filenames.HttpsCertFilename, filenames.HttpsKeyFilename, configuration.Config.HttpsUrl)
		if err != nil {
			log.Fatal("Error: Couldn't create https certificates.")
			return
		}
	}
}

func main() {
	// Setup
	var err error

	// GOMAXPROCS - Maybe not needed
	runtime.GOMAXPROCS(runtime.NumCPU())

	// Write log to file if the log flag was provided
	if flags.Log != "" {
		logFile, err := os.OpenFile(flags.Log, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		if err != nil {
			log.Fatal("Error: Couldn't open log file: " + err.Error())
		}
		defer logFile.Close()
		log.SetOutput(logFile)
	}

	// Configuration is read from config.json by loading the configuration package

	// Database
	err = database.Initialize()
	if err != nil {
		log.Fatal("Error: Couldn't initialize database:", err)
		return
	}

	// Global blog data
	err = methods.GenerateBlog()
	if err != nil {
		log.Fatal("Error: Couldn't generate blog data:", err)
		return
	}

	// Templates
	err = templates.Generate()
	if err != nil {
		log.Fatal("Error: Couldn't compile templates:", err)
		return
	}

	// Plugins
	err = plugins.Load()
	if err == nil {
		// Close LuaPool at the end
		defer plugins.LuaPool.Shutdown()
		log.Println("Plugins loaded.")
	}

	// HTTP(S) Server
	httpPort := configuration.Config.HttpHostAndPort
	httpsPort := configuration.Config.HttpsHostAndPort
	// Check if HTTP/HTTPS flags were provided
	if flags.HttpPort != "" {
		components := strings.SplitAfterN(httpPort, ":", 2)
		httpPort = components[0] + flags.HttpPort
	}
	if flags.HttpsPort != "" {
		components := strings.SplitAfterN(httpsPort, ":", 2)
		httpsPort = components[0] + flags.HttpsPort
	}
	// Determine the kind of https support (as set in the config.json)
	switch configuration.Config.HttpsUsage {
	case "AdminOnly":
		checkHttpsCertificates()
		httpRouter := httptreemux.New()
		httpsRouter := httptreemux.New()
		// Blog and pages as http
		server.InitializeBlog(httpRouter)
		server.InitializePages(httpRouter)
		// Blog and pages as https
		server.InitializeBlog(httpsRouter)
		server.InitializePages(httpsRouter)
		// Admin as https and http redirect
		// Add redirection to http router
		httpRouter.GET("/admin/", httpsRedirect)
		httpRouter.GET("/admin/*path", httpsRedirect)
		// Add routes to https router
		server.InitializeAdmin(httpsRouter)
		// Start https server
		log.Println("Starting https server on port " + httpsPort + "...")
		go func() {
			err := http.ListenAndServeTLS(httpsPort, filenames.HttpsCertFilename, filenames.HttpsKeyFilename, httpsRouter)
			if err != nil {
				log.Fatal("Error: Couldn't start the HTTPS server:", err)
			}
		}()
		// Start http server
		log.Println("Starting http server on port " + httpPort + "...")
		err := http.ListenAndServe(httpPort, httpRouter)
		if err != nil {
			log.Fatal("Error: Couldn't start the HTTP server:", err)
		}
	case "All":
		checkHttpsCertificates()
		httpsRouter := httptreemux.New()
		httpRouter := httptreemux.New()
		// Blog and pages as https
		server.InitializeBlog(httpsRouter)
		server.InitializePages(httpsRouter)
		// Admin as https
		server.InitializeAdmin(httpsRouter)
		// Add redirection to http router
		httpRouter.GET("/", httpsRedirect)
		httpRouter.GET("/*path", httpsRedirect)
		// Start https server
		log.Println("Starting https server on port " + httpsPort + "...")
		go func() {
			err := http.ListenAndServeTLS(httpsPort, filenames.HttpsCertFilename, filenames.HttpsKeyFilename, httpsRouter)
			if err != nil {
				log.Fatal("Error: Couldn't start the HTTPS server:", err)
			}
		}()
		// Start http server
		log.Println("Starting http server on port " + httpPort + "...")
		err := http.ListenAndServe(httpPort, httpRouter)
		if err != nil {
			log.Fatal("Error: Couldn't start the HTTP server:", err)
		}
	default: // This is configuration.HttpsUsage == "None"
		httpRouter := httptreemux.New()
		// Blog and pages as http
		server.InitializeBlog(httpRouter)
		server.InitializePages(httpRouter)
		// Admin as http
		server.InitializeAdmin(httpRouter)
		// Start http server
		log.Println("Starting server without HTTPS support. Please enable HTTPS in " + filenames.ConfigFilename + " to improve security.")
		log.Println("Starting http server on port " + httpPort + "...")
		err := http.ListenAndServe(httpPort, httpRouter)
		if err != nil {
			log.Fatal("Error: Couldn't start the HTTP server:", err)
		}
	}
}
<commit_msg>Terser if clauses<commit_after>package main

import (
	"github.com/dimfeld/httptreemux"
	"github.com/kabukky/httpscerts"
	"github.com/kabukky/journey/configuration"
	"github.com/kabukky/journey/database"
	"github.com/kabukky/journey/filenames"
	"github.com/kabukky/journey/flags"
	"github.com/kabukky/journey/plugins"
	"github.com/kabukky/journey/server"
	"github.com/kabukky/journey/structure/methods"
	"github.com/kabukky/journey/templates"
	"log"
	"net/http"
	"os"
	"runtime"
	"strings"
)

func httpsRedirect(w http.ResponseWriter, r *http.Request, _ map[string]string) {
	http.Redirect(w, r, configuration.Config.HttpsUrl+r.RequestURI, http.StatusMovedPermanently)
	return
}

func checkHttpsCertificates() {
	// Check https certificates. If they are not available generate temporary ones for testing.
	if err := httpscerts.Check(filenames.HttpsCertFilename, filenames.HttpsKeyFilename); err != nil {
		log.Println("Warning: couldn't load https certs. Generating new ones. Replace " + filenames.HttpsCertFilename + " and " + filenames.HttpsKeyFilename + " with your own certificates as soon as possible!")
		if err := httpscerts.Generate(filenames.HttpsCertFilename, filenames.HttpsKeyFilename, configuration.Config.HttpsUrl); err != nil {
			log.Fatal("Error: Couldn't create https certificates.")
			return
		}
	}
}

func main() {
	// Setup
	var err error

	// GOMAXPROCS - Maybe not needed
	runtime.GOMAXPROCS(runtime.NumCPU())

	// Write log to file if the log flag was provided
	if flags.Log != "" {
		logFile, err := os.OpenFile(flags.Log, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		if err != nil {
			log.Fatal("Error: Couldn't open log file: " + err.Error())
		}
		defer logFile.Close()
		log.SetOutput(logFile)
	}

	// Configuration is read from config.json by loading the configuration package

	// Database
	if err = database.Initialize(); err != nil {
		log.Fatal("Error: Couldn't initialize database:", err)
		return
	}

	// Global blog data
	if err = methods.GenerateBlog(); err != nil {
		log.Fatal("Error: Couldn't generate blog data:", err)
		return
	}

	// Templates
	if err = templates.Generate(); err != nil {
		log.Fatal("Error: Couldn't compile templates:", err)
		return
	}

	// Plugins
	if err = plugins.Load(); err != nil {
		// Close LuaPool at the end
		defer plugins.LuaPool.Shutdown()
		log.Println("Plugins loaded.")
	}

	// HTTP(S) Server
	httpPort := configuration.Config.HttpHostAndPort
	httpsPort := configuration.Config.HttpsHostAndPort
	// Check if HTTP/HTTPS flags were provided
	if flags.HttpPort != "" {
		components := strings.SplitAfterN(httpPort, ":", 2)
		httpPort = components[0] + flags.HttpPort
	}
	if flags.HttpsPort != "" {
		components := strings.SplitAfterN(httpsPort, ":", 2)
		httpsPort = components[0] + flags.HttpsPort
	}
	// Determine the kind of https support (as set in the config.json)
	switch configuration.Config.HttpsUsage {
	case "AdminOnly":
		checkHttpsCertificates()
		httpRouter := httptreemux.New()
		httpsRouter := httptreemux.New()
		// Blog and pages as http
		server.InitializeBlog(httpRouter)
		server.InitializePages(httpRouter)
		// Blog and pages as https
		server.InitializeBlog(httpsRouter)
		server.InitializePages(httpsRouter)
		// Admin as https and http redirect
		// Add redirection to http router
		httpRouter.GET("/admin/", httpsRedirect)
		httpRouter.GET("/admin/*path", httpsRedirect)
		// Add routes to https router
		server.InitializeAdmin(httpsRouter)
		// Start https server
		log.Println("Starting https server on port " + httpsPort + "...")
		go func() {
			if err := http.ListenAndServeTLS(httpsPort, filenames.HttpsCertFilename, filenames.HttpsKeyFilename, httpsRouter); err != nil {
				log.Fatal("Error: Couldn't start the HTTPS server:", err)
			}
		}()
		// Start http server
		log.Println("Starting http server on port " + httpPort + "...")
		if err := http.ListenAndServe(httpPort, httpRouter); err != nil {
			log.Fatal("Error: Couldn't start the HTTP server:", err)
		}
	case "All":
		checkHttpsCertificates()
		httpsRouter := httptreemux.New()
		httpRouter := httptreemux.New()
		// Blog and pages as https
		server.InitializeBlog(httpsRouter)
		server.InitializePages(httpsRouter)
		// Admin as https
		server.InitializeAdmin(httpsRouter)
		// Add redirection to http router
		httpRouter.GET("/", httpsRedirect)
		httpRouter.GET("/*path", httpsRedirect)
		// Start https server
		log.Println("Starting https server on port " + httpsPort + "...")
		go func() {
			if err := http.ListenAndServeTLS(httpsPort, filenames.HttpsCertFilename, filenames.HttpsKeyFilename, httpsRouter); err != nil {
				log.Fatal("Error: Couldn't start the HTTPS server:", err)
			}
		}()
		// Start http server
		log.Println("Starting http server on port " + httpPort + "...")
		if err := http.ListenAndServe(httpPort, httpRouter); err != nil {
			log.Fatal("Error: Couldn't start the HTTP server:", err)
		}
	default: // This is configuration.HttpsUsage == "None"
		httpRouter := httptreemux.New()
		// Blog and pages as http
		server.InitializeBlog(httpRouter)
		server.InitializePages(httpRouter)
		// Admin as http
		server.InitializeAdmin(httpRouter)
		// Start http server
		log.Println("Starting server without HTTPS support. Please enable HTTPS in " + filenames.ConfigFilename + " to improve security.")
		log.Println("Starting http server on port " + httpPort + "...")
		if err := http.ListenAndServe(httpPort, httpRouter); err != nil {
			log.Fatal("Error: Couldn't start the HTTP server:", err)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"os/signal"
	"syscall"

	"github.com/kiwiirc/webircgateway/pkg/webircgateway"
)

const VERSION = "0.2.4"

func init() {
	webircgateway.Version = VERSION
}

func main() {
	printVersion := flag.Bool("version", false, "Print the version")
	configFile := flag.String("config", "config.conf", "Config file location")
	runConfigTest := flag.Bool("test", false, "Just test the config file")
	flag.Parse()

	if *printVersion {
		fmt.Println(webircgateway.Version)
		os.Exit(0)
	}

	webircgateway.SetConfigFile(*configFile)
	log.Printf("Using config %s", webircgateway.CurrentConfigFile())

	err := webircgateway.LoadConfig()
	if err != nil {
		log.Printf("Config file error: %s", err.Error())
		os.Exit(1)
	}

	if *runConfigTest {
		// TODO: This
		log.Println("Config file is OK")
		os.Exit(0)
	}

	watchForSignals()
	webircgateway.Start()
}

func watchForSignals() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGHUP)
	go func() {
		for {
			<-c
			fmt.Println("Recieved SIGHUP, reloading config file")
			webircgateway.LoadConfig()
		}
	}()
}
<commit_msg>Version bump<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"os/signal"
	"syscall"

	"github.com/kiwiirc/webircgateway/pkg/webircgateway"
)

const VERSION = "0.2.5"

func init() {
	webircgateway.Version = VERSION
}

func main() {
	printVersion := flag.Bool("version", false, "Print the version")
	configFile := flag.String("config", "config.conf", "Config file location")
	runConfigTest := flag.Bool("test", false, "Just test the config file")
	flag.Parse()

	if *printVersion {
		fmt.Println(webircgateway.Version)
		os.Exit(0)
	}

	webircgateway.SetConfigFile(*configFile)
	log.Printf("Using config %s", webircgateway.CurrentConfigFile())

	err := webircgateway.LoadConfig()
	if err != nil {
		log.Printf("Config file error: %s", err.Error())
		os.Exit(1)
	}

	if *runConfigTest {
		// TODO: This
		log.Println("Config file is OK")
		os.Exit(0)
	}

	watchForSignals()
	webircgateway.Start()
}

func watchForSignals() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGHUP)
	go func() {
		for {
			<-c
			fmt.Println("Recieved SIGHUP, reloading config file")
			webircgateway.LoadConfig()
		}
	}()
}
<|endoftext|>


<commit_before>package logger

import (
	"fmt"
	"log"
	"os"
)

// Logger is a util class to print log in different level like DEBUG.
// It has 4 level: DEBUG, INFO, WARN, ERROR,
// and 2 exception logger: PANIC and FATAL
type Logger struct {
	Prefix string
	dl     *log.Logger
	il     *log.Logger
	wl     *log.Logger
	el     *log.Logger
	pl     *log.Logger
	fl     *log.Logger
}

// Logger level consts
const (
	LevelDebug int = iota
	LevelInfo
	LevelWarn
	LevelError
)

var (
	l = NewLogger("[Logger]")

	currentLevel = LevelDebug
)

// NewLogger create a new top level logger based on prefix.
func NewLogger(prefix string) *Logger {
	return &Logger{
		Prefix: prefix,
		dl:     log.New(os.Stdout, fmt.Sprintf("[%s] %s ", "DEBUG", prefix), log.LstdFlags),
		il:     log.New(os.Stdout, fmt.Sprintf("[%s] %s ", "INFO", prefix), log.LstdFlags),
		wl:     log.New(os.Stdout, fmt.Sprintf("[%s] %s ", "WARN", prefix), log.LstdFlags),
		el:     log.New(os.Stdout, fmt.Sprintf("[%s] %s ", "ERROR", prefix), log.LstdFlags),
		pl:     log.New(os.Stdout, fmt.Sprintf("[%s] %s ", "PANIC", prefix), log.LstdFlags),
		fl:     log.New(os.Stdout, fmt.Sprintf("[%s] %s ", "FATAL", prefix), log.LstdFlags),
	}
}

// Debug print log message as DEBUG leve.
// if you set log level higher than LevelDebug, no message will be print.
func (logger *Logger) Debug(data ...interface{}) {
	if currentLevel <= LevelDebug {
		logger.dl.Println(data)
	}
}

// Info print log message as INFO leve.
// If you set log level higher than LevelInfo, no message will be print.
func (logger *Logger) Info(data ...interface{}) {
	if currentLevel <= LevelInfo {
		logger.il.Println(data)
	}
}

// Warn print log message as WARN leve.
// If you set log level higher than LevelWarn, no message will be print.
func (logger *Logger) Warn(data ...interface{}) {
	if currentLevel <= LevelWarn {
		logger.wl.Println(data)
	}
}

// Error print log message as ERROR leve. This function do not create panic or fatal, it just print error message.
// If you want get a runtime panic or fatal, use Logger.Panic or Logger.Fatal instand.
func (logger *Logger) Error(data ...interface{}) {
	if currentLevel <= LevelError {
		logger.el.Println(data)
	}
}

// Panic print log message, and create a panic use the message.
func (logger *Logger) Panic(data ...interface{}) {
	logger.pl.Panicln(data)
}

// Fatal print log message, and create a fatal use the message.
func (logger *Logger) Fatal(data ...interface{}) {
	logger.fl.Fatalln(data)
}

// SubLogger create a new logger based on the logger.
// Prefix string of new logger will be concat of old and provided argument.
func (logger *Logger) SubLogger(prefix string) (subLogger *Logger) {
	subLogger = NewLogger(fmt.Sprintf("%s %s", logger.Prefix, prefix))
	return subLogger
}

// SetLevel set the minimum level that message will be print out
func SetLevel(level int) {
	if LevelDebug <= level && level < LevelError {
		currentLevel = level
	} else {
		l.Error("Set logger level", level, "failed, accepted range is", LevelInfo, "to", LevelError)
	}
}
<commit_msg>[*] 修正 logger 的行为，并修复注释<commit_after>package logger

import (
	"fmt"
	"log"
	"os"
)

// Logger is a util class to print log in different level like DEBUG.
// It has 4 level: DEBUG, INFO, WARN, ERROR,
// and 2 exception logger: PANIC and FATAL
type Logger struct {
	Prefix string
	dl     *log.Logger
	il     *log.Logger
	wl     *log.Logger
	el     *log.Logger
	pl     *log.Logger
	fl     *log.Logger
}

// Logger level consts
const (
	LevelDebug int = iota
	LevelInfo
	LevelWarn
	LevelError
)

var (
	l = NewLogger("[Logger]")

	currentLevel = LevelDebug
)

// NewLogger create a new top level logger based on prefix.
func NewLogger(prefix string) *Logger {
	return &Logger{
		Prefix: prefix,
		dl:     log.New(os.Stdout, fmt.Sprintf("[%s] %s ", "DEBUG", prefix), log.LstdFlags),
		il:     log.New(os.Stdout, fmt.Sprintf("[%s] %s ", "INFO", prefix), log.LstdFlags),
		wl:     log.New(os.Stdout, fmt.Sprintf("[%s] %s ", "WARN", prefix), log.LstdFlags),
		el:     log.New(os.Stdout, fmt.Sprintf("[%s] %s ", "ERROR", prefix), log.LstdFlags),
		pl:     log.New(os.Stdout, fmt.Sprintf("[%s] %s ", "PANIC", prefix), log.LstdFlags),
		fl:     log.New(os.Stdout, fmt.Sprintf("[%s] %s ", "FATAL", prefix), log.LstdFlags),
	}
}

// Debug print log message as DEBUG level.
// if you set log level higher than LevelDebug, no message will be print.
func (logger *Logger) Debug(data ...interface{}) {
	if currentLevel <= LevelDebug {
		logger.dl.Println(data...)
	}
}

// Info print log message as INFO level.
// If you set log level higher than LevelInfo, no message will be print.
func (logger *Logger) Info(data ...interface{}) {
	if currentLevel <= LevelInfo {
		logger.il.Println(data...)
	}
}

// Warn print log message as WARN level.
// If you set log level higher than LevelWarn, no message will be print.
func (logger *Logger) Warn(data ...interface{}) {
	if currentLevel <= LevelWarn {
		logger.wl.Println(data...)
	}
}

// Error print log message as ERROR level.
// This function do not create panic or fatal, it just print error message.
// If you want get a runtime panic or fatal, use Logger.Panic or Logger.Fatal instand.
func (logger *Logger) Error(data ...interface{}) {
	if currentLevel <= LevelError {
		logger.el.Println(data...)
	}
}

// Panic print log message, and create a panic use the message.
func (logger *Logger) Panic(data ...interface{}) {
	logger.pl.Panicln(data...)
}

// Fatal print log message, and create a fatal use the message.
func (logger *Logger) Fatal(data ...interface{}) {
	logger.fl.Fatalln(data...)
}

// SubLogger create a new logger based on the logger.
// Prefix string of new logger will be concat of old and provided argument.
func (logger *Logger) SubLogger(prefix string) (subLogger *Logger) {
	subLogger = NewLogger(fmt.Sprintf("%s %s", logger.Prefix, prefix))
	return subLogger
}

// SetLevel set the minimum level that message will be print out
func SetLevel(level int) {
	if LevelDebug <= level && level < LevelError {
		currentLevel = level
	} else {
		l.Error("Set logger level", level, "failed, accepted range is", LevelInfo, "to", LevelError)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"path"
	"strconv"
	"encoding/json"
	"database/sql"
	_ "github.com/lib/pq"
)

var workingDir string = path.Join(os.TempDir(), "apollo-audio")
var clipDir string = path.Join(workingDir, "clips")
var AAC string = "aac"
var M4A string = "m4a"
var OGG string = "ogg"

func check(e error) {
	if e != nil {
		panic(e)
	}
}

func exists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return true, err
}

func makeDir(dir string) {
	dirExists, err := exists(dir)
	check(err)
	if !dirExists {
		err := os.Mkdir(dir, 0777)
		check(err)
	}
}

func downloadFromS3AndSave(url string, filename string) string {
	clipPath := path.Join(clipDir, filename)
	if _, err := os.Stat(clipPath); err == nil {
		fmt.Println("file exists; skipping")
		return clipPath
	}
	fmt.Println(clipPath)
	fmt.Println("debug")
	out, err := os.Create(clipPath)
	check(err)
	defer out.Close()
	resp, err := http.Get(url)
	check(err)
	defer resp.Body.Close()
	_, err = io.Copy(out, resp.Body)
	check(err)
	return clipPath
}

type flushWriter struct {
	f http.Flusher
	w io.Writer
}

func (fw *flushWriter) Write(p []byte) (n int, err error) {
	n, err = fw.w.Write(p)
	if fw.f != nil {
		fw.f.Flush()
	}
	return
}

/* container for the request variables */
type RequestVars struct {
	mission int
	channels []int
	format string
	start int
	duration int
}

/* local paths to audio files for all channels belonging to particular time slice */
type TimeSlice struct {
	start int
	end int
	location []string
}

type DatabaseVars struct {
	DB_HOST string `json:"DB_HOST"`
	DB_PORT int `json:"DB_PORT"`
	DB_USER string `json:"DB_USER"`
	DB_PASSWORD string `json:"DB_PASSWORD"`
	DB_NAME string `json:"DB_NAME"`
}

func parseParameters(r *http.Request) *RequestVars {
	r.ParseForm()

	var rv *RequestVars

	tempMission, err := strconv.Atoi(r.Form["mission"][0])
	check(err)
	rv.mission = tempMission

	var tempChannels []int
	for n := range r.Form["channel"] {
		ch, err := strconv.Atoi(r.Form["channel"][n])
		check(err)
		tempChannels = append(tempChannels, ch)
	}
	rv.channels = tempChannels

	tempFormat := r.Form["format"][0]
	rv.format = tempFormat

	tempStart, err := strconv.Atoi(r.Form["t"][0])
	check(err)
	rv.start = tempStart

	tempDuration, err := strconv.Atoi(r.Form["len"][0])
	check(err)
	rv.duration = tempDuration

	return rv
}

func getLocations(rv *RequestVars) []TimeSlice {

	var slices []TimeSlice

	dbjson, err := ioutil.ReadFile("./config.json")
	check(err)
	var dbvars []DatabaseVars
	err = json.Unmarshal(dbjson, &dbvars)
	check(err)
	dbcreds := dbvars[0]
	dbinfo := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", dbcreds.DB_HOST, dbcreds.DB_PORT, dbcreds.DB_USER, dbcreds.DB_PASSWORD, dbcreds.DB_NAME)
	db, err := sql.Open("postgres", dbinfo)
	check(err)
	defer db.Close()

	stmt, err := db.Prepare("CREATE TABLE chunks_a AS SELECT * FROM chunks_a WHERE met_end > $1")
	check(err)
	_, err = stmt.Exec(rv.start)
	check(err)

	stmt, err = db.Prepare("CREATE TABLE chunks_b AS SELECT * FROM chunks_b WHERE met_start < $1")
	check(err)
	reqEnd := rv.start + rv.duration
	_, err = stmt.Exec(reqEnd)
	check(err)

	rows, err := db.Query("SELECT DISTINCT met_start, met_end FROM chunks_b ORDER BY met_start")

	for rows.Next() {
		var metstart int
		var metend int
		var loc []string
		err = rows.Scan(&metstart, &metend)
		slice := TimeSlice{start: metstart, end: metend, location: loc}
		slices = append(slices, slice)
	}

	for ch := range rv.channels {
		rows, err := db.Query("SELECT url, met_start, met_end from chunks_b cb WHERE cb.channel = $1", rv.channels[ch])
		check(err)

		for rows.Next() {
			var url string
			var startTime int
			var endTime int
			err = rows.Scan(&url, &startTime, &endTime)
			check(err)

			filename := fmt.Sprintf("mission%dchannel%d%d%d", rv.mission, rv.channels[ch], rv.start, rv.duration)
			loc := downloadFromS3AndSave(url, filename)

			for ts := range slices {
				if (startTime == slices[ts].start && endTime == slices[ts].end) {
					slices[ts].location = append(slices[ts].location, loc)
				}
			}
		}
	}

	_, err = db.Query("DROP TABLE chunks_a; DROP TABLE chunks_b;")
	check(err)
	return slices
}

func streamHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-type", "audio/mpeg")

	/* PARRRAMETERS */
	rv := parseParameters(r)

	/* DEEBEE */
	timeslices := getLocations(rv)

	sox, err := exec.LookPath("sox")
	check(err)
	fmt.Println("using sox " + sox)
	ffmpeg, err := exec.LookPath("ffmpeg")
	check(err)
	fmt.Println("using ffmpeg " + ffmpeg)

	for s := range timeslices {

		chunkFiles := timeslices[s].location

		soxArgs := []string{"-t", "wav", "-m"}
		soxArgs = append(soxArgs, chunkFiles...)
		soxArgs = append(soxArgs, "-p")
		soxCommand := exec.Command(sox, soxArgs...)

		// convert the thing
		var ffmpegArgs []string
		if rv.format == AAC || rv.format == M4A {
			ffmpegArgs = []string{"-i", "-", "-c:a", "libfdk_aac", "-b:a", "256k", "-f", M4A, "pipe:"}
			// works, but gotta compile ffmpeg on server with special options
		} else if rv.format == OGG {
			ffmpegArgs = []string{"-i", "-", "-c:a", "libvorbis", "-qscale:a", "6", "-f", OGG, "pipe:"}
		} else {
			fmt.Println("unsupported output format requested. break some rools.")
			ffmpegArgs = []string{"-i", "-", "-f", "mp3", "-ab", "256k", "pipe:"}
		}
		ffmpegCommand := exec.Command(ffmpeg, ffmpegArgs...)

		fw := flushWriter{w: w}
		if f, ok := w.(http.Flusher); ok {
			fw.f = f
		}

		ffmpegCommand.Stdin, _ = soxCommand.StdoutPipe()
		ffmpegCommand.Stdout = &fw
		ffmpegCommand.Stderr = os.Stdout

		ffmpegCommand.Start()
		soxCommand.Run()
		ffmpegCommand.Wait()

	}

	fmt.Println("done")

}

func main() {
	makeDir(workingDir)
	makeDir(clipDir)
	http.HandleFunc("/stream", streamHandler)
	ServerPort := "5000" // default port
	if len(os.Getenv("PORT")) > 0 {
		ServerPort = os.Getenv("PORT")
	}
	fmt.Println("Starting server on " + ServerPort)
	http.ListenAndServe(":"+ServerPort, nil)
}
<commit_msg>unmarshalling db creds more better, fixing queries<commit_after>package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"path"
	"strconv"
	"encoding/json"
	"database/sql"
	_ "github.com/lib/pq"
)

var workingDir string = path.Join(os.TempDir(), "apollo-audio")
var clipDir string = path.Join(workingDir, "clips")
var AAC string = "aac"
var M4A string = "m4a"
var OGG string = "ogg"

func check(e error) {
	if e != nil {
		panic(e)
	}
}

func exists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return true, err
}

func makeDir(dir string) {
	dirExists, err := exists(dir)
	check(err)
	if !dirExists {
		err := os.Mkdir(dir, 0777)
		check(err)
	}
}

func downloadFromS3AndSave(url string, filename string) string {
	clipPath := path.Join(clipDir, filename)
	if _, err := os.Stat(clipPath); err == nil {
		fmt.Println("file exists; skipping")
		return clipPath
	}
	fmt.Println(clipPath)
	fmt.Println("debug")
	out, err := os.Create(clipPath)
	check(err)
	defer out.Close()
	resp, err := http.Get(url)
	check(err)
	defer resp.Body.Close()
	_, err = io.Copy(out, resp.Body)
	check(err)
	return clipPath
}

type flushWriter struct {
	f http.Flusher
	w io.Writer
}

func (fw *flushWriter) Write(p []byte) (n int, err error) {
	n, err = fw.w.Write(p)
	if fw.f != nil {
		fw.f.Flush()
	}
	return
}

/* container for the request variables */
type RequestVars struct {
	mission int
	channels []int
	format string
	start int
	duration int
}

/* local paths to audio files for all channels belonging to particular time slice */
type TimeSlice struct {
	start int
	end int
	location []string
}

type DatabaseVars struct {
	DB_HOST string `json:"DB_HOST"`
	DB_PORT int `json:"DB_PORT"`
	DB_USER string `json:"DB_USER"`
	DB_PASSWORD string `json:"DB_PASSWORD"`
	DB_NAME string `json:"DB_NAME"`
}

func parseParameters(r *http.Request) RequestVars {
	r.ParseForm()

	var rv RequestVars

	tempMission, err := strconv.Atoi(r.Form["mission"][0])
	check(err)
	rv.mission = tempMission

	var tempChannels []int
	for n := range r.Form["channel"] {
		ch, err := strconv.Atoi(r.Form["channel"][n])
		check(err)
		tempChannels = append(tempChannels, ch)
	}
	rv.channels = tempChannels

	tempFormat := r.Form["format"][0]
	rv.format = tempFormat

	tempStart, err := strconv.Atoi(r.Form["t"][0])
	check(err)
	rv.start = tempStart

	tempDuration, err := strconv.Atoi(r.Form["len"][0])
	check(err)
	rv.duration = tempDuration

	return rv
}

func getLocations(rv RequestVars) []TimeSlice {

	var slices []TimeSlice

	dbjson, err := ioutil.ReadFile("./config.json")
	check(err)

	var dbvars DatabaseVars
	err = json.Unmarshal(dbjson, &dbvars)
	check(err)

	dbcreds := dbvars
	dbinfo := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", dbcreds.DB_HOST, dbcreds.DB_PORT, dbcreds.DB_USER, dbcreds.DB_PASSWORD, dbcreds.DB_NAME)
	db, err := sql.Open("postgres", dbinfo)
	check(err)
	defer db.Close()

	stmt, err := db.Prepare("CREATE TABLE chunks_a AS SELECT * FROM channel_chunks WHERE met_end > $1")
	check(err)
	_, err = stmt.Exec(rv.start)
	check(err)

	stmt, err = db.Prepare("CREATE TABLE chunks_b AS SELECT * FROM chunks_a WHERE met_start < $1")
	check(err)
	reqEnd := rv.start + rv.duration
	_, err = stmt.Exec(reqEnd)
	check(err)

	_, err = db.Query("DROP TABLE chunks_a")
	check(err)

	rows, err := db.Query("SELECT DISTINCT met_start, met_end FROM chunks_b ORDER BY met_start")

	for rows.Next() {
		var metstart int
		var metend int
		var loc []string
		err = rows.Scan(&metstart, &metend)
		slice := TimeSlice{start: metstart, end: metend, location: loc}
		slices = append(slices, slice)
	}

	for ch := range rv.channels {
		rows, err := db.Query("SELECT url, met_start, met_end from chunks_b cb WHERE cb.channel = $1", rv.channels[ch])
		check(err)

		for rows.Next() {
			var url string
			var startTime int
			var endTime int
			err = rows.Scan(&url, &startTime, &endTime)
			check(err)

			filename := fmt.Sprintf("mission%dchannel%d%d%d", rv.mission, rv.channels[ch], rv.start, rv.duration)
			loc := downloadFromS3AndSave(url, filename)

			for ts := range slices {
				if (startTime == slices[ts].start && endTime == slices[ts].end) {
					slices[ts].location = append(slices[ts].location, loc)
				}
			}
		}
	}

	_, err = db.Query("DROP TABLE chunks_b;")
	check(err)
	return slices
}

func streamHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-type", "audio/mpeg")

	/* PARRRAMETERS */
	rv := parseParameters(r)

	/* DEEBEE */
	timeslices := getLocations(rv)

	sox, err := exec.LookPath("sox")
	check(err)
	fmt.Println("using sox " + sox)
	ffmpeg, err := exec.LookPath("ffmpeg")
	check(err)
	fmt.Println("using ffmpeg " + ffmpeg)

	for s := range timeslices {

		chunkFiles := timeslices[s].location

		soxArgs := []string{"-t", "wav", "-m"}
		soxArgs = append(soxArgs, chunkFiles...)
		soxArgs = append(soxArgs, "-p")
		soxCommand := exec.Command(sox, soxArgs...)

		// convert the thing
		var ffmpegArgs []string
		if rv.format == AAC || rv.format == M4A {
			ffmpegArgs = []string{"-i", "-", "-c:a", "libfdk_aac", "-b:a", "256k", "-f", M4A, "pipe:"}
			// works, but gotta compile ffmpeg on server with special options
		} else if rv.format == OGG {
			ffmpegArgs = []string{"-i", "-", "-c:a", "libvorbis", "-qscale:a", "6", "-f", OGG, "pipe:"}
		} else {
			fmt.Println("unsupported output format requested. break some rools.")
			ffmpegArgs = []string{"-i", "-", "-f", "mp3", "-ab", "256k", "pipe:"}
		}
		ffmpegCommand := exec.Command(ffmpeg, ffmpegArgs...)

		fw := flushWriter{w: w}
		if f, ok := w.(http.Flusher); ok {
			fw.f = f
		}

		ffmpegCommand.Stdin, _ = soxCommand.StdoutPipe()
		ffmpegCommand.Stdout = &fw
		ffmpegCommand.Stderr = os.Stdout

		ffmpegCommand.Start()
		soxCommand.Run()
		ffmpegCommand.Wait()

	}

	fmt.Println("done")

}

func main() {
	makeDir(workingDir)
	makeDir(clipDir)
	http.HandleFunc("/stream", streamHandler)
	ServerPort := "5000" // default port
	if len(os.Getenv("PORT")) > 0 {
		ServerPort = os.Getenv("PORT")
	}
	fmt.Println("Starting server on " + ServerPort)
	http.ListenAndServe(":"+ServerPort, nil)
}
<|endoftext|>


<commit_before>// Copyright (c) 2014,2015,2016 Docker, Inc.
// Copyright (c) 2017 Intel Corporation
//
// Licensed 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.

package main

import (
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/Sirupsen/logrus"
	vc "github.com/containers/virtcontainers"
	specs "github.com/opencontainers/runtime-spec/specs-go"
	"github.com/urfave/cli"
)

// name holds the name of this program
const (
	name    = "cc-runtime"
	project = "Intel® Clear Containers"
)

// specConfig is the name of the file holding the containers configuration
const specConfig = "config.json"

const usage = project + ` runtime

cc-runtime is a command line program for running applications packaged
according to the Open Container Initiative (OCI).`

const notes = `
NOTES:

- Commands starting "cc-" and options starting "--cc-" are ` + project + ` extensions.

`

var ccLog = logrus.New()

// concrete virtcontainer implementation
var virtcontainersImpl = &vc.VCImpl{}

// vci is used to access a particular virtcontainers implementation.
// Normally, it refers to the official package, but is re-assigned in
// the tests to allow virtcontainers to be mocked.
var vci vc.VC = virtcontainersImpl

// defaultOutputFile is the default output file to write the gathered
// information to.
var defaultOutputFile = os.Stdout

func beforeSubcommands(context *cli.Context) error {
	if userWantsUsage(context) || (context.NArg() == 1 && (context.Args()[0] == "cc-check")) {
		// No setup required if the user just
		// wants to see the usage statement or are
		// running a command that does not manipulate
		// containers.
		return nil
	}

	if context.GlobalBool("debug") {
		ccLog.Level = logrus.DebugLevel
	}
	if path := context.GlobalString("log"); path != "" {
		f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND|os.O_SYNC, 0640)
		if err != nil {
			return err
		}
		ccLog.Out = f
	}

	switch context.GlobalString("log-format") {
	case "text":
		// retain logrus's default.
	case "json":
		ccLog.Formatter = new(logrus.JSONFormatter)
	default:
		return fmt.Errorf("unknown log-format %q", context.GlobalString("log-format"))
	}

	// Set virtcontainers logger.
	vci.SetLogger(ccLog)

	ignoreLogging := false
	if context.NArg() == 1 && context.Args()[0] == "cc-env" {
		// "cc-env" should simply report the logging setup
		ignoreLogging = true
	}

	configFile, logfilePath, runtimeConfig, err := loadConfiguration(context.GlobalString("cc-config"), ignoreLogging)
	if err != nil {
		fatal(err)
	}

	ccLog.Infof("%v (version %v, commit %v) called as: %v", name, version, commit, context.Args())
	ccLog.Infof("Using configuration file %q", configFile)

	// make the data accessible to the sub-commands.
	context.App.Metadata = map[string]interface{}{
		"runtimeConfig": runtimeConfig,
		"configFile":    configFile,
		"logfilePath":   logfilePath,
	}

	return nil
}

func main() {
	app := cli.NewApp()
	app.Name = name
	app.Usage = usage

	cli.AppHelpTemplate = fmt.Sprintf(`%s%s`, cli.AppHelpTemplate, notes)

	v := make([]string, 0, 3)
	if version != "" {
		v = append(v, name+"  : "+version)
	}
	if commit != "" {
		v = append(v, "   commit   : "+commit)
	}
	v = append(v, "   OCI specs: "+specs.Version)
	app.Version = strings.Join(v, "\n")

	// Override the default function to display version details to
	// ensure the "--version" option and "version" command are identical.
	cli.VersionPrinter = func(c *cli.Context) {
		fmt.Println(c.App.Version)
	}

	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "cc-config",
			Usage: project + " config file path",
		},
		cli.BoolFlag{
			Name:  "debug",
			Usage: "enable debug output for logging",
		},
		cli.StringFlag{
			Name:  "log",
			Value: "/dev/null",
			Usage: "set the log file path where internal debug information is written",
		},
		cli.StringFlag{
			Name:  "log-format",
			Value: "text",
			Usage: "set the format used by logs ('text' (default), or 'json')",
		},
		cli.StringFlag{
			Name:  "root",
			Value: defaultRootDirectory,
			Usage: "root directory for storage of container state (this should be located in tmpfs)",
		},
	}

	app.Commands = []cli.Command{
		checkCLICommand,
		envCLICommand,
		createCLICommand,
		deleteCLICommand,
		execCLICommand,
		killCLICommand,
		listCLICommand,
		runCLICommand,
		pauseCLICommand,
		resumeCLICommand,
		startCLICommand,
		stateCLICommand,
		versionCLICommand,
	}

	app.Before = beforeSubcommands
	// If the command returns an error, cli takes upon itself to print
	// the error on cli.ErrWriter and exit.
	// Use our own writer here to ensure the log gets sent to the right
	// location.
	cli.ErrWriter = &fatalWriter{cli.ErrWriter}

	if err := app.Run(os.Args); err != nil {
		fatal(err)
	}
}

// userWantsUsage determines if the user only wishes to see the usage
// statement.
func userWantsUsage(context *cli.Context) bool {
	if context.NArg() == 0 {
		return true
	}

	if context.NArg() == 1 && (context.Args()[0] == "help" || context.Args()[0] == "version") {
		return true
	}

	if context.NArg() >= 2 && (context.Args()[1] == "-h" || context.Args()[1] == "--help") {
		return true
	}

	return false
}

// fatal prints the error's details exits the program.
func fatal(err error) {
	ccLog.Error(err)
	fmt.Fprintln(os.Stderr, err)
	exit(1)
}

type fatalWriter struct {
	cliErrWriter io.Writer
}

func (f *fatalWriter) Write(p []byte) (n int, err error) {
	ccLog.Error(string(p))
	return f.cliErrWriter.Write(p)
}
<commit_msg>main: Fix comments.<commit_after>// Copyright (c) 2014,2015,2016 Docker, Inc.
// Copyright (c) 2017 Intel Corporation
//
// Licensed 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.

package main

import (
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/Sirupsen/logrus"
	vc "github.com/containers/virtcontainers"
	specs "github.com/opencontainers/runtime-spec/specs-go"
	"github.com/urfave/cli"
)

const (
	// name holds the name of this program
	name    = "cc-runtime"
	project = "Intel® Clear Containers"
)

// specConfig is the name of the file holding the containers configuration
const specConfig = "config.json"

const usage = project + ` runtime

cc-runtime is a command line program for running applications packaged
according to the Open Container Initiative (OCI).`

const notes = `
NOTES:

- Commands starting "cc-" and options starting "--cc-" are ` + project + ` extensions.

`

var ccLog = logrus.New()

// concrete virtcontainer implementation
var virtcontainersImpl = &vc.VCImpl{}

// vci is used to access a particular virtcontainers implementation.
// Normally, it refers to the official package, but is re-assigned in
// the tests to allow virtcontainers to be mocked.
var vci vc.VC = virtcontainersImpl

// defaultOutputFile is the default output file to write the gathered
// information to.
var defaultOutputFile = os.Stdout

func beforeSubcommands(context *cli.Context) error {
	if userWantsUsage(context) || (context.NArg() == 1 && (context.Args()[0] == "cc-check")) {
		// No setup required if the user just
		// wants to see the usage statement or are
		// running a command that does not manipulate
		// containers.
		return nil
	}

	if context.GlobalBool("debug") {
		ccLog.Level = logrus.DebugLevel
	}
	if path := context.GlobalString("log"); path != "" {
		f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND|os.O_SYNC, 0640)
		if err != nil {
			return err
		}
		ccLog.Out = f
	}

	switch context.GlobalString("log-format") {
	case "text":
		// retain logrus's default.
	case "json":
		ccLog.Formatter = new(logrus.JSONFormatter)
	default:
		return fmt.Errorf("unknown log-format %q", context.GlobalString("log-format"))
	}

	// Set virtcontainers logger.
	vci.SetLogger(ccLog)

	ignoreLogging := false
	if context.NArg() == 1 && context.Args()[0] == "cc-env" {
		// "cc-env" should simply report the logging setup
		ignoreLogging = true
	}

	configFile, logfilePath, runtimeConfig, err := loadConfiguration(context.GlobalString("cc-config"), ignoreLogging)
	if err != nil {
		fatal(err)
	}

	ccLog.Infof("%v (version %v, commit %v) called as: %v", name, version, commit, context.Args())
	ccLog.Infof("Using configuration file %q", configFile)

	// make the data accessible to the sub-commands.
	context.App.Metadata = map[string]interface{}{
		"runtimeConfig": runtimeConfig,
		"configFile":    configFile,
		"logfilePath":   logfilePath,
	}

	return nil
}

func main() {
	app := cli.NewApp()
	app.Name = name
	app.Usage = usage

	cli.AppHelpTemplate = fmt.Sprintf(`%s%s`, cli.AppHelpTemplate, notes)

	v := make([]string, 0, 3)
	if version != "" {
		v = append(v, name+"  : "+version)
	}
	if commit != "" {
		v = append(v, "   commit   : "+commit)
	}
	v = append(v, "   OCI specs: "+specs.Version)
	app.Version = strings.Join(v, "\n")

	// Override the default function to display version details to
	// ensure the "--version" option and "version" command are identical.
	cli.VersionPrinter = func(c *cli.Context) {
		fmt.Println(c.App.Version)
	}

	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "cc-config",
			Usage: project + " config file path",
		},
		cli.BoolFlag{
			Name:  "debug",
			Usage: "enable debug output for logging",
		},
		cli.StringFlag{
			Name:  "log",
			Value: "/dev/null",
			Usage: "set the log file path where internal debug information is written",
		},
		cli.StringFlag{
			Name:  "log-format",
			Value: "text",
			Usage: "set the format used by logs ('text' (default), or 'json')",
		},
		cli.StringFlag{
			Name:  "root",
			Value: defaultRootDirectory,
			Usage: "root directory for storage of container state (this should be located in tmpfs)",
		},
	}

	app.Commands = []cli.Command{
		checkCLICommand,
		envCLICommand,
		createCLICommand,
		deleteCLICommand,
		execCLICommand,
		killCLICommand,
		listCLICommand,
		runCLICommand,
		pauseCLICommand,
		resumeCLICommand,
		startCLICommand,
		stateCLICommand,
		versionCLICommand,
	}

	app.Before = beforeSubcommands
	// If the command returns an error, cli takes upon itself to print
	// the error on cli.ErrWriter and exit.
	// Use our own writer here to ensure the log gets sent to the right
	// location.
	cli.ErrWriter = &fatalWriter{cli.ErrWriter}

	if err := app.Run(os.Args); err != nil {
		fatal(err)
	}
}

// userWantsUsage determines if the user only wishes to see the usage
// statement.
func userWantsUsage(context *cli.Context) bool {
	if context.NArg() == 0 {
		return true
	}

	if context.NArg() == 1 && (context.Args()[0] == "help" || context.Args()[0] == "version") {
		return true
	}

	if context.NArg() >= 2 && (context.Args()[1] == "-h" || context.Args()[1] == "--help") {
		return true
	}

	return false
}

// fatal prints the error's details exits the program.
func fatal(err error) {
	ccLog.Error(err)
	fmt.Fprintln(os.Stderr, err)
	exit(1)
}

type fatalWriter struct {
	cliErrWriter io.Writer
}

func (f *fatalWriter) Write(p []byte) (n int, err error) {
	// Ensure error is logged before displaying to the user
	ccLog.Error(string(p))
	return f.cliErrWriter.Write(p)
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/

package main

import (
	"crypto/dsa"
	"crypto/rand"
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"
	"strings"
)

const (
	MOCKMYID_API_ROOT           = "/"
	MOCKMYID_API_LISTEN_ADDRESS = "127.0.0.1"
	MOCKMYID_API_LISTEN_PORT    = 8080
)

type LoginResponse struct {
	Email     string `json:"email"`
	Audience  string `json:"audience"`
	Assertion string `json:"assertion"`
}

func generateRandomKey() (*dsa.PrivateKey, error) {
	params := new(dsa.Parameters)
	if err := dsa.GenerateParameters(params, rand.Reader, dsa.L1024N160); err != nil {
		return nil, err
	}
	priv := new(dsa.PrivateKey)
	priv.PublicKey.Parameters = *params
	if err := dsa.GenerateKey(priv, rand.Reader); err != nil {
		return nil, err
	}
	return priv, nil
}

func handleLogin(w http.ResponseWriter, r *http.Request) {
	query := r.URL.Query()
	email := query["email"][0]
	audience := query["audience"][0]
	uniqueKey := query["uniqueKey"]

	var clientKey *dsa.PrivateKey
	if len(uniqueKey) != 0 {
		key, err := generateRandomKey()
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		clientKey = key
	} else {
		clientKey = globalRandomKey
	}

	assertion, err := CreateShortLivedMockMyIDAssertion(*clientKey, email, audience)

	loginResponse := &LoginResponse{
		Email:     email,
		Audience:  audience,
		Assertion: assertion,
	}

	encodedLoginResponse, err := json.Marshal(loginResponse)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	w.Write(encodedLoginResponse)
}

var globalRandomKey *dsa.PrivateKey

func main() {
	address := flag.String("address", MOCKMYID_API_LISTEN_ADDRESS, "address to listen on")
	port := flag.Int("port", MOCKMYID_API_LISTEN_PORT, "port to listen on")
	root := flag.String("root", MOCKMYID_API_ROOT, "application root (path prefix)")
	flag.Parse()

	prefix := *root
	if !strings.HasSuffix(prefix, "/") {
		prefix = prefix + "/"
	}

	log.Print("Generating client DSA key")
	key, err := generateRandomKey()
	if err != nil {
		panic("Cannot generate random key")
	}
	globalRandomKey = key

	http.HandleFunc(prefix+"/login", handleLogin)
	addr := fmt.Sprintf("%s:%d", *address, *port)
	log.Printf("Starting mockmyid-api server on http://%s%s", addr, prefix)
	err = http.ListenAndServe(addr, nil)
	if err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Quick fix for web app root handling<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/

package main

import (
	"crypto/dsa"
	"crypto/rand"
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"
)

const (
	MOCKMYID_API_ROOT           = "/"
	MOCKMYID_API_LISTEN_ADDRESS = "127.0.0.1"
	MOCKMYID_API_LISTEN_PORT    = 8080
)

type LoginResponse struct {
	Email     string `json:"email"`
	Audience  string `json:"audience"`
	Assertion string `json:"assertion"`
}

func generateRandomKey() (*dsa.PrivateKey, error) {
	params := new(dsa.Parameters)
	if err := dsa.GenerateParameters(params, rand.Reader, dsa.L1024N160); err != nil {
		return nil, err
	}
	priv := new(dsa.PrivateKey)
	priv.PublicKey.Parameters = *params
	if err := dsa.GenerateKey(priv, rand.Reader); err != nil {
		return nil, err
	}
	return priv, nil
}

func handleLogin(w http.ResponseWriter, r *http.Request) {
	query := r.URL.Query()
	email := query["email"][0]
	audience := query["audience"][0]
	uniqueKey := query["uniqueKey"]

	var clientKey *dsa.PrivateKey
	if len(uniqueKey) != 0 {
		key, err := generateRandomKey()
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		clientKey = key
	} else {
		clientKey = globalRandomKey
	}

	assertion, err := CreateShortLivedMockMyIDAssertion(*clientKey, email, audience)

	loginResponse := &LoginResponse{
		Email:     email,
		Audience:  audience,
		Assertion: assertion,
	}

	encodedLoginResponse, err := json.Marshal(loginResponse)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	w.Write(encodedLoginResponse)
}

var globalRandomKey *dsa.PrivateKey

func main() {
	address := flag.String("address", MOCKMYID_API_LISTEN_ADDRESS, "address to listen on")
	port := flag.Int("port", MOCKMYID_API_LISTEN_PORT, "port to listen on")
	root := flag.String("root", MOCKMYID_API_ROOT, "application root (path prefix)")
	flag.Parse()

	prefix := *root
	if prefix == "/" {
		prefix = ""
	}

	log.Print("Generating client DSA key")
	key, err := generateRandomKey()
	if err != nil {
		panic("Cannot generate random key")
	}
	globalRandomKey = key

	http.HandleFunc(prefix+"/login", handleLogin)
	addr := fmt.Sprintf("%s:%d", *address, *port)
	log.Printf("Starting mockmyid-api server on http://%s%s", addr, prefix)
	err = http.ListenAndServe(addr, nil)
	if err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"regexp"
	"strings"
	"sync"
	"time"
)

var (
	keyFile  = flag.String("key", "", "Key file")
	certFile = flag.String("cert", "", "Certificate file")
	dbDir    = flag.String("db", "", "Database directory")
	port     = flag.Int("port", 8443, "Listen port")
	tpl      *template.Template
)

var funcs = map[string]interface{}{
	"commatize": commatize,
	"number":    number,
}

func main() {
	flag.Parse()
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)

	fd, err := os.Open("static/index.html")
	if err != nil {
		log.Fatal(err)
	}
	bs, err := ioutil.ReadAll(fd)
	if err != nil {
		log.Fatal(err)
	}
	fd.Close()
	tpl = template.Must(template.New("index.html").Funcs(funcs).Parse(string(bs)))

	http.HandleFunc("/", rootHandler)
	http.HandleFunc("/newdata", newDataHandler)
	http.HandleFunc("/report", reportHandler)
	http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))

	err = http.ListenAndServeTLS(fmt.Sprintf(":%d", *port), *certFile, *keyFile, nil)
	if err != nil {
		log.Fatal(err)
	}
}

func rootHandler(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path == "/" || r.URL.Path == "/index.html" {
		k := timestamp()
		rep := getReport(k)

		w.Header().Set("Content-Type", "text/html; charset=utf-8")
		err := tpl.Execute(w, rep)
		if err != nil {
			log.Println(err)
		}
	} else {
		http.Error(w, "Not found", 404)
	}
}

func reportHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	k := timestamp()
	rep := getReport(k)
	json.NewEncoder(w).Encode(rep)
}

func newDataHandler(w http.ResponseWriter, r *http.Request) {
	today := time.Now().Format("20060102")
	dir := filepath.Join(*dbDir, today)
	ensureDir(dir, 0700)

	var m map[string]interface{}
	lr := &io.LimitedReader{R: r.Body, N: 10240}
	err := json.NewDecoder(lr).Decode(&m)

	if err != nil {
		log.Println(err)
		http.Error(w, err.Error(), 500)
		return
	}

	id, ok := m["uniqueID"]
	if ok {
		idStr, ok := id.(string)
		if !ok {
			if err != nil {
				log.Println("No ID")
				http.Error(w, "No ID", 500)
				return
			}
		}

		f, err := os.Create(path.Join(dir, idStr+".json"))
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), 500)
			return
		}
		json.NewEncoder(f).Encode(m)
		f.Close()
	} else {
		log.Println("No ID")
		http.Error(w, "No ID", 500)
		return
	}
}

type report struct {
	UniqueID       string
	Version        string
	Platform       string
	NumRepos       int
	NumNodes       int
	TotFiles       int
	RepoMaxFiles   int
	TotMiB         int
	RepoMaxMiB     int
	MemoryUsageMiB int
	SHA256Perf     float64
	MemorySize     int
}

func fileList() ([]string, error) {
	files := make(map[string]string)
	t0 := time.Now().Add(-24 * time.Hour).Format("20060102")
	t1 := time.Now().Format("20060102")

	dir := filepath.Join(*dbDir, t0)
	gr, err := filepath.Glob(filepath.Join(dir, "*.json"))
	if err != nil {
		return nil, err
	}
	for _, f := range gr {
		bn := filepath.Base(f)
		files[bn] = f
	}

	dir = filepath.Join(*dbDir, t1)
	gr, err = filepath.Glob(filepath.Join(dir, "*.json"))
	if err != nil {
		return nil, err
	}
	for _, f := range gr {
		bn := filepath.Base(f)
		files[bn] = f
	}

	l := make([]string, 0, len(files))
	for _, f := range files {
		si, err := os.Stat(f)
		if err != nil {
			continue
		}
		if time.Since(si.ModTime()) < 24*time.Hour {
			l = append(l, f)
		}
	}

	return l, nil
}

type category struct {
	Values [4]float64
	Key    string
	Descr  string
	Unit   string
	Binary bool
}

var reportCache map[string]interface{}
var reportMutex sync.Mutex

func getReport(key string) map[string]interface{} {
	reportMutex.Lock()
	defer reportMutex.Unlock()

	if k := reportCache["key"]; k == key {
		return reportCache
	}

	files, err := fileList()
	if err != nil {
		return nil
	}

	nodes := 0
	var versions []string
	var platforms []string
	var oses []string
	var numRepos []int
	var numNodes []int
	var totFiles []int
	var maxFiles []int
	var totMiB []int
	var maxMiB []int
	var memoryUsage []int
	var sha256Perf []float64
	var memorySize []int

	for _, fn := range files {
		f, err := os.Open(fn)
		if err != nil {
			continue
		}

		var rep report
		err = json.NewDecoder(f).Decode(&rep)
		if err != nil {
			continue
		}
		f.Close()

		nodes++
		versions = append(versions, transformVersion(rep.Version))
		platforms = append(platforms, rep.Platform)
		ps := strings.Split(rep.Platform, "-")
		oses = append(oses, ps[0])
		if rep.NumRepos > 0 {
			numRepos = append(numRepos, rep.NumRepos)
		}
		if rep.NumNodes > 0 {
			numNodes = append(numNodes, rep.NumNodes)
		}
		if rep.TotFiles > 0 {
			totFiles = append(totFiles, rep.TotFiles)
		}
		if rep.RepoMaxFiles > 0 {
			maxFiles = append(maxFiles, rep.RepoMaxFiles)
		}
		if rep.TotMiB > 0 {
			totMiB = append(totMiB, rep.TotMiB*(1<<20))
		}
		if rep.RepoMaxMiB > 0 {
			maxMiB = append(maxMiB, rep.RepoMaxMiB*(1<<20))
		}
		if rep.MemoryUsageMiB > 0 {
			memoryUsage = append(memoryUsage, rep.MemoryUsageMiB*(1<<20))
		}
		if rep.SHA256Perf > 0 {
			sha256Perf = append(sha256Perf, rep.SHA256Perf*(1<<20))
		}
		if rep.MemorySize > 0 {
			memorySize = append(memorySize, rep.MemorySize*(1<<20))
		}
	}

	var categories []category
	categories = append(categories, category{
		Values: statsForInts(totFiles),
		Descr:  "Files Managed per Node",
	})

	categories = append(categories, category{
		Values: statsForInts(maxFiles),
		Descr:  "Files in Largest Repo",
	})

	categories = append(categories, category{
		Values: statsForInts(totMiB),
		Descr:  "Data Managed per Node",
		Unit:   "B",
		Binary: true,
	})

	categories = append(categories, category{
		Values: statsForInts(maxMiB),
		Descr:  "Data in Largest Repo",
		Unit:   "B",
		Binary: true,
	})

	categories = append(categories, category{
		Values: statsForInts(numNodes),
		Descr:  "Number of Nodes in Cluster",
	})

	categories = append(categories, category{
		Values: statsForInts(numRepos),
		Descr:  "Number of Repositories Configured",
	})

	categories = append(categories, category{
		Values: statsForInts(memoryUsage),
		Descr:  "Memory Usage",
		Unit:   "B",
		Binary: true,
	})

	categories = append(categories, category{
		Values: statsForInts(memorySize),
		Descr:  "System Memory",
		Unit:   "B",
		Binary: true,
	})

	categories = append(categories, category{
		Values: statsForFloats(sha256Perf),
		Descr:  "SHA-256 Hashing Performance",
		Unit:   "B/s",
		Binary: true,
	})

	r := make(map[string]interface{})
	r["key"] = key
	r["nodes"] = nodes
	r["categories"] = categories
	r["versions"] = analyticsFor(versions)
	r["platforms"] = analyticsFor(platforms)
	r["os"] = analyticsFor(oses)

	reportCache = r

	return r
}

func ensureDir(dir string, mode int) {
	fi, err := os.Stat(dir)
	if os.IsNotExist(err) {
		os.MkdirAll(dir, 0700)
	} else if mode >= 0 && err == nil && int(fi.Mode()&0777) != mode {
		os.Chmod(dir, os.FileMode(mode))
	}
}

var vRe = regexp.MustCompile(`^(v\d+\.\d+\.\d+(?:-[a-z]\w+)?)[+\.-]`)

// transformVersion returns a version number formatted correctly, with all
// development versions aggregated into one.
func transformVersion(v string) string {
	if v == "unknown-dev" {
		return v
	}
	if !strings.HasPrefix(v, "v") {
		v = "v" + v
	}
	if m := vRe.FindStringSubmatch(v); len(m) > 0 {
		return m[1] + " (+dev)"
	}
	return v
}

// timestamp returns a time stamp for the current hour, to be used as a cache key
func timestamp() string {
	return time.Now().Format("20060102T15")
}
<commit_msg>Set read and write timeouts on HTTPS requests<commit_after>package main

import (
	"crypto/tls"
	"encoding/json"
	"flag"
	"fmt"
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"regexp"
	"strings"
	"sync"
	"time"
)

var (
	keyFile  = flag.String("key", "", "Key file")
	certFile = flag.String("cert", "", "Certificate file")
	dbDir    = flag.String("db", "", "Database directory")
	port     = flag.Int("port", 8443, "Listen port")
	tpl      *template.Template
)

var funcs = map[string]interface{}{
	"commatize": commatize,
	"number":    number,
}

func main() {
	flag.Parse()
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)

	fd, err := os.Open("static/index.html")
	if err != nil {
		log.Fatal(err)
	}
	bs, err := ioutil.ReadAll(fd)
	if err != nil {
		log.Fatal(err)
	}
	fd.Close()
	tpl = template.Must(template.New("index.html").Funcs(funcs).Parse(string(bs)))

	http.HandleFunc("/", rootHandler)
	http.HandleFunc("/newdata", newDataHandler)
	http.HandleFunc("/report", reportHandler)
	http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))

	cert, err := tls.LoadX509KeyPair(*certFile, *keyFile)
	if err != nil {
		log.Fatal(err)
	}

	cfg := &tls.Config{
		Certificates:           []tls.Certificate{cert},
		SessionTicketsDisabled: true,
	}

	listener, err := tls.Listen("tcp", fmt.Sprintf(":%d", *port), cfg)
	if err != nil {
		log.Fatal(err)
	}

	srv := http.Server{
		ReadTimeout:  5 * time.Second,
		WriteTimeout: 5 * time.Second,
	}

	err = srv.Serve(listener)
	if err != nil {
		log.Fatal(err)
	}
}

func rootHandler(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path == "/" || r.URL.Path == "/index.html" {
		k := timestamp()
		rep := getReport(k)

		w.Header().Set("Content-Type", "text/html; charset=utf-8")
		err := tpl.Execute(w, rep)
		if err != nil {
			log.Println(err)
		}
	} else {
		http.Error(w, "Not found", 404)
	}
}

func reportHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	k := timestamp()
	rep := getReport(k)
	json.NewEncoder(w).Encode(rep)
}

func newDataHandler(w http.ResponseWriter, r *http.Request) {
	today := time.Now().Format("20060102")
	dir := filepath.Join(*dbDir, today)
	ensureDir(dir, 0700)

	var m map[string]interface{}
	lr := &io.LimitedReader{R: r.Body, N: 10240}
	err := json.NewDecoder(lr).Decode(&m)

	if err != nil {
		log.Println(err)
		http.Error(w, err.Error(), 500)
		return
	}

	id, ok := m["uniqueID"]
	if ok {
		idStr, ok := id.(string)
		if !ok {
			if err != nil {
				log.Println("No ID")
				http.Error(w, "No ID", 500)
				return
			}
		}

		f, err := os.Create(path.Join(dir, idStr+".json"))
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), 500)
			return
		}
		json.NewEncoder(f).Encode(m)
		f.Close()
	} else {
		log.Println("No ID")
		http.Error(w, "No ID", 500)
		return
	}
}

type report struct {
	UniqueID       string
	Version        string
	Platform       string
	NumRepos       int
	NumNodes       int
	TotFiles       int
	RepoMaxFiles   int
	TotMiB         int
	RepoMaxMiB     int
	MemoryUsageMiB int
	SHA256Perf     float64
	MemorySize     int
}

func fileList() ([]string, error) {
	files := make(map[string]string)
	t0 := time.Now().Add(-24 * time.Hour).Format("20060102")
	t1 := time.Now().Format("20060102")

	dir := filepath.Join(*dbDir, t0)
	gr, err := filepath.Glob(filepath.Join(dir, "*.json"))
	if err != nil {
		return nil, err
	}
	for _, f := range gr {
		bn := filepath.Base(f)
		files[bn] = f
	}

	dir = filepath.Join(*dbDir, t1)
	gr, err = filepath.Glob(filepath.Join(dir, "*.json"))
	if err != nil {
		return nil, err
	}
	for _, f := range gr {
		bn := filepath.Base(f)
		files[bn] = f
	}

	l := make([]string, 0, len(files))
	for _, f := range files {
		si, err := os.Stat(f)
		if err != nil {
			continue
		}
		if time.Since(si.ModTime()) < 24*time.Hour {
			l = append(l, f)
		}
	}

	return l, nil
}

type category struct {
	Values [4]float64
	Key    string
	Descr  string
	Unit   string
	Binary bool
}

var reportCache map[string]interface{}
var reportMutex sync.Mutex

func getReport(key string) map[string]interface{} {
	reportMutex.Lock()
	defer reportMutex.Unlock()

	if k := reportCache["key"]; k == key {
		return reportCache
	}

	files, err := fileList()
	if err != nil {
		return nil
	}

	nodes := 0
	var versions []string
	var platforms []string
	var oses []string
	var numRepos []int
	var numNodes []int
	var totFiles []int
	var maxFiles []int
	var totMiB []int
	var maxMiB []int
	var memoryUsage []int
	var sha256Perf []float64
	var memorySize []int

	for _, fn := range files {
		f, err := os.Open(fn)
		if err != nil {
			continue
		}

		var rep report
		err = json.NewDecoder(f).Decode(&rep)
		if err != nil {
			continue
		}
		f.Close()

		nodes++
		versions = append(versions, transformVersion(rep.Version))
		platforms = append(platforms, rep.Platform)
		ps := strings.Split(rep.Platform, "-")
		oses = append(oses, ps[0])
		if rep.NumRepos > 0 {
			numRepos = append(numRepos, rep.NumRepos)
		}
		if rep.NumNodes > 0 {
			numNodes = append(numNodes, rep.NumNodes)
		}
		if rep.TotFiles > 0 {
			totFiles = append(totFiles, rep.TotFiles)
		}
		if rep.RepoMaxFiles > 0 {
			maxFiles = append(maxFiles, rep.RepoMaxFiles)
		}
		if rep.TotMiB > 0 {
			totMiB = append(totMiB, rep.TotMiB*(1<<20))
		}
		if rep.RepoMaxMiB > 0 {
			maxMiB = append(maxMiB, rep.RepoMaxMiB*(1<<20))
		}
		if rep.MemoryUsageMiB > 0 {
			memoryUsage = append(memoryUsage, rep.MemoryUsageMiB*(1<<20))
		}
		if rep.SHA256Perf > 0 {
			sha256Perf = append(sha256Perf, rep.SHA256Perf*(1<<20))
		}
		if rep.MemorySize > 0 {
			memorySize = append(memorySize, rep.MemorySize*(1<<20))
		}
	}

	var categories []category
	categories = append(categories, category{
		Values: statsForInts(totFiles),
		Descr:  "Files Managed per Node",
	})

	categories = append(categories, category{
		Values: statsForInts(maxFiles),
		Descr:  "Files in Largest Repo",
	})

	categories = append(categories, category{
		Values: statsForInts(totMiB),
		Descr:  "Data Managed per Node",
		Unit:   "B",
		Binary: true,
	})

	categories = append(categories, category{
		Values: statsForInts(maxMiB),
		Descr:  "Data in Largest Repo",
		Unit:   "B",
		Binary: true,
	})

	categories = append(categories, category{
		Values: statsForInts(numNodes),
		Descr:  "Number of Nodes in Cluster",
	})

	categories = append(categories, category{
		Values: statsForInts(numRepos),
		Descr:  "Number of Repositories Configured",
	})

	categories = append(categories, category{
		Values: statsForInts(memoryUsage),
		Descr:  "Memory Usage",
		Unit:   "B",
		Binary: true,
	})

	categories = append(categories, category{
		Values: statsForInts(memorySize),
		Descr:  "System Memory",
		Unit:   "B",
		Binary: true,
	})

	categories = append(categories, category{
		Values: statsForFloats(sha256Perf),
		Descr:  "SHA-256 Hashing Performance",
		Unit:   "B/s",
		Binary: true,
	})

	r := make(map[string]interface{})
	r["key"] = key
	r["nodes"] = nodes
	r["categories"] = categories
	r["versions"] = analyticsFor(versions)
	r["platforms"] = analyticsFor(platforms)
	r["os"] = analyticsFor(oses)

	reportCache = r

	return r
}

func ensureDir(dir string, mode int) {
	fi, err := os.Stat(dir)
	if os.IsNotExist(err) {
		os.MkdirAll(dir, 0700)
	} else if mode >= 0 && err == nil && int(fi.Mode()&0777) != mode {
		os.Chmod(dir, os.FileMode(mode))
	}
}

var vRe = regexp.MustCompile(`^(v\d+\.\d+\.\d+(?:-[a-z]\w+)?)[+\.-]`)

// transformVersion returns a version number formatted correctly, with all
// development versions aggregated into one.
func transformVersion(v string) string {
	if v == "unknown-dev" {
		return v
	}
	if !strings.HasPrefix(v, "v") {
		v = "v" + v
	}
	if m := vRe.FindStringSubmatch(v); len(m) > 0 {
		return m[1] + " (+dev)"
	}
	return v
}

// timestamp returns a time stamp for the current hour, to be used as a cache key
func timestamp() string {
	return time.Now().Format("20060102T15")
}
<|endoftext|>