<commit_before>package main

import (
    "encoding/json"
    "fmt"
    //"html"
    "io/ioutil"
    "net/http"
    "os"
    "path/filepath"
    "regexp"
    //"strconv"
    "strings"
    "sync"
    "time"

    "github.com/fsnotify/fsnotify"
)

type Settings struct {
    RemoteDirectory string
    Address         string
}

type GameIDs map[string]string
var Games *GameList
var LastUpdate  *time.Time

var s Settings
var re_gamename = regexp.MustCompile(`<td itemprop="name">(.+?)</td>`)

// Structure of json from steam's servers
type steamapps struct {
    Applist struct {
        Apps    []struct {
            Appid   uint64  `json:"appid"`
            Name    string  `json:"name"`
        }   `json:"apps"`
    }   `json:"applist"`
}

type GameList struct {
    games   GameIDs
    m       sync.Mutex
}

func NewGameList() *GameList {
    return &GameList{
        games:  make(map[string]string),
    }
}

func (g *GameList) Get(id string) string {
    g.m.Lock()
    defer g.m.Unlock()

    if val, ok := g.games[id]; ok {
        return val
    }
    return id
}

func (g *GameList) Set(id, val string) string {
    g.m.Lock()
    defer g.m.Unlock()

    g.games[id] = val
    return val
}

func (g *GameList) Update(list GameIDs) {
    g.m.Lock()
    defer g.m.Unlock()

    for key, val := range list {
        g.games[key] = val
    }
}

func (g GameList) GetMap() GameIDs {
    g.m.Lock()
    defer g.m.Unlock()

    retList := GameIDs{}
    for key, val := range g.games {
        retList[key] = val
    }
    return retList
}

func (g GameList) Length() int {
    return len(g.games)
}

func main() {
    Games = NewGameList()
    if err := loadSettings(); err != nil {
        fmt.Printf("Error loading settings: %s\n", err)
        return
    }

    if err := init_templates(); err != nil {
        fmt.Printf("Error loading templates: %s\n", err)
        return
    }

    mux := http.NewServeMux()
    mux.HandleFunc("/", handler_main)
    mux.HandleFunc("/thumb/", handler_thumb)
    mux.HandleFunc("/img/", handler_image)
    mux.HandleFunc("/banner/", handler_banner)
    mux.HandleFunc("/static/", handler_static)

    server := &http.Server{
        Addr:           s.Address,
        Handler:        mux,
        ReadTimeout:    10 * time.Second,
        WriteTimeout:   10 * time.Second,
        MaxHeaderBytes: 1 << 20,
    }

    ready := make(chan bool)
    go watchThings(ready)
    if <-ready {
        fmt.Println("Watching things OK")
    } else {
        fmt.Println("Watching things NOT OK")
        return
    }

    fmt.Println("Listening on address: " + s.Address)
    fmt.Println("Fisnished startup.")
    server.ListenAndServe()
}

// Keep an eye on the directory and re-discover as needed.
func watchThings(ready chan bool) {
    // Initial discovery
    dir, err := filepath.Glob(filepath.Join(s.RemoteDirectory, "*"))
    if err != nil {
        fmt.Println("Unable to glob RemoteDirectory: ", err)
        ready <- false
        return
    }
    dataTree = make(map[string][]string)

    for _, d := range dir {
        if strings.HasPrefix(filepath.Base(d), ".") {
            continue
        }

        disc, err := discoverDir(d)
        if err != nil {
            fmt.Println(err)
            continue
        }

        dataTree[filepath.Base(d)] = disc
    }

    w_root, err := fsnotify.NewWatcher()
    if err != nil {
        fmt.Println("Falied to create root watcher: ", err);
        return
    }
    defer w_root.Close()

    done := make(chan bool)
    go func() {
        for {
            //fmt.Print(".")
            select {
                case event := <-w_root.Events:
                    if event.Op > 0 {
                        fmt.Println("w_root event: ", event)
                        if event.Op&fsnotify.Write == fsnotify.Write {
                            fmt.Println("Modified file: " , event.Name)
                        }
                    }
                case err := <-w_root.Errors:
                    if err != nil {
                        fmt.Println("w_root error: ", err)
                    }
            }
        }
    }()

    if err = w_root.Add(s.RemoteDirectory); err != nil {
        fmt.Println("Unable to add root directory to w_root: ", err)
        return
    }

    fmt.Printf("Watching directory %q\n", s.RemoteDirectory)
    ready <- true
    <-done
}

// Discover things in a single directory
func discoverDir(dir string) ([]string, error) {
    found := []string{}
    jpg, err := filepath.Glob(filepath.Join(dir, "screenshots", "*.jpg"))
    if err != nil {
        return nil, fmt.Errorf("JPG glob error in %q: %s", dir, err)
    }
    found = append(found, jpg...)

    png, err := filepath.Glob(filepath.Join(dir, "screenshots", "*.png"))
    if err != nil {
        return nil, fmt.Errorf("PNG glob error in %q: %s", dir, err)
    }
    found = append(found, png...)

    return found, nil
}

func SliceContains(s []string, val string) bool {
    for _, v := range s {
        if v == val {
            return true
        }
    }
    return false
}

func GetKeys(m map[string][]string) []string {
    keys := []string{}
    for k, _ := range m {
        keys = append(keys, k)
    }

    return keys
}

func loadSettings() error {
    settingsFilename := "settings.json"
    if len(os.Args) > 1 {
        settingsFilename = os.Args[1]
    }

    settingsFile, err := ioutil.ReadFile(settingsFilename)
    if err != nil {
        return fmt.Errorf("Error reading settings file: %s", err)
    }

    err = json.Unmarshal(settingsFile, &s)
    if err != nil {
        return fmt.Errorf("Error unmarshaling settings: %s", err)
    }

    fmt.Println("Settings loaded")

    //updateGamesJson("")
    return loadGames()
}

func loadGames() error {
    if ex := exists("games.json"); !ex {
        fmt.Println("games.json doesn't exist.  Getting a new one.")
        if err := updateGamesJson(); err != nil {
            return fmt.Errorf("Unable update game list: %", err)
        }
    }

    gamesFile, err := ioutil.ReadFile("games.json")
    if err != nil {
        return fmt.Errorf("Error reading games file: %s", err)
    }

    var games GameIDs
    err = json.Unmarshal(gamesFile, &games)
    if err != nil {
        return fmt.Errorf("Error unmarshaling games: %s", err)
    }

    Games.Update(games)
    //fmt.Println("Number of games loaded: ", Games.Length())
    return nil
}

func getGameName(appid string) (string, error) {
    if appid == ".stfolder" {
        return appid, nil
    }

    //fmt.Printf("Getting name for appid %q\n", appid)
    if name := Games.Get(appid); name != appid {
        return name, nil
    }

    // Large appid, must be a non-steam game.  This could have some edge cases
    // as non-steam games' appids are CRCs.
    if len(appid) > 18 {
        return Games.Set(appid, fmt.Sprintf("Non-Steam game (%s)", appid)), nil
    }

    // TODO: rate limiting/cache age
    if err := updateGamesJson(); err == nil {
        if name := Games.Get(appid); name != appid {
            return name, nil
        }
    }
    return appid, nil
}

// Update the local cache of appids from steam's servers.
func updateGamesJson() error {
    if LastUpdate != nil && time.Since(*LastUpdate).Minutes() < 30 {
        //return fmt.Errorf("Cache still good.")
        fmt.Println("Not updating games list; cache still good.")
        return nil
    }

    now := time.Now()
    //fmt.Printf("time.Now(): {}\n", now)
    LastUpdate = &now

    fmt.Println("Updating games list")
    resp, err := http.Get("http://api.steampowered.com/ISteamApps/GetAppList/v2")
    if err != nil {
        return fmt.Errorf("Unable to get appid list from steam: %s", err)
    }
    defer resp.Body.Close()

    js, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return fmt.Errorf("Unable to read appid json: %s", err)
    }

    alist := &steamapps{}
    if err := json.Unmarshal(js, alist); err != nil {
        return fmt.Errorf("Unable to unmarshal json: %s", err)
    }

    for _, a := range alist.Applist.Apps {
        id := fmt.Sprintf("%d", a.Appid)
        Games.Set(id, a.Name)

    }

    // save games.json
    games := Games.GetMap()
    marshaled, err := json.MarshalIndent(games, "", "  ")
    if err != nil {
        return fmt.Errorf("Unable to marshal game json: %s", err)
    }

    err = ioutil.WriteFile("games.json", marshaled, 0777)
    if err != nil {
        return fmt.Errorf("Unable to save games.json: %s", err)
    }

    fmt.Printf("Finished updating games list.  Appids: %d\n", len(games))
    return nil
}

// Returns a filename
func getGameBanner(appid uint64) (string, error) {
    appstr := fmt.Sprintf("%d", appid)
    if exist := exists("banners/" + appstr + ".jpg"); exist {
        return "banners/" + appstr + ".jpg", nil
    }

    resp, err := http.Get("http://cdn.akamai.steamstatic.com/steam/apps/" + appstr + "/header.jpg")
    if err != nil {
        return "", fmt.Errorf("Unable to DL header: %s", err)
    }

    if resp.StatusCode >= 400 && resp.StatusCode < 500 {
        // Game not found.  Use unknown.

        raw, err := ioutil.ReadFile("banners/unknown.jpg")
        if err != nil {
            return "", fmt.Errorf("Unable to read unknown.jpg")
        }

        if err = ioutil.WriteFile("banners/" + appstr + ".jpg", raw, 0777); err != nil {
            return "", fmt.Errorf("Unable to save file: %s", err)
        }

        return "banners/" + appstr + ".jpg", nil
    }

    defer resp.Body.Close()

    file, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return "", fmt.Errorf("Unable to read file: %s", err)
    }

    if err = ioutil.WriteFile("banners/" + appstr + ".jpg", file, 0777); err != nil {
        return "", fmt.Errorf("Unable to save file: %s", err)
    }

    return "banners/" + appstr + ".jpg", nil
}

// exists returns whether the given file or directory exists or not.
// Taken from https://stackoverflow.com/a/10510783
func exists(path string) bool {
    _, err := os.Stat(path)
    if err == nil { return true }
    if os.IsNotExist(err) { return false }
    return true
}
<commit_msg>Break out reloading directories into goroutines<commit_after>package main

import (
    "encoding/json"
    "fmt"
    //"html"
    "io/ioutil"
    "net/http"
    "os"
    "path/filepath"
    "regexp"
    //"strconv"
    "strings"
    "sync"
    "time"

    "github.com/fsnotify/fsnotify"
)

type Settings struct {
    RemoteDirectory string
    Address         string
}

type GameIDs map[string]string
var Games *GameList
var LastUpdate  *time.Time

var s Settings
var re_gamename = regexp.MustCompile(`<td itemprop="name">(.+?)</td>`)

// Structure of json from steam's servers
type steamapps struct {
    Applist struct {
        Apps    []struct {
            Appid   uint64  `json:"appid"`
            Name    string  `json:"name"`
        }   `json:"apps"`
    }   `json:"applist"`
}

type GameList struct {
    games   GameIDs
    m       sync.Mutex
}

func NewGameList() *GameList {
    return &GameList{
        games:  make(map[string]string),
    }
}

func (g *GameList) Get(id string) string {
    g.m.Lock()
    defer g.m.Unlock()

    if val, ok := g.games[id]; ok {
        return val
    }
    return id
}

func (g *GameList) Set(id, val string) string {
    g.m.Lock()
    defer g.m.Unlock()

    g.games[id] = val
    return val
}

func (g *GameList) Update(list GameIDs) {
    g.m.Lock()
    defer g.m.Unlock()

    for key, val := range list {
        g.games[key] = val
    }
}

func (g GameList) GetMap() GameIDs {
    g.m.Lock()
    defer g.m.Unlock()

    retList := GameIDs{}
    for key, val := range g.games {
        retList[key] = val
    }
    return retList
}

func (g GameList) Length() int {
    return len(g.games)
}

func main() {
    Games = NewGameList()
    if err := loadSettings(); err != nil {
        fmt.Printf("Error loading settings: %s\n", err)
        return
    }

    if err := init_templates(); err != nil {
        fmt.Printf("Error loading templates: %s\n", err)
        return
    }

    mux := http.NewServeMux()
    mux.HandleFunc("/", handler_main)
    mux.HandleFunc("/thumb/", handler_thumb)
    mux.HandleFunc("/img/", handler_image)
    mux.HandleFunc("/banner/", handler_banner)
    mux.HandleFunc("/static/", handler_static)

    server := &http.Server{
        Addr:           s.Address,
        Handler:        mux,
        ReadTimeout:    10 * time.Second,
        WriteTimeout:   10 * time.Second,
        MaxHeaderBytes: 1 << 20,
    }

    ready := make(chan bool)
    go watchThings(ready)
    if <-ready {
        fmt.Println("Watching things OK")
    } else {
        fmt.Println("Watching things NOT OK")
        return
    }

    fmt.Println("Listening on address: " + s.Address)
    fmt.Println("Fisnished startup.")
    server.ListenAndServe()
}

// Keep an eye on the directory and re-discover as needed.
func watchThings(ready chan bool) {
    type watcher struct {
        base string
        watch *fsnotify.Watcher
    }
    w_list := []watcher{}

    // Initial discovery
    dir, err := filepath.Glob(filepath.Join(s.RemoteDirectory, "*"))
    if err != nil {
        fmt.Println("Unable to glob RemoteDirectory: ", err)
        ready <- false
        return
    }
    dataTree = make(map[string][]string)

    for _, d := range dir {
        base := filepath.Base(d)
        if strings.HasPrefix(base, ".") {
            continue
        }

        disc, err := discoverDir(d)
        if err != nil {
            fmt.Println(err)
            continue
        }
        dataTree[base] = disc

        w, err := fsnotify.NewWatcher()
        if err != nil {
            fmt.Println("Unable to create watch for %q: %s", base, err)
            ready <- false
            return
        }

        if err := w.Add(filepath.Join(d, "screenshots")); err != nil {
            fmt.Println("Unable to add dir to watch %q: %s", base, err)
            ready <- false
            return
        }

        w_list = append(w_list, watcher{base: base, watch: w})
    }

    // Watch things to auto-discover them
    w_root, err := fsnotify.NewWatcher()
    if err != nil {
        fmt.Println("Falied to create root watcher: ", err);
        return
    }
    defer w_root.Close()

    done := make(chan bool)
    lock := sync.Mutex{}

    // Root monitor.  Creates and deletes other monitors.
    go func() {
        for {
            select {
                case event := <-w_root.Events:
                    if event.Op > 0 {
                        fmt.Println("w_root event: ", event)
                        if event.Op&fsnotify.Create == fsnotify.Create {
                            fmt.Println("Create event")
                            newdir := filepath.Base(event.Name)
                            w, err := fsnotify.NewWatcher()
                            if err != nil {
                                fmt.Printf("Unable to create watcher for %q: %s\n", newdir, err)
                                continue
                            }

                            if err := w.Add(filepath.Join(newdir, "screenshots")); err != nil {
                                fmt.Printf("Unable to add dir to watch %q: %s\n", newdir, err)
                                continue
                            }

                            lock.Lock()
                            w_list = append(w_list, watcher{base: newdir, watch: w})
                            lock.Unlock()
                            fmt.Printf("New directory %q added to watch list\n", newdir)
                        }
                    }
                case err := <-w_root.Errors:
                    if err != nil {
                        fmt.Println("w_root error: ", err)
                    }
            }
        }
    }()

    // Directory monitor.
    go func() {
        for {
            lock.Lock()
            for _, w := range w_list {
                select {
                    case event := <-w.watch.Events:
                        if event.Op > 0 {
                            fmt.Printf("%s event: %s", w.base, event)
                        }
                    case err := <-w.watch.Errors:
                        if err != nil {
                            fmt.Println("% error: %s", w.base, err)
                        }
                }
            }
            lock.Unlock()
            time.Sleep(100 * time.Millisecond)
        }
    }()

    if err = w_root.Add(s.RemoteDirectory); err != nil {
        fmt.Println("Unable to add root directory to w_root: ", err)
        return
    }

    fmt.Printf("Watching directory %q\n", s.RemoteDirectory)
    ready <- true
    <-done
}

// Discover things in a single directory
func discoverDir(dir string) ([]string, error) {
    found := []string{}
    jpg, err := filepath.Glob(filepath.Join(dir, "screenshots", "*.jpg"))
    if err != nil {
        return nil, fmt.Errorf("JPG glob error in %q: %s", dir, err)
    }
    found = append(found, jpg...)

    png, err := filepath.Glob(filepath.Join(dir, "screenshots", "*.png"))
    if err != nil {
        return nil, fmt.Errorf("PNG glob error in %q: %s", dir, err)
    }
    found = append(found, png...)

    return found, nil
}

func SliceContains(s []string, val string) bool {
    for _, v := range s {
        if v == val {
            return true
        }
    }
    return false
}

func GetKeys(m map[string][]string) []string {
    keys := []string{}
    for k, _ := range m {
        keys = append(keys, k)
    }

    return keys
}

func loadSettings() error {
    settingsFilename := "settings.json"
    if len(os.Args) > 1 {
        settingsFilename = os.Args[1]
    }

    settingsFile, err := ioutil.ReadFile(settingsFilename)
    if err != nil {
        return fmt.Errorf("Error reading settings file: %s", err)
    }

    err = json.Unmarshal(settingsFile, &s)
    if err != nil {
        return fmt.Errorf("Error unmarshaling settings: %s", err)
    }

    fmt.Println("Settings loaded")

    //updateGamesJson("")
    return loadGames()
}

func loadGames() error {
    if ex := exists("games.json"); !ex {
        fmt.Println("games.json doesn't exist.  Getting a new one.")
        if err := updateGamesJson(); err != nil {
            return fmt.Errorf("Unable update game list: %", err)
        }
    }

    gamesFile, err := ioutil.ReadFile("games.json")
    if err != nil {
        return fmt.Errorf("Error reading games file: %s", err)
    }

    var games GameIDs
    err = json.Unmarshal(gamesFile, &games)
    if err != nil {
        return fmt.Errorf("Error unmarshaling games: %s", err)
    }

    Games.Update(games)
    //fmt.Println("Number of games loaded: ", Games.Length())
    return nil
}

func getGameName(appid string) (string, error) {
    if appid == ".stfolder" {
        return appid, nil
    }

    //fmt.Printf("Getting name for appid %q\n", appid)
    if name := Games.Get(appid); name != appid {
        return name, nil
    }

    // Large appid, must be a non-steam game.  This could have some edge cases
    // as non-steam games' appids are CRCs.
    if len(appid) > 18 {
        return Games.Set(appid, fmt.Sprintf("Non-Steam game (%s)", appid)), nil
    }

    // TODO: rate limiting/cache age
    if err := updateGamesJson(); err == nil {
        if name := Games.Get(appid); name != appid {
            return name, nil
        }
    }
    return appid, nil
}

// Update the local cache of appids from steam's servers.
func updateGamesJson() error {
    if LastUpdate != nil && time.Since(*LastUpdate).Minutes() < 30 {
        //return fmt.Errorf("Cache still good.")
        fmt.Println("Not updating games list; cache still good.")
        return nil
    }

    now := time.Now()
    //fmt.Printf("time.Now(): {}\n", now)
    LastUpdate = &now

    fmt.Println("Updating games list")
    resp, err := http.Get("http://api.steampowered.com/ISteamApps/GetAppList/v2")
    if err != nil {
        return fmt.Errorf("Unable to get appid list from steam: %s", err)
    }
    defer resp.Body.Close()

    js, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return fmt.Errorf("Unable to read appid json: %s", err)
    }

    alist := &steamapps{}
    if err := json.Unmarshal(js, alist); err != nil {
        return fmt.Errorf("Unable to unmarshal json: %s", err)
    }

    for _, a := range alist.Applist.Apps {
        id := fmt.Sprintf("%d", a.Appid)
        Games.Set(id, a.Name)

    }

    // save games.json
    games := Games.GetMap()
    marshaled, err := json.MarshalIndent(games, "", "  ")
    if err != nil {
        return fmt.Errorf("Unable to marshal game json: %s", err)
    }

    err = ioutil.WriteFile("games.json", marshaled, 0777)
    if err != nil {
        return fmt.Errorf("Unable to save games.json: %s", err)
    }

    fmt.Printf("Finished updating games list.  Appids: %d\n", len(games))
    return nil
}

// Returns a filename
func getGameBanner(appid uint64) (string, error) {
    appstr := fmt.Sprintf("%d", appid)
    if exist := exists("banners/" + appstr + ".jpg"); exist {
        return "banners/" + appstr + ".jpg", nil
    }

    resp, err := http.Get("http://cdn.akamai.steamstatic.com/steam/apps/" + appstr + "/header.jpg")
    if err != nil {
        return "", fmt.Errorf("Unable to DL header: %s", err)
    }

    if resp.StatusCode >= 400 && resp.StatusCode < 500 {
        // Game not found.  Use unknown.

        raw, err := ioutil.ReadFile("banners/unknown.jpg")
        if err != nil {
            return "", fmt.Errorf("Unable to read unknown.jpg")
        }

        if err = ioutil.WriteFile("banners/" + appstr + ".jpg", raw, 0777); err != nil {
            return "", fmt.Errorf("Unable to save file: %s", err)
        }

        return "banners/" + appstr + ".jpg", nil
    }

    defer resp.Body.Close()

    file, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return "", fmt.Errorf("Unable to read file: %s", err)
    }

    if err = ioutil.WriteFile("banners/" + appstr + ".jpg", file, 0777); err != nil {
        return "", fmt.Errorf("Unable to save file: %s", err)
    }

    return "banners/" + appstr + ".jpg", nil
}

// exists returns whether the given file or directory exists or not.
// Taken from https://stackoverflow.com/a/10510783
func exists(path string) bool {
    _, err := os.Stat(path)
    if err == nil { return true }
    if os.IsNotExist(err) { return false }
    return true
}
<|endoftext|>


<commit_before>package main

import (
	"net/http"
	"html/template"
	"log"
	"github.com/codegangsta/martini"
	"github.com/tanner/isgtwifidown.com/gtwifi"
)

type PageData struct {
	Green bool
	Yellow bool
	Red bool
	Reason string
}

func main() {
	m := martini.Classic()

	template := template.Must(template.ParseFiles("index.tmpl"))

	m.Get("/", func(res http.ResponseWriter, req *http.Request) {
		status, err := gtwifi.GetStatus()
		if err != nil {
			log.Println(err);
		}

		data := PageData{}
		data.Green = status.Status == gtwifi.GREEN
		data.Yellow = status.Status == gtwifi.YELLOW
		data.Red = status.Status == gtwifi.RED
		data.Reason = status.Reason

		template.Execute(res, data)
	})

	m.Run()
}
<commit_msg>Don't check for new data every request, only ever 5 minutes.<commit_after>package main

import (
	"net/http"
	"html/template"
	"log"
	"time"
	"github.com/codegangsta/martini"
	"github.com/tanner/isgtwifidown.com/gtwifi"
)

type PageData struct {
	Green bool
	Yellow bool
	Red bool
	Reason string
}

type LastData struct {
	Status int
	Reason string
	TimeRetrieved time.Time
}

var lastData LastData;

func main() {
	m := martini.Classic()

	template := template.Must(template.ParseFiles("index.tmpl"))

	schedule(checkData, 5 * time.Minute)
	checkData()

	m.Get("/", func(res http.ResponseWriter, req *http.Request) {
		data := PageData{}
		data.Green = lastData.Status == gtwifi.GREEN
		data.Yellow = lastData.Status == gtwifi.YELLOW
		data.Red = lastData.Status == gtwifi.RED
		data.Reason = lastData.Reason

		template.Execute(res, data)
	})

	m.Run()
}

func checkData() {
	log.Println("Retrieving new data...");

	status, err := gtwifi.GetStatus()

	if err != nil {
		log.Println(err);
		return
	}

	log.Println("New data retrieved!");

	lastData = LastData{status.Status, status.Reason, time.Now()}
}

func schedule(caller func(), delay time.Duration) chan bool {
	ticker := time.NewTicker(delay)
	stop := make(chan bool)

	go func() {
		for {
			select {
			case <- ticker.C:
				caller();
			case <- stop:
				ticker.Stop()
				return
			}
		}
	}();

	return stop
}<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"gopkg.in/alecthomas/kingpin.v2"
	"os"
)

var (
	default_config = `platform: aws
region: us-west-1
`
	cloud_name       = kingpin.Flag("cloud", "Name of public/private cloud").Short('c').Default("default").String()
	cmd_init         = kingpin.Command("init", "Create a configuration file for a new cloud.")
	cmd_print_config = kingpin.Command("print-config", "Print the cloudctl configuration for this cloud.")
	cmd_ls           = kingpin.Command("ls", "List the instances in this cloud.")
)

func main() {
	// Initialise
	ensureConfigDir()

	// Handle cli args
	switch kingpin.Parse() {
	case "init":
		config_path := ConfigPath(*cloud_name)
		if _, err := os.Stat(config_path); os.IsNotExist(err) {
			WriteConfig(*config_path, default_config)
		}
	case "print-config":
		config := GetConfig(*cloud_name)
		fmt.Printf("%+v\n", config)
	case "ls":
		config := GetConfig(*cloud_name)
		cloud, err := NewCloud(config)
		if err != nil {
			fmt.Println("Couldn't create cloud interface.")
			fmt.Println(err)
		}
		cloud.listInstances()
	}
}
<commit_msg>Typo fix<commit_after>package main

import (
	"fmt"
	"gopkg.in/alecthomas/kingpin.v2"
	"os"
)

var (
	default_config = `platform: aws
region: us-west-1
`
	cloud_name       = kingpin.Flag("cloud", "Name of public/private cloud").Short('c').Default("default").String()
	cmd_init         = kingpin.Command("init", "Create a configuration file for a new cloud.")
	cmd_print_config = kingpin.Command("print-config", "Print the cloudctl configuration for this cloud.")
	cmd_ls           = kingpin.Command("ls", "List the instances in this cloud.")
)

func main() {
	// Initialise
	ensureConfigDir()

	// Handle cli args
	switch kingpin.Parse() {
	case "init":
		config_path := ConfigPath(*cloud_name)
		if _, err := os.Stat(config_path); os.IsNotExist(err) {
			WriteConfig(config_path, default_config)
		}
	case "print-config":
		config := GetConfig(*cloud_name)
		fmt.Printf("%+v\n", config)
	case "ls":
		config := GetConfig(*cloud_name)
		cloud, err := NewCloud(config)
		if err != nil {
			fmt.Println("Couldn't create cloud interface.")
			fmt.Println(err)
		}
		cloud.listInstances()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/md5"
	"crypto/sha1"
	"encoding/hex"
	"flag"
	"fmt"
	"hash"
	"io"
	"os"
	"path/filepath"
	"sort"
)

var Usage = func() {
	fmt.Fprintf(os.Stderr, "Usage:  %s [-h=md5|sha1] files... \n\n", os.Args[0])
	fmt.Fprintf(os.Stderr, "This utility will hash all the files given on the command line using the given\n")
	fmt.Fprintf(os.Stderr, "hash function.\n")
	fmt.Fprintf(os.Stderr, "It will print the results two ways, sorted by hash digest and by file name.\n")
	flag.PrintDefaults()
	fmt.Fprintf(os.Stderr, "  files...: 1 or more file name specifications\n")
}

type hashtype func() hash.Hash

func HashFile(filepath string, ht hashtype, digestlen int) string {
	if f, e := os.Open(filepath); e == nil {
		defer f.Close()
		hash := ht()
		if _, e := io.Copy(hash, f); e == nil {
			digest := make([]byte, 0, digestlen)
			return hex.EncodeToString(hash.Sum(digest))
		}
	}
	return ""
}

type FileDigest struct {
	fpth, dgst string
}

type ByFile []FileDigest

func (s ByFile) Len() int           { return len(s) }
func (s ByFile) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
func (s ByFile) Less(i, j int) bool { return s[i].fpth <= s[j].fpth }

type ByDigest []FileDigest

func (s ByDigest) Len() int           { return len(s) }
func (s ByDigest) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
func (s ByDigest) Less(i, j int) bool { return s[i].dgst <= s[j].dgst }

func output(sorteddata []FileDigest) {
	for _, fd := range sorteddata {
		fmt.Println(fd.dgst, "->", fd.fpth)
	}
}

func main() {

	hashflg := flag.String("h", "md5", "hash function to use: md5|sha1")
	flag.Usage = Usage
	flag.Parse()

	if flag.NArg() == 0 {
		fmt.Fprintf(os.Stderr, "No file specifications given as arguments.\n")
		Usage()
		return
	}

	digestlen := 0
	var h func() hash.Hash
	switch *hashflg {
	case "md5":
		digestlen = 32
		h = md5.New
		//fmt.Printf("%T\n",h)
	case "sha1":
		digestlen = 40
		h = sha1.New
		//fmt.Printf("%T\n",h)
	}

	var data []FileDigest
	for _, a := range flag.Args() {
		matches, _ := filepath.Glob(a)
		for _, m := range matches {
			data = append(data, FileDigest{m, HashFile(m, h, digestlen)})
		}
	}
	sort.Sort(ByFile(data))
	fmt.Println("by file name")
	output(data)
	fmt.Println("\n\nby file digest")
	sort.Sort(ByDigest(data))
	output(data)

}
<commit_msg>use package constant for length rather than hard coding<commit_after>package main

import (
	"crypto/md5"
	"crypto/sha1"
	"encoding/hex"
	"flag"
	"fmt"
	"hash"
	"io"
	"os"
	"path/filepath"
	"sort"
)

var Usage = func() {
	fmt.Fprintf(os.Stderr, "Usage:  %s [-h=md5|sha1] files... \n\n", os.Args[0])
	fmt.Fprintf(os.Stderr, "This utility will hash all the files given on the command line using the given\n")
	fmt.Fprintf(os.Stderr, "hash function.\n")
	fmt.Fprintf(os.Stderr, "It will print the results two ways, sorted by hash digest and by file name.\n")
	flag.PrintDefaults()
	fmt.Fprintf(os.Stderr, "  files...: 1 or more file name specifications\n")
}

type hashtype func() hash.Hash

func HashFile(filepath string, ht hashtype, digestlen int) string {
	if f, e := os.Open(filepath); e == nil {
		defer f.Close()
		hash := ht()
		if _, e := io.Copy(hash, f); e == nil {
			digest := make([]byte, 0, digestlen)
			return hex.EncodeToString(hash.Sum(digest))
		}
	}
	return ""
}

type FileDigest struct {
	fpth, dgst string
}

type ByFile []FileDigest

func (s ByFile) Len() int           { return len(s) }
func (s ByFile) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
func (s ByFile) Less(i, j int) bool { return s[i].fpth <= s[j].fpth }

type ByDigest []FileDigest

func (s ByDigest) Len() int           { return len(s) }
func (s ByDigest) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
func (s ByDigest) Less(i, j int) bool { return s[i].dgst <= s[j].dgst }

func output(sorteddata []FileDigest) {
	for _, fd := range sorteddata {
		fmt.Println(fd.dgst, "->", fd.fpth)
	}
}

func main() {

	hashflg := flag.String("h", "md5", "hash function to use: md5|sha1")
	flag.Usage = Usage
	flag.Parse()

	if flag.NArg() == 0 {
		fmt.Fprintf(os.Stderr, "No file specifications given as arguments.\n")
		Usage()
		return
	}

	digestlen := 0
	var h func() hash.Hash
	switch *hashflg {
	case "md5":
		digestlen = md5.Size * 2
		h = md5.New
	case "sha1":
		digestlen = sha1.Size * 2
		h = sha1.New
	}

	var data []FileDigest
	for _, a := range flag.Args() {
		matches, _ := filepath.Glob(a)
		for _, m := range matches {
			data = append(data, FileDigest{m, HashFile(m, h, digestlen)})
		}
	}
	sort.Sort(ByFile(data))
	fmt.Println("by file name")
	output(data)
	fmt.Println("\n\nby file digest")
	sort.Sort(ByDigest(data))
	output(data)

}
<|endoftext|>


<commit_before>// Package now is a time toolkit for golang.
//
// More details README here: https://github.com/jinzhu/now
//
//  import "github.com/jinzhu/now"
//
//  now.BeginningOfMinute() // 2013-11-18 17:51:00 Mon
//  now.BeginningOfDay()    // 2013-11-18 00:00:00 Mon
//  now.EndOfDay()          // 2013-11-18 23:59:59.999999999 Mon
package now

import "time"

// WeekStartDay set week start day, default is sunday
var WeekStartDay = time.Sunday

// TimeFormats default time formats will be parsed as
var TimeFormats = []string{
	"2006", "2006-1", "2006-1-2", "2006-1-2 15", "2006-1-2 15:4", "2006-1-2 15:4:5", "1-2",
	"15:4:5", "15:4", "15",
	"15:4:5 Jan 2, 2006 MST", "2006-01-02 15:04:05.999999999 -0700 MST", "2006-01-02T15:04:05-07:00",
	"2006.1.2", "2006.1.2 15:04:05", "2006.01.02", "2006.01.02 15:04:05",
	"1/2/2006", "1/2/2006 15:4:5", "2006/01/02", "2006/01/02 15:04:05",
	time.RFC3339,
}

// Config configuration for now package
type Config struct {
	WeekStartDay time.Weekday
	TimeLocation *time.Location
	TimeFormats  []string
}

// DefaultConfig default config
var DefaultConfig *Config

// New initialize Now based on configuration
func (config *Config) New(t time.Time) *Now {
	return &Now{Time: t, Config: config}
}

// Parse parse string to time based on configuration
func (config *Config) Parse(strs ...string) (time.Time, error) {
	if config.TimeLocation == nil {
		return config.New(time.Now()).Parse(strs...)
	} else {
		return config.New(time.Now().In(config.TimeLocation)).Parse(strs...)
	}
}

// MustParse must parse string to time or will panic
func (config *Config) MustParse(strs ...string) time.Time {
	if config.TimeLocation == nil {
		return config.New(time.Now()).MustParse(strs...)
	} else {
		return config.New(time.Now().In(config.TimeLocation)).MustParse(strs...)
	}
}

// Now now struct
type Now struct {
	time.Time
	*Config
}

// New initialize Now with time
func New(t time.Time) *Now {
	config := DefaultConfig
	if config == nil {
		config = &Config{
			WeekStartDay: WeekStartDay,
			TimeFormats:  TimeFormats,
		}
	}

	return &Now{Time: t, Config: config}
}

// BeginningOfMinute beginning of minute
func BeginningOfMinute() time.Time {
	return New(time.Now()).BeginningOfMinute()
}

// BeginningOfHour beginning of hour
func BeginningOfHour() time.Time {
	return New(time.Now()).BeginningOfHour()
}

// BeginningOfDay beginning of day
func BeginningOfDay() time.Time {
	return New(time.Now()).BeginningOfDay()
}

// BeginningOfWeek beginning of week
func BeginningOfWeek() time.Time {
	return New(time.Now()).BeginningOfWeek()
}

// BeginningOfMonth beginning of month
func BeginningOfMonth() time.Time {
	return New(time.Now()).BeginningOfMonth()
}

// BeginningOfQuarter beginning of quarter
func BeginningOfQuarter() time.Time {
	return New(time.Now()).BeginningOfQuarter()
}

// BeginningOfYear beginning of year
func BeginningOfYear() time.Time {
	return New(time.Now()).BeginningOfYear()
}

// EndOfMinute end of minute
func EndOfMinute() time.Time {
	return New(time.Now()).EndOfMinute()
}

// EndOfHour end of hour
func EndOfHour() time.Time {
	return New(time.Now()).EndOfHour()
}

// EndOfDay end of day
func EndOfDay() time.Time {
	return New(time.Now()).EndOfDay()
}

// EndOfWeek end of week
func EndOfWeek() time.Time {
	return New(time.Now()).EndOfWeek()
}

// EndOfMonth end of month
func EndOfMonth() time.Time {
	return New(time.Now()).EndOfMonth()
}

// EndOfQuarter end of quarter
func EndOfQuarter() time.Time {
	return New(time.Now()).EndOfQuarter()
}

// EndOfYear end of year
func EndOfYear() time.Time {
	return New(time.Now()).EndOfYear()
}

// Monday monday
func Monday() time.Time {
	return New(time.Now()).Monday()
}

// Sunday sunday
func Sunday() time.Time {
	return New(time.Now()).Sunday()
}

// EndOfSunday end of sunday
func EndOfSunday() time.Time {
	return New(time.Now()).EndOfSunday()
}

// Parse parse string to time
func Parse(strs ...string) (time.Time, error) {
	return New(time.Now()).Parse(strs...)
}

// ParseInLocation parse string to time in location
func ParseInLocation(loc *time.Location, strs ...string) (time.Time, error) {
	return New(time.Now().In(loc)).Parse(strs...)
}

// MustParse must parse string to time or will panic
func MustParse(strs ...string) time.Time {
	return New(time.Now()).MustParse(strs...)
}

// MustParseInLocation must parse string to time in location or will panic
func MustParseInLocation(loc *time.Location, strs ...string) time.Time {
	return New(time.Now().In(loc)).MustParse(strs...)
}

// Between check now between the begin, end time or not
func Between(time1, time2 string) bool {
	return New(time.Now()).Between(time1, time2)
}
<commit_msg>Add common go time formats, fix #15<commit_after>// Package now is a time toolkit for golang.
//
// More details README here: https://github.com/jinzhu/now
//
//  import "github.com/jinzhu/now"
//
//  now.BeginningOfMinute() // 2013-11-18 17:51:00 Mon
//  now.BeginningOfDay()    // 2013-11-18 00:00:00 Mon
//  now.EndOfDay()          // 2013-11-18 23:59:59.999999999 Mon
package now

import "time"

// WeekStartDay set week start day, default is sunday
var WeekStartDay = time.Sunday

// TimeFormats default time formats will be parsed as
var TimeFormats = []string{
	"2006", "2006-1", "2006-1-2", "2006-1-2 15", "2006-1-2 15:4", "2006-1-2 15:4:5", "1-2",
	"15:4:5", "15:4", "15",
	"15:4:5 Jan 2, 2006 MST", "2006-01-02 15:04:05.999999999 -0700 MST", "2006-01-02T15:04:05-07:00",
	"2006.1.2", "2006.1.2 15:04:05", "2006.01.02", "2006.01.02 15:04:05",
	"1/2/2006", "1/2/2006 15:4:5", "2006/01/02", "2006/01/02 15:04:05",
	time.ANSIC, time.UnixDate, time.RubyDate, time.RFC822, time.RFC822Z, time.RFC850,
	time.RFC1123, time.RFC1123Z, time.RFC3339, time.RFC3339Nano,
	time.Kitchen, time.Stamp, time.StampMilli, time.StampMicro, time.StampNano,
}

// Config configuration for now package
type Config struct {
	WeekStartDay time.Weekday
	TimeLocation *time.Location
	TimeFormats  []string
}

// DefaultConfig default config
var DefaultConfig *Config

// New initialize Now based on configuration
func (config *Config) New(t time.Time) *Now {
	return &Now{Time: t, Config: config}
}

// Parse parse string to time based on configuration
func (config *Config) Parse(strs ...string) (time.Time, error) {
	if config.TimeLocation == nil {
		return config.New(time.Now()).Parse(strs...)
	} else {
		return config.New(time.Now().In(config.TimeLocation)).Parse(strs...)
	}
}

// MustParse must parse string to time or will panic
func (config *Config) MustParse(strs ...string) time.Time {
	if config.TimeLocation == nil {
		return config.New(time.Now()).MustParse(strs...)
	} else {
		return config.New(time.Now().In(config.TimeLocation)).MustParse(strs...)
	}
}

// Now now struct
type Now struct {
	time.Time
	*Config
}

// New initialize Now with time
func New(t time.Time) *Now {
	config := DefaultConfig
	if config == nil {
		config = &Config{
			WeekStartDay: WeekStartDay,
			TimeFormats:  TimeFormats,
		}
	}

	return &Now{Time: t, Config: config}
}

// BeginningOfMinute beginning of minute
func BeginningOfMinute() time.Time {
	return New(time.Now()).BeginningOfMinute()
}

// BeginningOfHour beginning of hour
func BeginningOfHour() time.Time {
	return New(time.Now()).BeginningOfHour()
}

// BeginningOfDay beginning of day
func BeginningOfDay() time.Time {
	return New(time.Now()).BeginningOfDay()
}

// BeginningOfWeek beginning of week
func BeginningOfWeek() time.Time {
	return New(time.Now()).BeginningOfWeek()
}

// BeginningOfMonth beginning of month
func BeginningOfMonth() time.Time {
	return New(time.Now()).BeginningOfMonth()
}

// BeginningOfQuarter beginning of quarter
func BeginningOfQuarter() time.Time {
	return New(time.Now()).BeginningOfQuarter()
}

// BeginningOfYear beginning of year
func BeginningOfYear() time.Time {
	return New(time.Now()).BeginningOfYear()
}

// EndOfMinute end of minute
func EndOfMinute() time.Time {
	return New(time.Now()).EndOfMinute()
}

// EndOfHour end of hour
func EndOfHour() time.Time {
	return New(time.Now()).EndOfHour()
}

// EndOfDay end of day
func EndOfDay() time.Time {
	return New(time.Now()).EndOfDay()
}

// EndOfWeek end of week
func EndOfWeek() time.Time {
	return New(time.Now()).EndOfWeek()
}

// EndOfMonth end of month
func EndOfMonth() time.Time {
	return New(time.Now()).EndOfMonth()
}

// EndOfQuarter end of quarter
func EndOfQuarter() time.Time {
	return New(time.Now()).EndOfQuarter()
}

// EndOfYear end of year
func EndOfYear() time.Time {
	return New(time.Now()).EndOfYear()
}

// Monday monday
func Monday() time.Time {
	return New(time.Now()).Monday()
}

// Sunday sunday
func Sunday() time.Time {
	return New(time.Now()).Sunday()
}

// EndOfSunday end of sunday
func EndOfSunday() time.Time {
	return New(time.Now()).EndOfSunday()
}

// Parse parse string to time
func Parse(strs ...string) (time.Time, error) {
	return New(time.Now()).Parse(strs...)
}

// ParseInLocation parse string to time in location
func ParseInLocation(loc *time.Location, strs ...string) (time.Time, error) {
	return New(time.Now().In(loc)).Parse(strs...)
}

// MustParse must parse string to time or will panic
func MustParse(strs ...string) time.Time {
	return New(time.Now()).MustParse(strs...)
}

// MustParseInLocation must parse string to time in location or will panic
func MustParseInLocation(loc *time.Location, strs ...string) time.Time {
	return New(time.Now().In(loc)).MustParse(strs...)
}

// Between check now between the begin, end time or not
func Between(time1, time2 string) bool {
	return New(time.Now()).Between(time1, time2)
}
<|endoftext|>


<commit_before>// +build windows

package main

import (
	"bytes"
	"encoding/json"
	"log"
	"os/exec"
	"strings"
	"time"
)

// Stat represents stats to send to graphite
type Stat struct {
	Key   string `json:"key"`
	Value string `json:"value"`
	DT    int64  `json:"dt"`
}

func getCPUStats() (stat Stat) {
	var out bytes.Buffer
	cmd := exec.Command("typeperf", "-sc", "1", "processor(_total)\\% processor time")
	cmd.Stdout = &out
	err := cmd.Run()
	if err != nil {
		log.Fatal(err)
	}

	chunks := strings.Split(out.String(), ",")
	chunks = strings.Split(chunks[2], "\"")
	stat = Stat{"cpu", chunks[1], time.Now().Unix()}
	return
}

func getStats() (stats []Stat) {
	stats = append(stats, getCPUStats(), getCPUStats(), getCPUStats())
	return
}
func main() {
	b, _ := json.Marshal(getStats())
	log.Printf("Output: %s", string(b))
}
<commit_msg>grab stats forever and ever<commit_after>// +build windows

package main

import (
	"bytes"
	"encoding/json"
	"log"
	"os/exec"
	"strings"
	"time"
)

// Stat represents stats to send to graphite
type Stat struct {
	Key   string `json:"key"`
	Value string `json:"value"`
	DT    int64  `json:"dt"`
}

func schedule(what func(), delay time.Duration) chan bool {
	stop := make(chan bool)

	go func() {
		for {
			what()
			select {
			case <-time.After(delay):
			case <-stop:
				return
			}
		}
	}()

	return stop
}

func getCPUStats() (stat Stat) {
	var out bytes.Buffer
	cmd := exec.Command("typeperf", "-sc", "1", "processor(_total)\\% processor time")
	cmd.Stdout = &out
	err := cmd.Run()
	if err != nil {
		log.Fatal(err)
	}

	chunks := strings.Split(out.String(), ",")
	chunks = strings.Split(chunks[2], "\"")
	stat = Stat{"cpu", chunks[1], time.Now().Unix()}
	return
}

func getStats() (stats []Stat) {
	stats = append(stats, getCPUStats())
	return
}

func main() {
	var stats []Stat
	getStatsInterval := func() {
		newStats := getStats()
		stats = append(stats, newStats...)
	}
	outputStatsInterval := func() {
		var stat Stat
		for len(stats) != 0 {
			stat, stats = stats[len(stats)-1], stats[:len(stats)-1]
			b, _ := json.Marshal(stat)
			log.Printf("Output: %s", string(b))
		}
	}
	/*stopGet := */ schedule(getStatsInterval, 5*time.Second)
	/*stopOutput := */ schedule(outputStatsInterval, 5*time.Millisecond)
	for {
		time.Sleep(100 * time.Second)
	}
}
<|endoftext|>


<commit_before>/*
 * Copyright 2013 Nan Deng
 *
 * 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 (
	"flag"
	"fmt"
	"net"
	"os"
	"time"
	"strings"
)

var argvPort = flag.Int("port", 8117, "port to listen")
var argvCandidates = flag.String("nodes", "", "comma separated list of nodes.")
var argvRestBind = flag.String("http", "127.0.0.1:8080", "Network address which will be bind to a restful service")
var argvShowPort = flag.Bool("showport", false, "Output the leader's port number (which is only useful for debug purpose)")
var argvUnixTime = flag.Bool("unixTime", true, "Show the timestamp in unix time")

func main() {
	flag.Parse()
	bindAddr := fmt.Sprintf("0.0.0.0:%v", *argvPort)

	ln, err := net.Listen("tcp", bindAddr)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%v\n", err)
		return
	}
	bully := NewBully(ln, nil)
	defer bully.Finalize()

	nodeAddr := strings.Split(*argvCandidates, ",")
	dialTimtout := 5 * time.Second

	for _, node := range nodeAddr {
		err := bully.AddCandidate(node, nil, dialTimtout)
		if err != nil {
			fmt.Fprintf(os.Stderr, "%v cannot be added: %v\n", node, err)
		}
	}

	fmt.Printf("My ID: %v\n", bully.MyId())

	web := NewWebAPI(bully, *argvShowPort, *argvUnixTime)
	web.Run(*argvRestBind)
	bully.Finalize()
}

<commit_msg>[Mod] skip empty node names<commit_after>/*
 * Copyright 2013 Nan Deng
 *
 * 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 (
	"flag"
	"fmt"
	"net"
	"os"
	"time"
	"strings"
)

var argvPort = flag.Int("port", 8117, "port to listen")
var argvCandidates = flag.String("nodes", "", "comma separated list of nodes.")
var argvRestBind = flag.String("http", "127.0.0.1:8080", "Network address which will be bind to a restful service")
var argvShowPort = flag.Bool("showport", false, "Output the leader's port number (which is only useful for debug purpose)")
var argvUnixTime = flag.Bool("unixTime", true, "Show the timestamp in unix time")

func main() {
	flag.Parse()
	bindAddr := fmt.Sprintf("0.0.0.0:%v", *argvPort)

	ln, err := net.Listen("tcp", bindAddr)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%v\n", err)
		return
	}
	bully := NewBully(ln, nil)
	defer bully.Finalize()

	nodeAddr := strings.Split(*argvCandidates, ",")
	dialTimtout := 5 * time.Second

	for _, node := range nodeAddr {
		if len(node) == 0 {
			continue
		}
		err := bully.AddCandidate(node, nil, dialTimtout)
		if err != nil {
			fmt.Fprintf(os.Stderr, "%v cannot be added: %v\n", node, err)
		}
	}

	fmt.Printf("My ID: %v\n", bully.MyId())

	web := NewWebAPI(bully, *argvShowPort, *argvUnixTime)
	web.Run(*argvRestBind)
	bully.Finalize()
}

<|endoftext|>


<commit_before>/*

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 (
	"flag"
	"os"
	"time"

	"github.com/go-logr/zapr"
	opa "github.com/open-policy-agent/frameworks/constraint/pkg/client"
	"github.com/open-policy-agent/frameworks/constraint/pkg/client/drivers/local"
	"github.com/open-policy-agent/gatekeeper/api"
	configv1alpha1 "github.com/open-policy-agent/gatekeeper/api/v1alpha1"
	"github.com/open-policy-agent/gatekeeper/pkg/audit"
	"github.com/open-policy-agent/gatekeeper/pkg/controller"
	configController "github.com/open-policy-agent/gatekeeper/pkg/controller/config"
	"github.com/open-policy-agent/gatekeeper/pkg/controller/constrainttemplate"
	"github.com/open-policy-agent/gatekeeper/pkg/metrics"
	"github.com/open-policy-agent/gatekeeper/pkg/target"
	"github.com/open-policy-agent/gatekeeper/pkg/upgrade"
	"github.com/open-policy-agent/gatekeeper/pkg/watch"
	"github.com/open-policy-agent/gatekeeper/pkg/webhook"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"k8s.io/apimachinery/pkg/runtime"
	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
	_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
	ctrl "sigs.k8s.io/controller-runtime"
	k8sCli "sigs.k8s.io/controller-runtime/pkg/client"
	crzap "sigs.k8s.io/controller-runtime/pkg/log/zap"
	// +kubebuilder:scaffold:imports
)

var (
	scheme   = runtime.NewScheme()
	setupLog = ctrl.Log.WithName("setup")
)

var (
	logLevel    = flag.String("log-level", "INFO", "Minimum log level. For example, DEBUG, INFO, WARNING, ERROR. Defaulted to INFO if unspecified.")
	metricsAddr = flag.String("metrics-addr", ":8080", "The address the metric endpoint binds to.")
	port        = flag.Int("port", 443, "port for the server. defaulted to 443 if unspecified ")
	certDir     = flag.String("cert-dir", "/certs", "The directory where certs are stored, defaults to /certs")
)

func init() {
	_ = clientgoscheme.AddToScheme(scheme)

	_ = api.AddToScheme(scheme)

	_ = configv1alpha1.AddToScheme(scheme)
	// +kubebuilder:scaffold:scheme
}

func main() {
	flag.Parse()

	switch *logLevel {
	case "DEBUG":
		ctrl.SetLogger(crzap.Logger(true))
	case "WARNING", "ERROR":
		setLoggerForProduction()
	case "INFO":
		fallthrough
	default:
		ctrl.SetLogger(crzap.Logger(false))
	}
	ctrl.SetLogger(crzap.Logger(true))

	mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
		Scheme:             scheme,
		MetricsBindAddress: *metricsAddr,
		LeaderElection:     false,
		Port:               *port,
		CertDir:            *certDir,
	})
	if err != nil {
		setupLog.Error(err, "unable to start manager")
		os.Exit(1)
	}

	// initialize OPA
	driver := local.New(local.Tracing(false))
	backend, err := opa.NewBackend(opa.Driver(driver))
	if err != nil {
		setupLog.Error(err, "unable to set up OPA backend")
		os.Exit(1)
	}
	client, err := backend.NewClient(opa.Targets(&target.K8sValidationTarget{}))
	if err != nil {
		setupLog.Error(err, "unable to set up OPA client")
	}

	wm, err := watch.New(mgr.GetConfig())
	if err != nil {
		setupLog.Error(err, "unable to create watch manager")
		os.Exit(1)
	}
	if err := mgr.Add(wm); err != nil {
		setupLog.Error(err, "unable to register watch manager to the manager")
		os.Exit(1)
	}

	// Setup all Controllers
	setupLog.Info("Setting up controller")
	if err := controller.AddToManager(mgr, client, wm); err != nil {
		setupLog.Error(err, "unable to register controllers to the manager")
		os.Exit(1)
	}

	setupLog.Info("setting up webhooks")
	if err := webhook.AddToManager(mgr, client); err != nil {
		setupLog.Error(err, "unable to register webhooks to the manager")
		os.Exit(1)
	}

	setupLog.Info("setting up audit")
	if err := audit.AddToManager(mgr, client); err != nil {
		setupLog.Error(err, "unable to register audit to the manager")
		os.Exit(1)
	}

	setupLog.Info("setting up upgrade")
	if err := upgrade.AddToManager(mgr); err != nil {
		setupLog.Error(err, "unable to register upgrade to the manager")
		os.Exit(1)
	}

	setupLog.Info("setting up metrics")
	if err := metrics.AddToManager(mgr); err != nil {
		setupLog.Error(err, "unable to register metrics to the manager")
		os.Exit(1)
	}

	// +kubebuilder:scaffold:builder

	setupLog.Info("starting manager")
	hadError := false
	if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
		setupLog.Error(err, "problem running manager")
		hadError = true
	}

	// wm.Pause() blocks until the watch manager has stopped and ensures it does
	// not restart
	if err := wm.Pause(); err != nil {
		setupLog.Error(err, "could not pause watch manager, attempting cleanup anyway")
	}

	// Unfortunately there is no way to block until all child
	// goroutines of the manager have finished, so sleep long
	// enough for dangling reconciles to finish
	// time.Sleep(5 * time.Second)
	time.Sleep(5 * time.Second)

	// Create a fresh client to be sure RESTmapper is up-to-date
	setupLog.Info("cleaning state...")
	cli, err := k8sCli.New(mgr.GetConfig(), k8sCli.Options{Scheme: mgr.GetScheme(), Mapper: nil})
	if err != nil {
		setupLog.Error(err, "unable to create cleanup client")
		os.Exit(1)
	}

	// Clean up sync finalizers
	// This logic should be disabled if OPA is run as a sidecar
	syncCleaned := make(chan struct{})
	go configController.TearDownState(cli, syncCleaned)

	// Clean up constraint finalizers
	templatesCleaned := make(chan struct{})
	go constrainttemplate.TearDownState(cli, templatesCleaned)

	<-syncCleaned
	<-templatesCleaned
	setupLog.Info("state cleaned")
	if hadError {
		os.Exit(1)
	}
}

func setLoggerForProduction() {
	sink := zapcore.AddSync(os.Stderr)
	var opts []zap.Option
	encCfg := zap.NewProductionEncoderConfig()
	enc := zapcore.NewJSONEncoder(encCfg)
	lvl := zap.NewAtomicLevelAt(zap.WarnLevel)
	opts = append(opts, zap.AddStacktrace(zap.ErrorLevel),
		zap.WrapCore(func(core zapcore.Core) zapcore.Core {
			return zapcore.NewSampler(core, time.Second, 100, 100)
		}))
	opts = append(opts, zap.AddCallerSkip(1), zap.ErrorOutput(sink))
	zlog := zap.New(zapcore.NewCore(&crzap.KubeAwareEncoder{Encoder: enc, Verbose: false}, sink, lvl))
	zlog = zlog.WithOptions(opts...)
	newlogger := zapr.NewLogger(zlog)
	ctrl.SetLogger(newlogger)
}
<commit_msg>Disable default Kubebuilder metrics (#397)<commit_after>/*

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 (
	"flag"
	"os"
	"time"

	"github.com/go-logr/zapr"
	opa "github.com/open-policy-agent/frameworks/constraint/pkg/client"
	"github.com/open-policy-agent/frameworks/constraint/pkg/client/drivers/local"
	"github.com/open-policy-agent/gatekeeper/api"
	configv1alpha1 "github.com/open-policy-agent/gatekeeper/api/v1alpha1"
	"github.com/open-policy-agent/gatekeeper/pkg/audit"
	"github.com/open-policy-agent/gatekeeper/pkg/controller"
	configController "github.com/open-policy-agent/gatekeeper/pkg/controller/config"
	"github.com/open-policy-agent/gatekeeper/pkg/controller/constrainttemplate"
	"github.com/open-policy-agent/gatekeeper/pkg/metrics"
	"github.com/open-policy-agent/gatekeeper/pkg/target"
	"github.com/open-policy-agent/gatekeeper/pkg/upgrade"
	"github.com/open-policy-agent/gatekeeper/pkg/watch"
	"github.com/open-policy-agent/gatekeeper/pkg/webhook"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"k8s.io/apimachinery/pkg/runtime"
	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
	_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
	ctrl "sigs.k8s.io/controller-runtime"
	k8sCli "sigs.k8s.io/controller-runtime/pkg/client"
	crzap "sigs.k8s.io/controller-runtime/pkg/log/zap"
	// +kubebuilder:scaffold:imports
)

var (
	scheme   = runtime.NewScheme()
	setupLog = ctrl.Log.WithName("setup")
)

var (
	logLevel    = flag.String("log-level", "INFO", "Minimum log level. For example, DEBUG, INFO, WARNING, ERROR. Defaulted to INFO if unspecified.")
	metricsAddr = flag.String("metrics-addr", "0", "The address the metric endpoint binds to.")
	port        = flag.Int("port", 443, "port for the server. defaulted to 443 if unspecified ")
	certDir     = flag.String("cert-dir", "/certs", "The directory where certs are stored, defaults to /certs")
)

func init() {
	_ = clientgoscheme.AddToScheme(scheme)

	_ = api.AddToScheme(scheme)

	_ = configv1alpha1.AddToScheme(scheme)
	// +kubebuilder:scaffold:scheme
}

func main() {
	flag.Parse()

	switch *logLevel {
	case "DEBUG":
		ctrl.SetLogger(crzap.Logger(true))
	case "WARNING", "ERROR":
		setLoggerForProduction()
	case "INFO":
		fallthrough
	default:
		ctrl.SetLogger(crzap.Logger(false))
	}
	ctrl.SetLogger(crzap.Logger(true))

	mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
		Scheme:             scheme,
		MetricsBindAddress: *metricsAddr,
		LeaderElection:     false,
		Port:               *port,
		CertDir:            *certDir,
	})
	if err != nil {
		setupLog.Error(err, "unable to start manager")
		os.Exit(1)
	}

	// initialize OPA
	driver := local.New(local.Tracing(false))
	backend, err := opa.NewBackend(opa.Driver(driver))
	if err != nil {
		setupLog.Error(err, "unable to set up OPA backend")
		os.Exit(1)
	}
	client, err := backend.NewClient(opa.Targets(&target.K8sValidationTarget{}))
	if err != nil {
		setupLog.Error(err, "unable to set up OPA client")
	}

	wm, err := watch.New(mgr.GetConfig())
	if err != nil {
		setupLog.Error(err, "unable to create watch manager")
		os.Exit(1)
	}
	if err := mgr.Add(wm); err != nil {
		setupLog.Error(err, "unable to register watch manager to the manager")
		os.Exit(1)
	}

	// Setup all Controllers
	setupLog.Info("Setting up controller")
	if err := controller.AddToManager(mgr, client, wm); err != nil {
		setupLog.Error(err, "unable to register controllers to the manager")
		os.Exit(1)
	}

	setupLog.Info("setting up webhooks")
	if err := webhook.AddToManager(mgr, client); err != nil {
		setupLog.Error(err, "unable to register webhooks to the manager")
		os.Exit(1)
	}

	setupLog.Info("setting up audit")
	if err := audit.AddToManager(mgr, client); err != nil {
		setupLog.Error(err, "unable to register audit to the manager")
		os.Exit(1)
	}

	setupLog.Info("setting up upgrade")
	if err := upgrade.AddToManager(mgr); err != nil {
		setupLog.Error(err, "unable to register upgrade to the manager")
		os.Exit(1)
	}

	setupLog.Info("setting up metrics")
	if err := metrics.AddToManager(mgr); err != nil {
		setupLog.Error(err, "unable to register metrics to the manager")
		os.Exit(1)
	}

	// +kubebuilder:scaffold:builder

	setupLog.Info("starting manager")
	hadError := false
	if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
		setupLog.Error(err, "problem running manager")
		hadError = true
	}

	// wm.Pause() blocks until the watch manager has stopped and ensures it does
	// not restart
	if err := wm.Pause(); err != nil {
		setupLog.Error(err, "could not pause watch manager, attempting cleanup anyway")
	}

	// Unfortunately there is no way to block until all child
	// goroutines of the manager have finished, so sleep long
	// enough for dangling reconciles to finish
	// time.Sleep(5 * time.Second)
	time.Sleep(5 * time.Second)

	// Create a fresh client to be sure RESTmapper is up-to-date
	setupLog.Info("cleaning state...")
	cli, err := k8sCli.New(mgr.GetConfig(), k8sCli.Options{Scheme: mgr.GetScheme(), Mapper: nil})
	if err != nil {
		setupLog.Error(err, "unable to create cleanup client")
		os.Exit(1)
	}

	// Clean up sync finalizers
	// This logic should be disabled if OPA is run as a sidecar
	syncCleaned := make(chan struct{})
	go configController.TearDownState(cli, syncCleaned)

	// Clean up constraint finalizers
	templatesCleaned := make(chan struct{})
	go constrainttemplate.TearDownState(cli, templatesCleaned)

	<-syncCleaned
	<-templatesCleaned
	setupLog.Info("state cleaned")
	if hadError {
		os.Exit(1)
	}
}

func setLoggerForProduction() {
	sink := zapcore.AddSync(os.Stderr)
	var opts []zap.Option
	encCfg := zap.NewProductionEncoderConfig()
	enc := zapcore.NewJSONEncoder(encCfg)
	lvl := zap.NewAtomicLevelAt(zap.WarnLevel)
	opts = append(opts, zap.AddStacktrace(zap.ErrorLevel),
		zap.WrapCore(func(core zapcore.Core) zapcore.Core {
			return zapcore.NewSampler(core, time.Second, 100, 100)
		}))
	opts = append(opts, zap.AddCallerSkip(1), zap.ErrorOutput(sink))
	zlog := zap.New(zapcore.NewCore(&crzap.KubeAwareEncoder{Encoder: enc, Verbose: false}, sink, lvl))
	zlog = zlog.WithOptions(opts...)
	newlogger := zapr.NewLogger(zlog)
	ctrl.SetLogger(newlogger)
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"fmt"
	"log"
	"net"
	"os"

	toolkitversion "github.com/serulian/compiler/version"
	"github.com/serulian/serulian-langserver/handler"
	"github.com/serulian/serulian-langserver/version"

	"github.com/sourcegraph/jsonrpc2"
	"github.com/spf13/cobra"
)

const (
	tcpMode   = "tcp"
	stdioMode = "stdio"
)

var (
	mode                      string
	debug                     bool
	addr                      string
	entrypointSourceFile      string
	vcsDevelopmentDirectories []string
)

func main() {
	var cmdRun = &cobra.Command{
		Use:   "run",
		Short: "Runs the Serulian language server",
		Long:  `Runs the Serulian language server`,
		Run: func(cmd *cobra.Command, args []string) {
			run()
		},
	}

	cmdRun.PersistentFlags().StringVar(&addr, "addr", ":4389", "The address at which the language server will be served")
	cmdRun.PersistentFlags().StringVar(&mode, "mode", stdioMode, "The communication mode under which the language server will be served (tcp|stdio)")
	cmdRun.PersistentFlags().StringVar(&entrypointSourceFile, "entrypointSourceFile", "", "The entrypoint source file for the project (optional)")
	cmdRun.PersistentFlags().StringSliceVar(&vcsDevelopmentDirectories, "vcs-dev-dir", []string{},
		"If specified, VCS packages without specification will be first checked against this path")

	var cmdVersion = &cobra.Command{
		Use:   "version",
		Short: "Displays the version of the Serulian language server",
		Long:  `Displays the version of the Serulian language server`,
		Run: func(cmd *cobra.Command, args []string) {
			fmt.Printf("Serulian Language Server\n\n")

			fmt.Printf("Toolkit Version: %s\n\n", toolkitversion.DescriptiveVersion())

			fmt.Printf("Language Server SHA: %s\n", version.GitSHA)
			fmt.Printf("Toolkit SHA: %s\n", toolkitversion.GitSHA)
		},
	}

	// Register the root command.
	var rootCmd = &cobra.Command{
		Use:   "langserver",
		Short: "Serulian Language Server",
		Long:  fmt.Sprintf("Serulian Language Server (Version %s, SHA %s)", toolkitversion.DescriptiveVersion(), version.GitSHA),
	}

	rootCmd.AddCommand(cmdRun)
	rootCmd.AddCommand(cmdVersion)
	rootCmd.PersistentFlags().BoolVar(&debug, "debug", false, "If set to true, will print debug logs")
	rootCmd.Execute()
}

func run() error {
	var connOptions []jsonrpc2.ConnOpt
	if debug {
		log.SetOutput(os.Stderr)
		log.Println("Debug mode enabled")
		connOptions = append(connOptions, jsonrpc2.LogMessages(log.New(os.Stderr, "", 0)))
	}

	handler := handler.NewHandler(entrypointSourceFile, vcsDevelopmentDirectories)
	if mode == stdioMode {
		log.Printf("Serulian language server running under STDIO mode\n")
		<-jsonrpc2.NewConn(context.Background(), jsonrpc2.NewBufferedStream(stdrwc{}, jsonrpc2.VSCodeObjectCodec{}), handler, connOptions...).DisconnectNotify()
		return nil
	}

	listener, err := net.Listen("tcp", addr)
	if err != nil {
		if debug {
			log.Printf("Got error when trying to start: %v\n", err)
		}
		return err
	}
	defer listener.Close()

	log.Printf("Serulian language server running under TCP at %s\n", addr)
	for {
		conn, err := listener.Accept()
		if err != nil {
			return err
		}
		jsonrpc2.NewConn(context.Background(), jsonrpc2.NewBufferedStream(conn, jsonrpc2.VSCodeObjectCodec{}), handler, connOptions...)
	}
}

// Note: Based on https://github.com/sourcegraph/go-langserver/blob/master/main.go
type stdrwc struct{}

func (stdrwc) Read(p []byte) (int, error) {
	return os.Stdin.Read(p)
}

func (stdrwc) Write(p []byte) (int, error) {
	return os.Stdout.Write(p)
}

func (stdrwc) Close() error {
	if err := os.Stdin.Close(); err != nil {
		return err
	}
	return os.Stdout.Close()
}
<commit_msg>Add profile flag to serulian lang server<commit_after>package main

import (
	"context"
	"fmt"
	"log"
	"net"
	"os"

	goprofile "github.com/pkg/profile"

	toolkitversion "github.com/serulian/compiler/version"
	"github.com/serulian/serulian-langserver/handler"
	"github.com/serulian/serulian-langserver/version"

	"github.com/sourcegraph/jsonrpc2"
	"github.com/spf13/cobra"
)

const (
	tcpMode   = "tcp"
	stdioMode = "stdio"
)

var (
	mode                      string
	debug                     bool
	profile                   bool
	addr                      string
	entrypointSourceFile      string
	vcsDevelopmentDirectories []string
)

func main() {
	var cmdRun = &cobra.Command{
		Use:   "run",
		Short: "Runs the Serulian language server",
		Long:  `Runs the Serulian language server`,
		Run: func(cmd *cobra.Command, args []string) {
			if profile {
				defer goprofile.Start(goprofile.CPUProfile).Stop()
			}

			run()
		},
	}

	cmdRun.PersistentFlags().StringVar(&addr, "addr", ":4389", "The address at which the language server will be served")
	cmdRun.PersistentFlags().StringVar(&mode, "mode", stdioMode, "The communication mode under which the language server will be served (tcp|stdio)")
	cmdRun.PersistentFlags().StringVar(&entrypointSourceFile, "entrypointSourceFile", "", "The entrypoint source file for the project (optional)")
	cmdRun.PersistentFlags().StringSliceVar(&vcsDevelopmentDirectories, "vcs-dev-dir", []string{},
		"If specified, VCS packages without specification will be first checked against this path")

	var cmdVersion = &cobra.Command{
		Use:   "version",
		Short: "Displays the version of the Serulian language server",
		Long:  `Displays the version of the Serulian language server`,
		Run: func(cmd *cobra.Command, args []string) {
			fmt.Printf("Serulian Language Server\n\n")

			fmt.Printf("Toolkit Version: %s\n\n", toolkitversion.DescriptiveVersion())

			fmt.Printf("Language Server SHA: %s\n", version.GitSHA)
			fmt.Printf("Toolkit SHA: %s\n", toolkitversion.GitSHA)
		},
	}

	// Register the root command.
	var rootCmd = &cobra.Command{
		Use:   "langserver",
		Short: "Serulian Language Server",
		Long:  fmt.Sprintf("Serulian Language Server (Version %s, SHA %s)", toolkitversion.DescriptiveVersion(), version.GitSHA),
	}

	rootCmd.AddCommand(cmdRun)
	rootCmd.AddCommand(cmdVersion)
	rootCmd.PersistentFlags().BoolVar(&debug, "debug", false, "If set to true, will print debug logs")
	rootCmd.PersistentFlags().BoolVar(&profile, "profile", false, "If set to true, the language server will be profiled")
	rootCmd.Execute()
}

func run() error {
	var connOptions []jsonrpc2.ConnOpt
	if debug {
		log.SetOutput(os.Stderr)
		log.Println("Debug mode enabled")
		connOptions = append(connOptions, jsonrpc2.LogMessages(log.New(os.Stderr, "", 0)))
	}

	handler := handler.NewHandler(entrypointSourceFile, vcsDevelopmentDirectories)
	if mode == stdioMode {
		log.Printf("Serulian language server running under STDIO mode\n")
		<-jsonrpc2.NewConn(context.Background(), jsonrpc2.NewBufferedStream(stdrwc{}, jsonrpc2.VSCodeObjectCodec{}), handler, connOptions...).DisconnectNotify()
		return nil
	}

	listener, err := net.Listen("tcp", addr)
	if err != nil {
		if debug {
			log.Printf("Got error when trying to start: %v\n", err)
		}
		return err
	}
	defer listener.Close()

	log.Printf("Serulian language server running under TCP at %s\n", addr)
	for {
		conn, err := listener.Accept()
		if err != nil {
			return err
		}
		jsonrpc2.NewConn(context.Background(), jsonrpc2.NewBufferedStream(conn, jsonrpc2.VSCodeObjectCodec{}), handler, connOptions...)
	}
}

// Note: Based on https://github.com/sourcegraph/go-langserver/blob/master/main.go
type stdrwc struct{}

func (stdrwc) Read(p []byte) (int, error) {
	return os.Stdin.Read(p)
}

func (stdrwc) Write(p []byte) (int, error) {
	return os.Stdout.Write(p)
}

func (stdrwc) Close() error {
	if err := os.Stdin.Close(); err != nil {
		return err
	}
	return os.Stdout.Close()
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/hex"
	"flag"
	"fmt"
	"log"
	"os"
	"os/signal"
	"os/user"
	"path/filepath"
	"runtime/pprof"

	"github.com/rakoo/rakoshare/pkg/id"
	"github.com/rakoo/rakoshare/pkg/sharesession"
)

var (
	cpuprofile = flag.String("cpuprofile", "", "If not empty, collects CPU profile samples and writes the profile to the given file before the program exits")
	memprofile = flag.String("memprofile", "", "If not empty, writes memory heap allocations to the given file before the program exits")
	idstring   = flag.String("id", "", "The id of the share")
	generate   = flag.Bool("gen", false, "If true, generate a 3-tuple of ids")
)

var torrent string

func main() {
	flag.Usage = usage
	flag.Parse()

	if *generate {
		tmpId, err := id.New()
		if err != nil {
			log.Fatal(err)
		}
		fmt.Printf("WriteReadStore:\t%s\n     ReadStore:\t%s\n         Store:\t%s\n",
			tmpId.WRS(), tmpId.RS(), tmpId.S())
		return
	}

	if *idstring == "" {
		fmt.Println("Missing a share id")
		usage()
		os.Exit(2)
	}
	shareID, err := id.NewFromString(*idstring)
	if err != nil {
		log.Fatal(err)
	}
	if shareID.CanWrite() {
		log.Printf("WriteReadStore: %s\n", shareID.WRS())
	}
	if shareID.CanRead() {
		log.Printf("ReadStore: %s\n", shareID.RS())
	}
	log.Printf("Store: %s\n", shareID.S())

	if flag.NArg() != 0 {
		log.Println("Don't want arguments")
		usage()
	}

	if *cpuprofile != "" {
		cpuf, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(cpuf)
		defer pprof.StopCPUProfile()
	}

	if *memprofile != "" {
		defer func(file string) {
			memf, err := os.Create(file)
			if err != nil {
				log.Fatal(err)
			}
			pprof.WriteHeapProfile(memf)
		}(*memprofile)
	}

	// Working directory, where all transient stuff happens
	u, err := user.Current()
	if err != nil {
		log.Fatal("Couldn't watch dir: ", err)
	}
	pathArgs := []string{u.HomeDir, ".local", "share", "rakoshare"}
	workDir := filepath.Join(pathArgs...)
	sessionName := hex.EncodeToString(shareID.Infohash) + ".sql"
	session, err := sharesession.New(filepath.Join(workDir, sessionName))
	if err != nil {
		log.Fatal("Couldn't open session file: ", err)
	}

	// Watcher
	if fileDir == "." {
		fmt.Println("fileDir option is missing")
		flag.Usage()
	}
	_, err = os.Stat(fileDir)
	if err != nil {
		fmt.Printf("%s is an invalid dir: %s\n", fileDir, err)
		os.Exit(1)
	}
	watcher, err := NewWatcher(session, filepath.Clean(fileDir), shareID.CanWrite())
	if err != nil {
		log.Fatal("Couldn't start watcher: ", err)
	}

	log.Println("Starting.")

	// External listener
	conChan, listenPort, err := listenForPeerConnections([]byte(shareID.Psk[:]))
	if err != nil {
		log.Fatal("Couldn't listen for peers connection: ", err)
	}

	var currentSession TorrentSessionI = EmptyTorrent{}

	// quitChan
	quitChan := listenSigInt()

	// LPD
	lpd := &Announcer{announces: make(chan *Announce)}
	if *useLPD {
		lpd, err = NewAnnouncer(listenPort)
		if err != nil {
			log.Fatal("Couldn't listen for Local Peer Discoveries: ", err)
		}
	}

	// Control session
	controlSession, err := NewControlSession(shareID, listenPort, session)
	if err != nil {
		log.Fatal(err)
	}
	if *useLPD {
		lpd.Announce(string(shareID.Infohash))
	}

mainLoop:
	for {
		select {
		case <-quitChan:
			err := currentSession.Quit()
			if err != nil {
				log.Println("Failed: ", err)
			} else {
				log.Println("Done")
			}
			break mainLoop
		case c := <-conChan:
			if currentSession.Matches(c.infohash) {
				currentSession.AcceptNewPeer(c)
			} else if controlSession.Matches(c.infohash) {
				controlSession.AcceptNewPeer(c)
			}
		case announce := <-lpd.announces:
			hexhash, err := hex.DecodeString(announce.infohash)
			if err != nil {
				log.Println("Err with hex-decoding:", err)
				break
			}
			if controlSession.Matches(string(hexhash)) {
				controlSession.hintNewPeer(announce.peer)
			}
		case ih := <-watcher.PingNewTorrent:
			if ih == controlSession.currentIH && !currentSession.IsEmpty() {
				break
			}

			controlSession.SetCurrent(ih)

			currentSession.Quit()

			torrentFile := session.GetCurrentTorrent()
			tentativeSession, err := NewTorrentSession(shareID, torrentFile, listenPort)
			if err != nil {
				log.Println("Couldn't start new session from watched dir: ", err)

				// Fallback to an emptytorrent, because the previous one is
				// invalid; hope it will be ok next time !
				currentSession = EmptyTorrent{}
				break
			}
			currentSession = tentativeSession
			go currentSession.DoTorrent()
			for _, peer := range controlSession.peers {
				currentSession.hintNewPeer(peer.address)
			}
		case announce := <-controlSession.Torrents:
			controlSession.SetCurrent(announce.infohash)

			currentSession.Quit()

			magnet := fmt.Sprintf("magnet:?xt=urn:btih:%x", announce.infohash)
			tentativeSession, err := NewTorrentSession(shareID, magnet, listenPort)
			if err != nil {
				log.Println("Couldn't start new session from announce: ", err)
				currentSession = EmptyTorrent{}
				break
			}
			currentSession = tentativeSession
			go currentSession.DoTorrent()
			currentSession.hintNewPeer(announce.peer)
		case peer := <-controlSession.NewPeers:
			if currentSession.IsEmpty() {
				magnet := fmt.Sprintf("magnet:?xt=urn:btih:%x", controlSession.currentIH)
				tentativeSession, err := NewTorrentSession(shareID, magnet, listenPort)
				if err != nil {
					log.Printf("Couldn't start new session with new peer: %s\n", err)
					break
				}
				currentSession = tentativeSession
				go currentSession.DoTorrent()
			}
			currentSession.hintNewPeer(peer)
		case meta := <-currentSession.NewMetaInfo():
			watcher.saveMetainfo(meta)
		}
	}
}

type EmptyTorrent struct{}

func (et EmptyTorrent) Quit() error                 { return nil }
func (et EmptyTorrent) Matches(ih string) bool      { return false }
func (et EmptyTorrent) AcceptNewPeer(btc *btConn)   {}
func (et EmptyTorrent) DoTorrent()                  {}
func (et EmptyTorrent) hintNewPeer(peer string)     {}
func (et EmptyTorrent) IsEmpty() bool               { return true }
func (et EmptyTorrent) NewMetaInfo() chan *MetaInfo { return nil }

func usage() {
	log.Printf("usage: Taipei-Torrent [options] (torrent-file | torrent-url)")

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

func listenSigInt() chan os.Signal {
	c := make(chan os.Signal)
	signal.Notify(c, os.Interrupt, os.Kill)
	return c
}
<commit_msg>Create target directory if it doesn't already exist<commit_after>package main

import (
	"encoding/hex"
	"flag"
	"fmt"
	"log"
	"os"
	"os/signal"
	"os/user"
	"path/filepath"
	"runtime/pprof"

	"github.com/rakoo/rakoshare/pkg/id"
	"github.com/rakoo/rakoshare/pkg/sharesession"
)

var (
	cpuprofile = flag.String("cpuprofile", "", "If not empty, collects CPU profile samples and writes the profile to the given file before the program exits")
	memprofile = flag.String("memprofile", "", "If not empty, writes memory heap allocations to the given file before the program exits")
	idstring   = flag.String("id", "", "The id of the share")
	generate   = flag.Bool("gen", false, "If true, generate a 3-tuple of ids")
)

var torrent string

func main() {
	flag.Usage = usage
	flag.Parse()

	if *generate {
		tmpId, err := id.New()
		if err != nil {
			log.Fatal(err)
		}
		fmt.Printf("WriteReadStore:\t%s\n     ReadStore:\t%s\n         Store:\t%s\n",
			tmpId.WRS(), tmpId.RS(), tmpId.S())
		return
	}

	if *idstring == "" {
		fmt.Println("Missing a share id")
		usage()
		os.Exit(2)
	}
	shareID, err := id.NewFromString(*idstring)
	if err != nil {
		log.Fatal(err)
	}
	if shareID.CanWrite() {
		log.Printf("WriteReadStore: %s\n", shareID.WRS())
	}
	if shareID.CanRead() {
		log.Printf("ReadStore: %s\n", shareID.RS())
	}
	log.Printf("Store: %s\n", shareID.S())

	if flag.NArg() != 0 {
		log.Println("Don't want arguments")
		usage()
	}

	if *cpuprofile != "" {
		cpuf, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(cpuf)
		defer pprof.StopCPUProfile()
	}

	if *memprofile != "" {
		defer func(file string) {
			memf, err := os.Create(file)
			if err != nil {
				log.Fatal(err)
			}
			pprof.WriteHeapProfile(memf)
		}(*memprofile)
	}

	// Working directory, where all transient stuff happens
	u, err := user.Current()
	if err != nil {
		log.Fatal("Couldn't watch dir: ", err)
	}
	pathArgs := []string{u.HomeDir, ".local", "share", "rakoshare"}
	workDir := filepath.Join(pathArgs...)
	sessionName := hex.EncodeToString(shareID.Infohash) + ".sql"
	session, err := sharesession.New(filepath.Join(workDir, sessionName))
	if err != nil {
		log.Fatal("Couldn't open session file: ", err)
	}

	// Watcher
	if fileDir == "." {
		fmt.Println("fileDir option is missing")
		flag.Usage()
	}
	_, err = os.Stat(fileDir)
	if err != nil {
		if os.IsNotExist(err) {
			os.MkdirAll(fileDir, 0744)
		} else {
			fmt.Printf("%s is an invalid dir: %s\n", fileDir, err)
			os.Exit(1)
		}
	}
	watcher, err := NewWatcher(session, filepath.Clean(fileDir), shareID.CanWrite())
	if err != nil {
		log.Fatal("Couldn't start watcher: ", err)
	}

	log.Println("Starting.")

	// External listener
	conChan, listenPort, err := listenForPeerConnections([]byte(shareID.Psk[:]))
	if err != nil {
		log.Fatal("Couldn't listen for peers connection: ", err)
	}

	var currentSession TorrentSessionI = EmptyTorrent{}

	// quitChan
	quitChan := listenSigInt()

	// LPD
	lpd := &Announcer{announces: make(chan *Announce)}
	if *useLPD {
		lpd, err = NewAnnouncer(listenPort)
		if err != nil {
			log.Fatal("Couldn't listen for Local Peer Discoveries: ", err)
		}
	}

	// Control session
	controlSession, err := NewControlSession(shareID, listenPort, session)
	if err != nil {
		log.Fatal(err)
	}
	if *useLPD {
		lpd.Announce(string(shareID.Infohash))
	}

mainLoop:
	for {
		select {
		case <-quitChan:
			err := currentSession.Quit()
			if err != nil {
				log.Println("Failed: ", err)
			} else {
				log.Println("Done")
			}
			break mainLoop
		case c := <-conChan:
			if currentSession.Matches(c.infohash) {
				currentSession.AcceptNewPeer(c)
			} else if controlSession.Matches(c.infohash) {
				controlSession.AcceptNewPeer(c)
			}
		case announce := <-lpd.announces:
			hexhash, err := hex.DecodeString(announce.infohash)
			if err != nil {
				log.Println("Err with hex-decoding:", err)
				break
			}
			if controlSession.Matches(string(hexhash)) {
				controlSession.hintNewPeer(announce.peer)
			}
		case ih := <-watcher.PingNewTorrent:
			if ih == controlSession.currentIH && !currentSession.IsEmpty() {
				break
			}

			controlSession.SetCurrent(ih)

			currentSession.Quit()

			torrentFile := session.GetCurrentTorrent()
			tentativeSession, err := NewTorrentSession(shareID, torrentFile, listenPort)
			if err != nil {
				log.Println("Couldn't start new session from watched dir: ", err)

				// Fallback to an emptytorrent, because the previous one is
				// invalid; hope it will be ok next time !
				currentSession = EmptyTorrent{}
				break
			}
			currentSession = tentativeSession
			go currentSession.DoTorrent()
			for _, peer := range controlSession.peers {
				currentSession.hintNewPeer(peer.address)
			}
		case announce := <-controlSession.Torrents:
			controlSession.SetCurrent(announce.infohash)

			currentSession.Quit()

			magnet := fmt.Sprintf("magnet:?xt=urn:btih:%x", announce.infohash)
			tentativeSession, err := NewTorrentSession(shareID, magnet, listenPort)
			if err != nil {
				log.Println("Couldn't start new session from announce: ", err)
				currentSession = EmptyTorrent{}
				break
			}
			currentSession = tentativeSession
			go currentSession.DoTorrent()
			currentSession.hintNewPeer(announce.peer)
		case peer := <-controlSession.NewPeers:
			if currentSession.IsEmpty() {
				magnet := fmt.Sprintf("magnet:?xt=urn:btih:%x", controlSession.currentIH)
				tentativeSession, err := NewTorrentSession(shareID, magnet, listenPort)
				if err != nil {
					log.Printf("Couldn't start new session with new peer: %s\n", err)
					break
				}
				currentSession = tentativeSession
				go currentSession.DoTorrent()
			}
			currentSession.hintNewPeer(peer)
		case meta := <-currentSession.NewMetaInfo():
			watcher.saveMetainfo(meta)
		}
	}
}

type EmptyTorrent struct{}

func (et EmptyTorrent) Quit() error                 { return nil }
func (et EmptyTorrent) Matches(ih string) bool      { return false }
func (et EmptyTorrent) AcceptNewPeer(btc *btConn)   {}
func (et EmptyTorrent) DoTorrent()                  {}
func (et EmptyTorrent) hintNewPeer(peer string)     {}
func (et EmptyTorrent) IsEmpty() bool               { return true }
func (et EmptyTorrent) NewMetaInfo() chan *MetaInfo { return nil }

func usage() {
	log.Printf("usage: Taipei-Torrent [options] (torrent-file | torrent-url)")

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

func listenSigInt() chan os.Signal {
	c := make(chan os.Signal)
	signal.Notify(c, os.Interrupt, os.Kill)
	return c
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"
	"runtime"

	"github.com/jobtalk/pnzr/subcmd/deploy"
	"github.com/jobtalk/pnzr/vars"
	"github.com/mitchellh/cli"
	"github.com/jobtalk/pnzr/subcmd/vault"
	"github.com/jobtalk/pnzr/subcmd/update"
	"github.com/jobtalk/pnzr/subcmd/vault_edit"
	"github.com/jobtalk/pnzr/subcmd/vault_view"
)

var (
	VERSION    string
	BUILD_DATE string
	BUILD_OS   string
)

func generateBuildInfo() string {
	ret := fmt.Sprintf("Build version: %s\n", VERSION)
	ret += fmt.Sprintf("Go version: %s\n", runtime.Version())
	ret += fmt.Sprintf("Build Date: %s\n", BUILD_DATE)
	ret += fmt.Sprintf("Build OS: %s\n", BUILD_OS)
	return ret
}

func init() {
	if VERSION == "" {
		VERSION = "unknown"
	}
	vars.VERSION = VERSION
	vars.BUILD_DATE = BUILD_DATE
	vars.BUILD_OS = BUILD_OS

	VERSION = generateBuildInfo()
	log.SetFlags(log.Llongfile)

}

func main() {
	c := cli.NewCLI("pnzr", VERSION)
	c.Args = os.Args[1:]
	c.Commands = map[string]cli.CommandFactory{
		"deploy": func() (cli.Command, error) {
			return &deploy.Deploy{}, nil
		},
		"vault": func() (cli.Command, error) {
			return &vault.Vault{}, nil
		},
		"update": func() (cli.Command, error) {
			return &update.Update{}, nil
		},
		"vault-edit": func() (cli.Command, error) {
			return &vedit.VaultEdit{}, nil
		},
		"vault-view": func() (cli.Command, error) {
			return &vview.VaultView{}, nil
		},
	}
	exitCode, err := c.Run()
	if err != nil {
		log.Fatalln(err)
	}
	os.Exit(exitCode)
}
<commit_msg>dotfileの読み込み設定<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"runtime"

	"github.com/jobtalk/pnzr/subcmd/deploy"
	"github.com/jobtalk/pnzr/vars"
	"github.com/mitchellh/cli"
	"github.com/jobtalk/pnzr/subcmd/vault"
	"github.com/jobtalk/pnzr/subcmd/update"
	"github.com/jobtalk/pnzr/subcmd/vault_edit"
	"github.com/jobtalk/pnzr/subcmd/vault_view"
	"github.com/joho/godotenv"
)

var (
	VERSION    string
	BUILD_DATE string
	BUILD_OS   string
)

func generateBuildInfo() string {
	ret := fmt.Sprintf("Build version: %s\n", VERSION)
	ret += fmt.Sprintf("Go version: %s\n", runtime.Version())
	ret += fmt.Sprintf("Build Date: %s\n", BUILD_DATE)
	ret += fmt.Sprintf("Build OS: %s\n", BUILD_OS)
	return ret
}

func init() {
	if VERSION == "" {
		VERSION = "unknown"
	}
	vars.VERSION = VERSION
	vars.BUILD_DATE = BUILD_DATE
	vars.BUILD_OS = BUILD_OS

	VERSION = generateBuildInfo()
	log.SetFlags(log.Llongfile)
	godotenv.Load("~/.pnzr")
	godotenv.Load(".pnzr")
}

func main() {
	c := cli.NewCLI("pnzr", VERSION)
	c.Args = os.Args[1:]
	c.Commands = map[string]cli.CommandFactory{
		"deploy": func() (cli.Command, error) {
			return &deploy.Deploy{}, nil
		},
		"vault": func() (cli.Command, error) {
			return &vault.Vault{}, nil
		},
		"update": func() (cli.Command, error) {
			return &update.Update{}, nil
		},
		"vault-edit": func() (cli.Command, error) {
			return &vedit.VaultEdit{}, nil
		},
		"vault-view": func() (cli.Command, error) {
			return &vview.VaultView{}, nil
		},
	}
	exitCode, err := c.Run()
	if err != nil {
		log.Fatalln(err)
	}
	os.Exit(exitCode)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"io/ioutil"
	"log"
	"runtime"
	"strconv"
	"time"
)

// receive parameters
var (
	// project path:Must Be Relative path
	project = flag.String("p", "", "path of project.")
	// save path of report
	report = flag.String("d", "", "path of report.")
	// except packages,multiple packages are separated by semicolons
	except = flag.String("e", "", "except packages.")
	// meta information
	meta = flag.String("m", "{}", "project meta information.")
	// template
	tplpath = flag.String("t", "", "project meta information.")
	// report formate
	formate = flag.String("r", "", "project report formate(json/html).")
)

func init() {
	if runtime.GOOS == `windows` {
		system = `\`
	} else {
		system = `/`
	}
}

func main() {
	flag.Parse()
	log.SetPrefix("[Apollo]")
	if *project == "" {
		log.Fatal("The project path is not specified")
	}

	if *tplpath == "" {
		log.Fatal("The template path is not specified")
	} else {
		fileData, err := ioutil.ReadFile(*tplpath)
		if err != nil {
			log.Fatal(err)
		} else {
			tpl = string(fileData)
		}
	}

	if *report == "" {
		log.Println("The report path is not specified, and the current path is used by default")
	}

	if *except == "" {
		log.Println("There are no packages that are excepted, review all items of the package")
	}

	if *meta == "" {
		log.Println("There is no review of attribute information, using default settings")
	}

	startTime := strconv.FormatInt(time.Now().Unix(), 10)
	reporter := NewReporter()
	reporter.Engine(*project, *except)
	htmlData, err := reporter.Json2Html()
	if err != nil {
		log.Println("Json2Html error")
		return
	}
	if *formate == "json" {
		reporter.SaveAsJson(*project, *report, startTime)
	} else {
		reporter.SaveAsHtml(htmlData, *project, *report, startTime)
	}
}
<commit_msg>add index<commit_after>package main

import (
	"flag"
	"io/ioutil"
	"log"
	"runtime"
	"strconv"
	"time"
)

// receive parameters
var (
	// project path:Must Be Relative path
	project = flag.String("p", "", "path of project.")
	// save path of report
	report = flag.String("d", "", "path of report.")
	// except packages,multiple packages are separated by semicolons
	except = flag.String("e", "", "except packages.")
	// template
	tplpath = flag.String("t", "", "project meta information.")
	// report formate
	formate = flag.String("r", "", "project report formate(json/html).")
)

func init() {
	if runtime.GOOS == `windows` {
		system = `\`
	} else {
		system = `/`
	}
}

func main() {
	flag.Parse()
	log.SetPrefix("[Apollo]")
	if *project == "" {
		log.Fatal("The project path is not specified")
	}

	if *tplpath == "" {
		log.Fatal("The template path is not specified")
	} else {
		fileData, err := ioutil.ReadFile(*tplpath)
		if err != nil {
			log.Fatal(err)
		} else {
			tpl = string(fileData)
		}
	}

	if *report == "" {
		log.Println("The report path is not specified, and the current path is used by default")
	}

	if *except == "" {
		log.Println("There are no packages that are excepted, review all items of the package")
	}

	startTime := strconv.FormatInt(time.Now().Unix(), 10)
	reporter := NewReporter()
	reporter.Engine(*project, *except)
	htmlData, err := reporter.Json2Html()
	if err != nil {
		log.Println("Json2Html error")
		return
	}
	if *formate == "json" {
		reporter.SaveAsJson(*project, *report, startTime)
	} else {
		reporter.SaveAsHtml(htmlData, *project, *report, startTime)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/pranavraja/refactor/src/refactor"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"regexp"
	"strings"
)

func walk(root string, suffix string, filePaths chan<- string) {
	defer close(filePaths)
	entries, err := ioutil.ReadDir(root)
	if err != nil {
		return
	}
	for _, file := range entries {
		if strings.HasPrefix(file.Name(), ".") {
			continue // Ignore hidden files
		}
		fullPath := path.Join(root, file.Name())
		if file.IsDir() {
			nestedFilePaths := make(chan string)
			go walk(fullPath, suffix, nestedFilePaths)
			for f := range nestedFilePaths {
				filePaths <- f
			}
		} else {
            if strings.HasSuffix(fullPath, suffix) {
                filePaths <- fullPath
            }
		}
	}
}

func patchAll(filenames <-chan string, find *regexp.Regexp, replace string, patches chan<- refactor.Patch, proceed <-chan bool) {
	defer close(patches)
	for filename := range filenames {
		f, err := os.Open(filename)
		if err != nil {
			continue
		}
		contents, err := ioutil.ReadAll(f)
		f.Close()
		if err != nil {
			continue
		}
		filePatches := make(chan refactor.Patch)
		patcherCanProceed := make(chan bool)
		fileResult := make(chan string)
		go refactor.Patcher(string(contents), find, replace, filePatches, patcherCanProceed, fileResult)
		for patch := range filePatches {
			patch.Filename = filename
			patches <- patch
			patcherCanProceed <- <-proceed
		}
		r, changed := <-fileResult
		if changed {
			ioutil.WriteFile(filename, []byte(r), 0) // Assume file already exists
		}
	}
}

func main() {
	if len(os.Args) <= 3 {
        println("Example: refactor .rb require import\n  Replaces 'require' with 'import' in all .rb files")
		return
	}
    suffix := os.Args[1]
	find := regexp.MustCompile(os.Args[2])
	replace := os.Args[3]
	patches := make(chan refactor.Patch)
	proceed := make(chan bool)

	paths := make(chan string)
	go walk(".", suffix, paths)
	go patchAll(paths, find, replace, patches, proceed)
	var canProceed bool
	for p := range patches {
		fmt.Printf("%v\n", p)
		if !canProceed {
			fmt.Printf("Continue? (y/n[default]): ")
			var input rune
			_, err := fmt.Scanf("%c", &input)
			if input == 'y' {
				canProceed = true
			}
			if err != nil {
				fmt.Printf("%v", err)
				return
			}
			if !canProceed {
				return
			}
		}
		proceed <- true
	}
}
<commit_msg>Added basic pretty-printing of patches<commit_after>package main

import (
	"fmt"
	"github.com/pranavraja/refactor/src/refactor"
	"github.com/vrischmann/termcolor"
	"io"
	"io/ioutil"
	"os"
	"path"
	"regexp"
	"strings"
)

func walk(root string, suffix string, filePaths chan<- string) {
	defer close(filePaths)
	entries, err := ioutil.ReadDir(root)
	if err != nil {
		return
	}
	for _, file := range entries {
		if strings.HasPrefix(file.Name(), ".") {
			continue // Ignore hidden files
		}
		fullPath := path.Join(root, file.Name())
		if file.IsDir() {
			nestedFilePaths := make(chan string)
			go walk(fullPath, suffix, nestedFilePaths)
			for f := range nestedFilePaths {
				filePaths <- f
			}
		} else {
			if strings.HasSuffix(fullPath, suffix) {
				filePaths <- fullPath
			}
		}
	}
}

func patchAll(filenames <-chan string, find *regexp.Regexp, replace string, patches chan<- refactor.Patch, proceed <-chan bool) {
	defer close(patches)
	for filename := range filenames {
		f, err := os.Open(filename)
		if err != nil {
			continue
		}
		contents, err := ioutil.ReadAll(f)
		f.Close()
		if err != nil {
			continue
		}
		filePatches := make(chan refactor.Patch)
		patcherCanProceed := make(chan bool)
		fileResult := make(chan string)
		go refactor.Patcher(string(contents), find, replace, filePatches, patcherCanProceed, fileResult)
		for patch := range filePatches {
			patch.Filename = filename
			patches <- patch
			patcherCanProceed <- <-proceed
		}
		r, changed := <-fileResult
		if changed {
			ioutil.WriteFile(filename, []byte(r), 0) // Assume file already exists
		}
	}
}

func prettyPrint(patch refactor.Patch, out io.Writer) {
	fmt.Fprintf(out, "%s\n %s\n %s\n", termcolor.Colored(patch.Filename, termcolor.Cyan), termcolor.Colored("-"+patch.Before, termcolor.Red), termcolor.Colored("+"+patch.After, termcolor.Green))
}

func main() {
	if len(os.Args) <= 3 {
		println("Example: refactor .rb require import\n  Replaces 'require' with 'import' in all .rb files")
		return
	}
	suffix := os.Args[1]
	find := regexp.MustCompile(os.Args[2])
	replace := os.Args[3]
	patches := make(chan refactor.Patch)
	proceed := make(chan bool)

	paths := make(chan string)
	go walk(".", suffix, paths)
	go patchAll(paths, find, replace, patches, proceed)
	var canProceed bool
	for p := range patches {
		prettyPrint(p, os.Stdout)
		if !canProceed {
			fmt.Printf("Continue? (y/n[default]): ")
			var input rune
			_, err := fmt.Scanf("%c", &input)
			if input == 'y' {
				canProceed = true
			}
			if err != nil {
				fmt.Printf("%v", err)
				return
			}
			if !canProceed {
				return
			}
		}
		proceed <- true
	}
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"os"
	"os/signal"
	"sync"

	"github.com/Shopify/sarama"
)

func main() {

	consumerBrokers := []string{"kafka-broker-01.ana.kochava.com:9092", "kafka-broker-02.ana.kochava.com:9092", "kafka-broker-03.ana.kochava.com:9092"}
	producerBrokers := []string{"analytics-kafka-v000-9lzw:9092", "analytics-kafka-v000-u40u:9092", "analytics-kafka-v000-wrdq:9092"}

	logFile, err := os.OpenFile("/var/log/firehose/firehose.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		log.Fatalln("Failed to open log file:", err)
	}
	defer logFile.Close()

	log.SetOutput(logFile)

	metricsFile, err := os.OpenFile("/var/log/firehose/metrics.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		log.Fatalln("Failed to open log file:", err)
	}
	defer metricsFile.Close()

	log.Println("Getting the Kafka consumer")
	consumer, err := GetKafkaConsumer(consumerBrokers, metricsFile)
	if err != nil {
		log.Println("Unable to create consumer", err)
	}

	log.Println("Getting the Kafka producer")
	producer, err := GetKafkaProducer(producerBrokers, metricsFile)
	if err != nil {
		log.Println("Unable to create producer", err)
	}

	defer CloseConsumer(consumer)
	defer CloseProducer(producer)

	signals := make(chan os.Signal, 1)
	signal.Notify(signals, os.Interrupt)

	var wg sync.WaitGroup

	topic := "events"

	for partition := 0; partition < 24; partition++ {
		transferChan := make(chan sarama.ProducerMessage, 10000000)

		partitionConsumer, err := consumer.ConsumePartition(topic, int32(partition), sarama.OffsetNewest)
		if err != nil {
			panic(err)
		}

		wg.Add(2)

		go PullFromTopic(partitionConsumer, transferChan, signals, &wg)
		log.Println("Started consumer for partition ", partition)

		go PushToTopic(producer, transferChan, signals, &wg)
		log.Println("Started producer for partition ", partition)
	}

	wg.Wait()
}
<commit_msg>Use a single chan for transfer<commit_after>package main

import (
	"log"
	"os"
	"os/signal"
	"sync"

	"github.com/Shopify/sarama"
)

func main() {

	consumerBrokers := []string{"kafka-broker-01.ana.kochava.com:9092", "kafka-broker-02.ana.kochava.com:9092", "kafka-broker-03.ana.kochava.com:9092"}
	producerBrokers := []string{"analytics-kafka-v000-9lzw:9092", "analytics-kafka-v000-u40u:9092", "analytics-kafka-v000-wrdq:9092"}

	logFile, err := os.OpenFile("/var/log/firehose/firehose.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		log.Fatalln("Failed to open log file:", err)
	}
	defer logFile.Close()

	log.SetOutput(logFile)

	metricsFile, err := os.OpenFile("/var/log/firehose/metrics.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		log.Fatalln("Failed to open log file:", err)
	}
	defer metricsFile.Close()

	log.Println("Getting the Kafka consumer")
	consumer, err := GetKafkaConsumer(consumerBrokers, metricsFile)
	if err != nil {
		log.Println("Unable to create consumer", err)
	}

	log.Println("Getting the Kafka producer")
	producer, err := GetKafkaProducer(producerBrokers, metricsFile)
	if err != nil {
		log.Println("Unable to create producer", err)
	}

	defer CloseConsumer(consumer)
	defer CloseProducer(producer)

	signals := make(chan os.Signal, 1)
	signal.Notify(signals, os.Interrupt)

	var wg sync.WaitGroup

	topic := "events"

	transferChan := make(chan sarama.ProducerMessage, 100000)
	for partition := 0; partition < 24; partition++ {

		partitionConsumer, err := consumer.ConsumePartition(topic, int32(partition), sarama.OffsetNewest)
		if err != nil {
			panic(err)
		}

		wg.Add(2)

		go PullFromTopic(partitionConsumer, transferChan, signals, &wg)
		log.Println("Started consumer for partition ", partition)

		go PushToTopic(producer, transferChan, signals, &wg)
		log.Println("Started producer for partition ", partition)
	}

	go func() {
		log.Println(len(transferChan))
	}()

	wg.Wait()
}
<|endoftext|>