<commit_before>package main

import (
	"bytes"
	"log"
	"net/url"
	"regexp"
	"strings"

	"github.com/json-iterator/go"
	"github.com/valyala/fasthttp"
)

type replace interface {
	apply(data []byte) []byte
}

type regexReplace struct {
	regex       *regexp.Regexp
	replacement []byte
}

func newRegexReplace(regex, replace string) *regexReplace {
	return &regexReplace{
		regex:       regexp.MustCompile(regex),
		replacement: []byte(replace),
	}
}

func (v *regexReplace) apply(data []byte) []byte {
	return v.regex.ReplaceAll(data, v.replacement)
}

type stringReplace struct {
	needle      []byte
	replacement []byte
}

func newStringReplace(needle, replace string) *stringReplace {
	return &stringReplace{
		needle:      []byte(needle),
		replacement: []byte(replace),
	}
}

func (v *stringReplace) apply(data []byte) []byte {
	return bytes.Replace(data, v.needle, v.replacement, -1)
}

type DomainConfig struct {
	apiReplaces                []replace
	apiOfficialLongpollReplace replace
	apiLongpollReplace         replace
	siteHlsReplace             replace
}

// Constants
var (
	apiOfficialLongpollPath  = []byte("/method/execute")
	apiOfficialLongpollPath2 = []byte("/method/execute.imGetLongPollHistoryExtended")
	apiOfficialNewsfeedPath  = []byte("/method/execute.getNewsfeedSmart")
	apiLongpollPath          = []byte("/method/messages.getLongPollServer")
	apiNewsfeedGet           = []byte("/method/newsfeed.get")
	videoHlsPath             = []byte("/video_hls.php")
	atPath                   = []byte("/%40")
	awayPath                 = []byte("/away")
	https                    = []byte("https")
	apiHost                  = []byte("api.vk.com")
	siteHost                 = []byte("vk.com")
	siteHostRoot             = []byte(".vk.com")
)

var client = &fasthttp.Client{}
var domains = make(map[string]*DomainConfig)
var json = jsoniter.ConfigFastest

func getDomainConfig(domain string) *DomainConfig {
	cfg, ok := domains[domain]
	if !ok {
		cfg = &DomainConfig{}
		cfg.apiReplaces = []replace{
			newRegexReplace(`"https:\\/\\/(pu\.vk\.com|[-_a-zA-Z0-9]+\.(?:userapi\.com|vk-cdn\.net|vk\.me|vkuser(?:live|video|audio)\.(?:net|com)))\\/`, `"https:\/\/`+domain+`\/_\/$1\/`),
			newStringReplace(`"https:\/\/vk.com\/video_hls.php`, `"https:\/\/`+domain+`\/@vk.com\/video_hls.php`),
			newRegexReplace(`"https:\\/\\/vk\.com\\/(images\\/|doc-?[0-9]+_)`, `"https:\/\/`+domain+`\/_\/vk.com\/$1`),
		}
		cfg.apiOfficialLongpollReplace = newStringReplace(`"server":"api.vk.com\/newuim`, `"server":"`+domain+`\/_\/api.vk.com\/newuim`)
		cfg.apiLongpollReplace = newStringReplace(`"server":"`, `"server":"`+domain+`\/_\/`)
		cfg.siteHlsReplace = newRegexReplace(`https:\/\/([-_a-zA-Z0-9]+\.(?:userapi\.com|vk-cdn\.net|vk\.me|vkuser(?:live|video)\.(?:net|com)))\/`, `https://`+domain+`/_/$1/`)
		domains[domain] = cfg
	}
	return cfg
}

func reverseProxyHandler(ctx *fasthttp.RequestCtx) {
	defer func() {
		if r := recover(); r != nil {
			ctx.Logger().Printf("panic when proxying the request: %s", r)
			ctx.Response.Reset()
			ctx.SetStatusCode(500)
			ctx.SetBodyString("500 Internal Server Error")
		}
	}()

	var config *DomainConfig
	if Config.domain != "" {
		config = getDomainConfig(Config.domain)
	} else {
		config = getDomainConfig(string(ctx.Host()))
	}

	if !preRequest(ctx) {
		ctx.Response.SetStatusCode(400)
		ctx.Response.SetBodyString("400 Bad Request")
		return
	}

	// In case of redirect
	if ctx.Response.StatusCode() != 200 {
		trackRequest(ctx, 0)
		return
	}

	if err := client.Do(&ctx.Request, &ctx.Response); err != nil {
		ctx.Logger().Printf("error when proxying the request: %s", err)
		ctx.Response.Reset()
		if strings.Contains(err.Error(), "timed out") || strings.Contains(err.Error(), "timeout") {
			ctx.SetStatusCode(408)
			ctx.SetBodyString("408 Request Timeout")
		} else {
			ctx.SetStatusCode(500)
			ctx.SetBodyString("500 Internal Server Error")
		}
		trackRequest(ctx, 0)
	} else {
		postResponse(config, ctx)
	}
}

func preRequest(ctx *fasthttp.RequestCtx) bool {
	req := &ctx.Request
	path := req.RequestURI()
	if bytes.HasPrefix(path, atPath) {
		slashIndex := bytes.IndexRune(path[1:], '/')
		if slashIndex == -1 {
			return false
		}
		endpoint := []byte(path[4:slashIndex+1])
		if !bytes.Equal(endpoint, siteHost) && !bytes.HasSuffix(endpoint, siteHostRoot) {
			return false
		}
		req.Header.SetHostBytes(endpoint)
		req.SetRequestURIBytes([]byte(path[1+slashIndex:]))
	} else if bytes.HasPrefix(path, awayPath) {
		to := string(req.URI().QueryArgs().Peek("to"))
		if to == "" {
			return false
		}
		to, err := url.QueryUnescape(to)
		if err != nil {
			return false
		}
		ctx.Redirect(to, 301)
		return true
	} else {
		req.SetHostBytes(apiHost)
	}
	// After req.URI() call it is impossible to modify URI
	req.URI().SetSchemeBytes(https)
	req.Header.Del("Accept-Encoding")
	return true
}

func postResponse(config *DomainConfig, ctx *fasthttp.RequestCtx) {
	uri := ctx.Request.URI()
	res := &ctx.Response
	res.Header.Del("Set-Cookie")
	body := res.Body()

	if bytes.Equal(uri.Host(), siteHost) {
		if bytes.Equal(uri.Path(), videoHlsPath) {
			body = config.siteHlsReplace.apply(body)
		}
	} else {
		for _, replace := range config.apiReplaces {
			body = replace.apply(body)
		}

		// Replace longpoll server
		if bytes.Equal(uri.Path(), apiLongpollPath) {
			body = config.apiLongpollReplace.apply(body)
		} else

		// Replace longpoll server for official app
		if bytes.Equal(uri.Path(), apiOfficialLongpollPath) || bytes.Equal(uri.Path(), apiOfficialLongpollPath2) {
			body = config.apiOfficialLongpollReplace.apply(body)
		} else

		// Clear feed from SPAM
		if bytes.Equal(uri.Path(), apiOfficialNewsfeedPath) || bytes.Equal(uri.Path(), apiNewsfeedGet) {
			var parsed map[string]interface{}
			if err := json.Unmarshal(body, &parsed); err == nil {
				if parsed["response"] != nil {
					response := parsed["response"].(map[string]interface{})
					if response["items"] != nil {
						newItems, modified := filterFeed(response["items"].([]interface{}))
						if modified {
							response["items"] = newItems
							body, err = json.Marshal(parsed)
						}
					}
				}
			}
		}
	}
	res.SetBody(body)

	if Config.debug {
		log.Println(string(uri.Path()) + "\n" + string(body))
	}

	trackRequest(ctx, len(body))
}

func filterFeed(items []interface{}) ([]interface{}, bool) {
	removed := 0
	for i := len(items) - 1; i >= 0; i-- {
		post := items[i].(map[string]interface{})
		if post["type"] == "ads" || (post["type"] == "post" && post["marked_as_ads"] != nil && post["marked_as_ads"].(float64) == 1) {
			items[i] = items[len(items)-1]
			items[len(items)-1] = nil
			items = items[:len(items)-1]
			removed++
		}
	}
	if removed > 0 {
		newItems := make([]interface{}, len(items))
		copy(newItems, items)
		return newItems, true
	}
	return nil, false
}
<commit_msg>Еще один адрес для longpoll сервера<commit_after>package main

import (
	"bytes"
	"log"
	"net/url"
	"regexp"
	"strings"

	"github.com/json-iterator/go"
	"github.com/valyala/fasthttp"
)

type replace interface {
	apply(data []byte) []byte
}

type regexReplace struct {
	regex       *regexp.Regexp
	replacement []byte
}

func newRegexReplace(regex, replace string) *regexReplace {
	return &regexReplace{
		regex:       regexp.MustCompile(regex),
		replacement: []byte(replace),
	}
}

func (v *regexReplace) apply(data []byte) []byte {
	return v.regex.ReplaceAll(data, v.replacement)
}

type stringReplace struct {
	needle      []byte
	replacement []byte
}

func newStringReplace(needle, replace string) *stringReplace {
	return &stringReplace{
		needle:      []byte(needle),
		replacement: []byte(replace),
	}
}

func (v *stringReplace) apply(data []byte) []byte {
	return bytes.Replace(data, v.needle, v.replacement, -1)
}

type DomainConfig struct {
	apiReplaces                []replace
	apiOfficialLongpollReplace replace
	apiLongpollReplace         replace
	siteHlsReplace             replace
}

// Constants
var (
	apiOfficialLongpollPath  = []byte("/method/execute")
	apiOfficialLongpollPath2 = []byte("/method/execute.imGetLongPollHistoryExtended")
	apiOfficialLongpollPath3 = []byte("/method/execute.imLpInit")
	apiOfficialNewsfeedPath  = []byte("/method/execute.getNewsfeedSmart")
	apiLongpollPath          = []byte("/method/messages.getLongPollServer")
	apiNewsfeedGet           = []byte("/method/newsfeed.get")
	videoHlsPath             = []byte("/video_hls.php")
	atPath                   = []byte("/%40")
	awayPath                 = []byte("/away")
	https                    = []byte("https")
	apiHost                  = []byte("api.vk.com")
	siteHost                 = []byte("vk.com")
	siteHostRoot             = []byte(".vk.com")
)

var client = &fasthttp.Client{}
var domains = make(map[string]*DomainConfig)
var json = jsoniter.ConfigFastest

func getDomainConfig(domain string) *DomainConfig {
	cfg, ok := domains[domain]
	if !ok {
		cfg = &DomainConfig{}
		cfg.apiReplaces = []replace{
			newRegexReplace(`"https:\\/\\/(pu\.vk\.com|[-_a-zA-Z0-9]+\.(?:userapi\.com|vk-cdn\.net|vk\.me|vkuser(?:live|video|audio)\.(?:net|com)))\\/`, `"https:\/\/`+domain+`\/_\/$1\/`),
			newStringReplace(`"https:\/\/vk.com\/video_hls.php`, `"https:\/\/`+domain+`\/@vk.com\/video_hls.php`),
			newRegexReplace(`"https:\\/\\/vk\.com\\/(images\\/|doc-?[0-9]+_)`, `"https:\/\/`+domain+`\/_\/vk.com\/$1`),
		}
		cfg.apiOfficialLongpollReplace = newStringReplace(`"server":"api.vk.com\/newuim`, `"server":"`+domain+`\/_\/api.vk.com\/newuim`)
		cfg.apiLongpollReplace = newStringReplace(`"server":"`, `"server":"`+domain+`\/_\/`)
		cfg.siteHlsReplace = newRegexReplace(`https:\/\/([-_a-zA-Z0-9]+\.(?:userapi\.com|vk-cdn\.net|vk\.me|vkuser(?:live|video)\.(?:net|com)))\/`, `https://`+domain+`/_/$1/`)
		domains[domain] = cfg
	}
	return cfg
}

func reverseProxyHandler(ctx *fasthttp.RequestCtx) {
	defer func() {
		if r := recover(); r != nil {
			ctx.Logger().Printf("panic when proxying the request: %s", r)
			ctx.Response.Reset()
			ctx.SetStatusCode(500)
			ctx.SetBodyString("500 Internal Server Error")
		}
	}()

	var config *DomainConfig
	if Config.domain != "" {
		config = getDomainConfig(Config.domain)
	} else {
		config = getDomainConfig(string(ctx.Host()))
	}

	if !preRequest(ctx) {
		ctx.Response.SetStatusCode(400)
		ctx.Response.SetBodyString("400 Bad Request")
		return
	}

	// In case of redirect
	if ctx.Response.StatusCode() != 200 {
		trackRequest(ctx, 0)
		return
	}

	if err := client.Do(&ctx.Request, &ctx.Response); err != nil {
		ctx.Logger().Printf("error when proxying the request: %s", err)
		ctx.Response.Reset()
		if strings.Contains(err.Error(), "timed out") || strings.Contains(err.Error(), "timeout") {
			ctx.SetStatusCode(408)
			ctx.SetBodyString("408 Request Timeout")
		} else {
			ctx.SetStatusCode(500)
			ctx.SetBodyString("500 Internal Server Error")
		}
		trackRequest(ctx, 0)
	} else {
		postResponse(config, ctx)
	}
}

func preRequest(ctx *fasthttp.RequestCtx) bool {
	req := &ctx.Request
	path := req.RequestURI()
	if bytes.HasPrefix(path, atPath) {
		slashIndex := bytes.IndexRune(path[1:], '/')
		if slashIndex == -1 {
			return false
		}
		endpoint := []byte(path[4:slashIndex+1])
		if !bytes.Equal(endpoint, siteHost) && !bytes.HasSuffix(endpoint, siteHostRoot) {
			return false
		}
		req.Header.SetHostBytes(endpoint)
		req.SetRequestURIBytes([]byte(path[1+slashIndex:]))
	} else if bytes.HasPrefix(path, awayPath) {
		to := string(req.URI().QueryArgs().Peek("to"))
		if to == "" {
			return false
		}
		to, err := url.QueryUnescape(to)
		if err != nil {
			return false
		}
		ctx.Redirect(to, 301)
		return true
	} else {
		req.SetHostBytes(apiHost)
	}
	// After req.URI() call it is impossible to modify URI
	req.URI().SetSchemeBytes(https)
	req.Header.Del("Accept-Encoding")
	return true
}

func postResponse(config *DomainConfig, ctx *fasthttp.RequestCtx) {
	uri := ctx.Request.URI()
	res := &ctx.Response
	res.Header.Del("Set-Cookie")
	body := res.Body()
	path := uri.Path()

	if bytes.Equal(uri.Host(), siteHost) {
		if bytes.Equal(path, videoHlsPath) {
			body = config.siteHlsReplace.apply(body)
		}
	} else {
		for _, replace := range config.apiReplaces {
			body = replace.apply(body)
		}

		// Replace longpoll server
		if bytes.Equal(path, apiLongpollPath) {
			body = config.apiLongpollReplace.apply(body)
		} else

		// Replace longpoll server for official app
		if bytes.Equal(path, apiOfficialLongpollPath) ||
			bytes.Equal(path, apiOfficialLongpollPath2) ||
			bytes.Equal(path, apiOfficialLongpollPath3) {
			body = config.apiOfficialLongpollReplace.apply(body)
		} else

		// Clear feed from SPAM
		if bytes.Equal(path, apiOfficialNewsfeedPath) ||
			bytes.Equal(path, apiNewsfeedGet) {
			var parsed map[string]interface{}
			if err := json.Unmarshal(body, &parsed); err == nil {
				if parsed["response"] != nil {
					response := parsed["response"].(map[string]interface{})
					if response["items"] != nil {
						newItems, modified := filterFeed(response["items"].([]interface{}))
						if modified {
							response["items"] = newItems
							body, err = json.Marshal(parsed)
						}
					}
				}
			}
		}
	}
	res.SetBody(body)

	if Config.debug {
		log.Println(string(path) + "\n" + string(body))
	}

	trackRequest(ctx, len(body))
}

func filterFeed(items []interface{}) ([]interface{}, bool) {
	removed := 0
	for i := len(items) - 1; i >= 0; i-- {
		post := items[i].(map[string]interface{})
		if post["type"] == "ads" || (post["type"] == "post" && post["marked_as_ads"] != nil && post["marked_as_ads"].(float64) == 1) {
			items[i] = items[len(items)-1]
			items[len(items)-1] = nil
			items = items[:len(items)-1]
			removed++
		}
	}
	if removed > 0 {
		newItems := make([]interface{}, len(items))
		copy(newItems, items)
		return newItems, true
	}
	return nil, false
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/http"
	"net/http/httputil"
	"net/url"

	"github.com/cloudflare/unsee/internal/alertmanager"
	"github.com/cloudflare/unsee/internal/config"
	"github.com/gin-gonic/gin"

	log "github.com/sirupsen/logrus"
)

func proxyPathPrefix(name string) string {
	return fmt.Sprintf("%sproxy/alertmanager/%s", config.Config.Listen.Prefix, name)
}

// NewAlertmanagerProxy creates a proxy instance for given alertmanager instance
func NewAlertmanagerProxy(alertmanager *alertmanager.Alertmanager) (*httputil.ReverseProxy, error) {
	upstreamURL, err := url.Parse(alertmanager.URI)
	if err != nil {
		return nil, err
	}
	proxy := httputil.ReverseProxy{
		Director: func(req *http.Request) {
			req.URL.Scheme = upstreamURL.Scheme
			req.URL.Host = upstreamURL.Host
			// drop Accept-Encoding header so we always get uncompressed reponses from
			// upstream, there's a gzip middleware that's global so we don't want it
			// to gzip twice
			req.Header.Del("Accept-Encoding")
			log.Debugf("[%s] Proxy request for %s", alertmanager.Name, req.URL.Path)
		},
		ModifyResponse: func(resp *http.Response) error {
			// drop Content-Length header from upstream responses, gzip middleware
			// will compress those and that could cause a mismatch
			resp.Header.Del("Content-Length")
			return nil
		},
	}
	return &proxy, nil
}

func setupRouterProxyHandlers(router *gin.Engine, alertmanager *alertmanager.Alertmanager) error {
	proxy, err := NewAlertmanagerProxy(alertmanager)
	if err != nil {
		return err
	}
	router.POST(
		fmt.Sprintf("%s/api/v1/silences", proxyPathPrefix(alertmanager.Name)),
		gin.WrapH(http.StripPrefix(proxyPathPrefix(alertmanager.Name), proxy)))
	router.DELETE(
		fmt.Sprintf("%s/api/v1/silence/*id", proxyPathPrefix(alertmanager.Name)),
		gin.WrapH(http.StripPrefix(proxyPathPrefix(alertmanager.Name), proxy)))
	return nil
}
<commit_msg>Cleanup path setup a bit<commit_after>package main

import (
	"fmt"
	"net/http"
	"net/http/httputil"
	"net/url"

	"github.com/cloudflare/unsee/internal/alertmanager"
	"github.com/cloudflare/unsee/internal/config"
	"github.com/gin-gonic/gin"

	log "github.com/sirupsen/logrus"
)

func proxyPathPrefix(name string) string {
	return fmt.Sprintf("%sproxy/alertmanager/%s", config.Config.Listen.Prefix, name)
}

func proxyPath(name, path string) string {
	return fmt.Sprintf("%s%s", proxyPathPrefix(name), path)
}

// NewAlertmanagerProxy creates a proxy instance for given alertmanager instance
func NewAlertmanagerProxy(alertmanager *alertmanager.Alertmanager) (*httputil.ReverseProxy, error) {
	upstreamURL, err := url.Parse(alertmanager.URI)
	if err != nil {
		return nil, err
	}
	proxy := httputil.ReverseProxy{
		Director: func(req *http.Request) {
			req.URL.Scheme = upstreamURL.Scheme
			req.URL.Host = upstreamURL.Host
			// drop Accept-Encoding header so we always get uncompressed reponses from
			// upstream, there's a gzip middleware that's global so we don't want it
			// to gzip twice
			req.Header.Del("Accept-Encoding")
			log.Debugf("[%s] Proxy request for %s", alertmanager.Name, req.URL.Path)
		},
		ModifyResponse: func(resp *http.Response) error {
			// drop Content-Length header from upstream responses, gzip middleware
			// will compress those and that could cause a mismatch
			resp.Header.Del("Content-Length")
			return nil
		},
	}
	return &proxy, nil
}

func setupRouterProxyHandlers(router *gin.Engine, alertmanager *alertmanager.Alertmanager) error {
	proxy, err := NewAlertmanagerProxy(alertmanager)
	if err != nil {
		return err
	}
	router.POST(
		proxyPath(alertmanager.Name, "/api/v1/silences"),
		gin.WrapH(http.StripPrefix(proxyPathPrefix(alertmanager.Name), proxy)))
	router.DELETE(
		proxyPath(alertmanager.Name, "/api/v1/silence/*id"),
		gin.WrapH(http.StripPrefix(proxyPathPrefix(alertmanager.Name), proxy)))
	return nil
}
<|endoftext|>


<commit_before>package main

import(
	"fmt"
	"time"
	"math"
)

/*type struct Coords{
	long float64
	lat float64
}*/

//https://en.wikipedia.org/wiki/Julian_day
func julianCent(jul float64) float64{
	return (jul - 2451545.0)/36525.0
}

func julian(dt time.Time) float64{
	year := float64(dt.Year())
	month := float64(dt.Month())
	day := float64(dt.Day())
	hour := float64(dt.Hour())
	minute := float64(dt.Minute())
	second := float64(dt.Second())
	_, zone := dt.Zone()

	if month <= 2 {
                year -= 1
                month += 12
	}

	a := math.Floor(year/100.0)
	b := 2 - a + math.Floor(a / 4.0)
	jd := math.Floor(365.25 * (year + 4716.0)) + math.Floor(30.6001 * (month + 1)) + day + b - 1524.5
	mins := hour * 60.0 + minute + second / 60.0
	return jd + mins/1444.0 - float64(zone)/24.0
}

func fixAngle(deg float64) float64{
	return math.Mod(deg, 360.0)
}

func toRadians(deg float64) float64{
	return deg*math.Pi/180.0
}

func toDegrees(rad float64) float64{
	return rad*180.0/math.Pi
}

func meanObliquityEcliptic(jul float64) float64{
	seconds := 21.448 - jul*(46.8150 + jul*(0.00059 - jul*(0.001813)))
	e0 := 23.0 + (26.0 + (seconds/60.0))/60.0
	return e0
}

func obliquityCorrection(jul float64) float64{
	e0 := meanObliquityEcliptic(jul)
	omega := 125.04 - 1934.136 * jul
	e := e0 + 0.00256 * math.Cos(toRadians(omega))
	//fmt.Println("obliquity correction ", e)
	return e
}

func geomMeanAnomalySun(jul float64) float64{
	a := 357.52911 + jul * (35999.05029 - 0.0001537 * jul)
	//fmt.Println("Mean Anomaly: ", a)
	return a
}

func geomMeanLongSun(jul float64) float64{
	L0 := 280.46646 + jul * (36000.76983 + jul*(0.0003032))
	L0 = fixAngle(L0)
	//fmt.Println("Mean Long: ", L0)
	return L0
}

func eccentricityEarthOrbit(jul float64) float64{
	e := 0.016708634 - jul * (0.000042037 + 0.0000001267 * jul)
	//fmt.Println("Eccentricity: ", e)
	return e
}

func sunEqOfCenter(jul float64) float64{
	m := geomMeanAnomalySun(jul)
	mrad := toRadians(m)
	sinm := math.Sin(mrad)
	sin2m := math.Sin(2.0 * mrad)
	sin3m := math.Sin(3.0 * mrad)
	C := sinm * (1.914602 - jul * (0.004817 + 0.000014 * jul)) + sin2m * (0.019993 - 0.000101 * jul) + sin3m * 0.000289
	return C
}

func sunTrueLong(jul float64) float64{
	l0 := geomMeanLongSun(jul)
	c := sunEqOfCenter(jul)
	o := l0 + c
	return o
}

func sunApparentLong(jul float64) float64{
	o := sunTrueLong(jul)
	omega := 125.04 - 1934.136 * jul
	lambda := o - 0.00569 - 0.00478 * math.Sin(toRadians(omega))
	return lambda
}

func solarDeclination(jul float64) float64{
	e := obliquityCorrection(jul)
	lambda := sunApparentLong(jul)

	sint := math.Sin(toRadians(e)) * math.Sin(toRadians(lambda))
	return toDegrees(math.Asin(sint))
}

func equationOfTime(jul float64) float64{
	epsilon := obliquityCorrection(jul);
	l0 := geomMeanLongSun(jul);
	e := eccentricityEarthOrbit(jul);
	m := geomMeanAnomalySun(jul);

	y := math.Tan(toRadians(epsilon)/2.0);
	y *= y;

	sin2l0 := math.Sin(2.0 * toRadians(l0));
	sinm   := math.Sin(toRadians(m));
	cos2l0 := math.Cos(2.0 * toRadians(l0));
	sin4l0 := math.Sin(4.0 * toRadians(l0));
	sin2m  := math.Sin(2.0 * toRadians(m));

	eTime := y * sin2l0 - 2.0 * e * sinm + 4.0 * e * y * sinm * cos2l0 - 0.5 * y * y * sin4l0 - 1.25 * e * e * sin2m;

	return toDegrees(eTime) * 4.0 / 60.0
}

func dhuhr(zone int, longitude float64, clock_offset float64) float64{
	return 12.0 + float64(zone) - longitude/15.0 - clock_offset
}

func sunrise(lat float64, solDec float64, dhuhr float64) float64{
	return dhuhr - timeAngle(lat, solDec, toRadians(0.833))
}

func sunset(lat float64, solDec float64, dhuhr float64) float64{
	return dhuhr + timeAngle(lat, solDec, toRadians(0.833))
}

func fajr(lat float64, solDec float64, dhuhr float64) float64{
	angle := toRadians(15.0)
	return dhuhr - timeAngle(lat, solDec, angle)
}

func isha(lat float64, solDec float64, dhuhr float64) float64{
	angle := toRadians(15.0)
	return dhuhr + timeAngle(lat, solDec, angle)
}

func maghrib(lat float64, solDec float64, dhuhr float64) float64{
	angle := toRadians(4.0)
	return dhuhr + timeAngle(lat, solDec, angle)
}

func asr(lat float64, long float64, jul float64, factor float64) float64{
	dec := solarDeclination(jul)
	eqt := equationOfTime(jul)
	zone := 0
	//_, zone := time.Zone(
	dhuhrT := dhuhr(zone, long, eqt)
	angle := -1.0/math.Atan(factor + math.Tan(math.Abs(lat - dec)))
	return dhuhrT + timeAngle(lat, dec, angle)
}

func timeAngle(latitude float64, solDec float64, angle float64) float64{
	latitude = toRadians(latitude)
	solDec = toRadians(solDec)
	return 1/15.0*toDegrees(math.Acos(-math.Sin(angle) - math.Sin(latitude)*math.Sin(solDec)/(math.Cos(latitude) * math.Cos(solDec))))
}

func main(){
	date := time.Date(2015, time.December, 29, 12, 0, 0, 0, time.UTC)
	jul := julianCent(julian(date))
	eqTime := equationOfTime(jul)
	solDec := solarDeclination(jul)
	dh := dhuhr(0.0, 0.0, eqTime)
	fr := fajr(0.0, solDec, dh)
	fmt.Println("Fajr: ", fr)
	fmt.Println("Dhuhr: ", dh)
	is := isha(0.0, solDec, dh)
	as := asr(0.0, 0.0, jul, 1.0)
	fmt.Println("Asr: ", as)
	mr := maghrib(0.0, solDec, dh)
	fmt.Println("Maghrib: ", mr)
	fmt.Println("Isha: ", is)

}
<commit_msg>Change date formatting, refactor mildly<commit_after>package main

import(
	"fmt"
	"time"
	"math"
)

/*type struct Coords{
	long float64
	lat float64
}*/

//https://en.wikipedia.org/wiki/Julian_day
func julianCent(jul float64) float64{
	return (jul - 2451545.0)/36525.0
}

func julian(dt time.Time) float64{
	year := float64(dt.Year())
	month := float64(dt.Month())
	day := float64(dt.Day())
	hour := float64(dt.Hour())
	minute := float64(dt.Minute())
	second := float64(dt.Second())
	_, zone := dt.Zone()

	if month <= 2 {
                year -= 1
                month += 12
	}

	a := math.Floor(year/100.0)
	b := 2 - a + math.Floor(a / 4.0)
	jd := math.Floor(365.25 * (year + 4716.0)) + math.Floor(30.6001 * (month + 1)) + day + b - 1524.5
	mins := hour * 60.0 + minute + second / 60.0
	return jd + mins/1444.0 - float64(zone)/24.0
}

func fixAngle(deg float64) float64{
	return math.Mod(deg, 360.0)
}

func toRadians(deg float64) float64{
	return deg*math.Pi/180.0
}

func toDegrees(rad float64) float64{
	return rad*180.0/math.Pi
}

func meanObliquityEcliptic(jul float64) float64{
	seconds := 21.448 - jul*(46.8150 + jul*(0.00059 - jul*(0.001813)))
	e0 := 23.0 + (26.0 + (seconds/60.0))/60.0
	return e0
}

func obliquityCorrection(jul float64) float64{
	e0 := meanObliquityEcliptic(jul)
	omega := 125.04 - 1934.136 * jul
	e := e0 + 0.00256 * math.Cos(toRadians(omega))
	//fmt.Println("obliquity correction ", e)
	return e
}

func geomMeanAnomalySun(jul float64) float64{
	a := 357.52911 + jul * (35999.05029 - 0.0001537 * jul)
	//fmt.Println("Mean Anomaly: ", a)
	return a
}

func geomMeanLongSun(jul float64) float64{
	L0 := 280.46646 + jul * (36000.76983 + jul*(0.0003032))
	L0 = fixAngle(L0)
	//fmt.Println("Mean Long: ", L0)
	return L0
}

func eccentricityEarthOrbit(jul float64) float64{
	e := 0.016708634 - jul * (0.000042037 + 0.0000001267 * jul)
	//fmt.Println("Eccentricity: ", e)
	return e
}

func sunEqOfCenter(jul float64) float64{
	m := geomMeanAnomalySun(jul)
	mrad := toRadians(m)
	sinm := math.Sin(mrad)
	sin2m := math.Sin(2.0 * mrad)
	sin3m := math.Sin(3.0 * mrad)
	C := sinm * (1.914602 - jul * (0.004817 + 0.000014 * jul)) + sin2m * (0.019993 - 0.000101 * jul) + sin3m * 0.000289
	return C
}

func sunTrueLong(jul float64) float64{
	l0 := geomMeanLongSun(jul)
	c := sunEqOfCenter(jul)
	o := l0 + c
	return o
}

func sunApparentLong(jul float64) float64{
	o := sunTrueLong(jul)
	omega := 125.04 - 1934.136 * jul
	lambda := o - 0.00569 - 0.00478 * math.Sin(toRadians(omega))
	return lambda
}

func solarDeclination(jul float64) float64{
	e := obliquityCorrection(jul)
	lambda := sunApparentLong(jul)

	sint := math.Sin(toRadians(e)) * math.Sin(toRadians(lambda))
	return toDegrees(math.Asin(sint))
}

func equationOfTime(jul float64) float64{
	epsilon := obliquityCorrection(jul);
	l0 := geomMeanLongSun(jul);
	e := eccentricityEarthOrbit(jul);
	m := geomMeanAnomalySun(jul);

	y := math.Tan(toRadians(epsilon)/2.0);
	y *= y;

	sin2l0 := math.Sin(2.0 * toRadians(l0));
	sinm   := math.Sin(toRadians(m));
	cos2l0 := math.Cos(2.0 * toRadians(l0));
	sin4l0 := math.Sin(4.0 * toRadians(l0));
	sin2m  := math.Sin(2.0 * toRadians(m));

	eTime := y * sin2l0 - 2.0 * e * sinm + 4.0 * e * y * sinm * cos2l0 - 0.5 * y * y * sin4l0 - 1.25 * e * e * sin2m;

	return toDegrees(eTime) * 4.0 / 60.0
}

func dhuhr(zone int, longitude float64, clock_offset float64) float64{
	return 12.0 + float64(zone) - longitude/15.0 - clock_offset
}

func sunrise(lat float64, solDec float64, dhuhr float64) float64{
	return dhuhr - timeAngle(lat, solDec, toRadians(0.833))
}

func sunset(lat float64, solDec float64, dhuhr float64) float64{
	return dhuhr + timeAngle(lat, solDec, toRadians(0.833))
}

func fajr(lat float64, solDec float64, dhuhr float64) float64{
	angle := toRadians(15.0)
	return dhuhr - timeAngle(lat, solDec, angle)
}

func isha(lat float64, solDec float64, dhuhr float64) float64{
	angle := toRadians(15.0)
	return dhuhr + timeAngle(lat, solDec, angle)
}

func maghrib(lat float64, solDec float64, dhuhr float64) float64{
	angle := toRadians(4.0)
	return dhuhr + timeAngle(lat, solDec, angle)
}

func asr(lat float64, long float64, jul float64, factor float64) float64{
	dec := solarDeclination(jul)
	eqt := equationOfTime(jul)
	zone := 0
	//_, zone := time.Zone(
	dhuhrT := dhuhr(zone, long, eqt)
	angle := -1.0/math.Atan(factor + math.Tan(math.Abs(lat - dec)))
	return dhuhrT + timeAngle(lat, dec, angle)
}

func timeAngle(latitude float64, solDec float64, angle float64) float64{
	latitude = toRadians(latitude)
	solDec = toRadians(solDec)
	return 1/15.0*toDegrees(math.Acos(-math.Sin(angle) - math.Sin(latitude)*math.Sin(solDec)/(math.Cos(latitude) * math.Cos(solDec))))
}

func main(){
	date, _ := time.Parse("01/02/2006 15:04:05 -0700", "01/20/2016 20:45:00 -0500")
	jul := julianCent(julian(date))
	eqTime := equationOfTime(jul)
	solDec := solarDeclination(jul)
	dh := dhuhr(0.0, 0.0, eqTime)
	fr := fajr(0.0, solDec, dh)
	fmt.Println("Fajr: ", fr)
	fmt.Println("Dhuhr: ", dh)
	is := isha(0.0, solDec, dh)
	as := asr(0.0, 0.0, jul, 1.0)
	fmt.Println("Asr: ", as)
	mr := maghrib(0.0, solDec, dh)
	fmt.Println("Maghrib: ", mr)
	fmt.Println("Isha: ", is)

}
<|endoftext|>


<commit_before>package main

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

	"github.com/intelsdilabs/pulse/control"
	"github.com/intelsdilabs/pulse/schedule"
)

var (
	// Pulse Flags for command line
	version  = flag.Bool("version", false, "print Pulse version")
	maxProcs = flag.Int("max_procs", 1, "max number of CPUs that can be used simultaneously. Default is use all cores.")

	gitversion string
)

const (
	defaultQueueSize int = 25
	defaultPoolSize  int = 4
)

type coreModule interface {
	Start() error
	Stop()
}

func main() {
	flag.Parse()
	if *version {
		fmt.Println("Pulse version:", gitversion)
		os.Exit(0)
	}
	// Set Max Processors for the Pulse agent.
	setMaxProcs()

	c := control.New()
	s := schedule.New(defaultPoolSize, defaultQueueSize)
	s.SetMetricManager(c)

	// Set interrupt handling so we can die gracefully.
	startInterruptHandling(c, s)

	//  Start our modules
	if err := startModule("Plugin Controller", c); err != nil {
		printErrorAndExit("Plugin Controller", err)
	}
	if err := startModule("Scheduler", s); err != nil {
		if c.Started {
			c.Stop()
		}
		printErrorAndExit("Scheduler", err)
	}

	select {} //run forever and ever
}

func setMaxProcs() {
	var _maxProcs int
	numProcs := runtime.NumCPU()
	if *maxProcs <= 0 {
		if *maxProcs < 0 {
			log.Println("WARNING: max_procs set to less than zero. Setting GOMAXPROCS to default of 1")
		}
		_maxProcs = 1
	} else if *maxProcs > numProcs {
		log.Printf("WARNING: Not allowed to set GOMAXPROCS above number of processors in system. Setting GOMAXPROCS to %v", numProcs)
		_maxProcs = numProcs
	} else {
		_maxProcs = *maxProcs
	}
	log.Printf("Setting GOMAXPROCS to %v\n", _maxProcs)
	runtime.GOMAXPROCS(_maxProcs)

	//Verify setting worked
	actualNumProcs := runtime.GOMAXPROCS(0)
	if actualNumProcs != _maxProcs {
		log.Printf("WARNING: Specified max procs of %v but using %v", _maxProcs, actualNumProcs)
	}
}

func startModule(name string, m coreModule) error {
	log.Printf("Starting Pulse Agent %s module", name)
	return m.Start()
}

func printErrorAndExit(name string, err error) {
	log.Println("ERROR:", err)
	log.Println("ERROR: Error starting Pulse Agent %s module. Exiting now.", name)
	os.Exit(1)
}

func startInterruptHandling(modules ...coreModule) {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill, syscall.SIGTERM)

	//Let's block until someone tells us to quit
	go func() {
		sig := <-c
		log.Println("Stopping Pulse Agent modules")
		for _, m := range modules {
			m.Stop()
		}
		log.Printf("Exiting given signal: %v", sig)
		os.Exit(0)
	}()
}
<commit_msg>Fix error<commit_after>package main

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

	"github.com/intelsdilabs/pulse/control"
	"github.com/intelsdilabs/pulse/schedule"
)

var (
	// Pulse Flags for command line
	version  = flag.Bool("version", false, "print Pulse version")
	maxProcs = flag.Int("max_procs", 1, "max number of CPUs that can be used simultaneously. Default is use all cores.")

	gitversion string
)

const (
	defaultQueueSize int = 25
	defaultPoolSize  int = 4
)

type coreModule interface {
	Start() error
	Stop()
}

func main() {
	flag.Parse()
	if *version {
		fmt.Println("Pulse version:", gitversion)
		os.Exit(0)
	}
	// Set Max Processors for the Pulse agent.
	setMaxProcs()

	c := control.New()
	s := schedule.New(defaultPoolSize, defaultQueueSize)
	s.SetMetricManager(c)

	// Set interrupt handling so we can die gracefully.
	startInterruptHandling(c, s)

	//  Start our modules
	if err := startModule("Plugin Controller", c); err != nil {
		printErrorAndExit("Plugin Controller", err)
	}
	if err := startModule("Scheduler", s); err != nil {
		if c.Started {
			c.Stop()
		}
		printErrorAndExit("Scheduler", err)
	}

	select {} //run forever and ever
}

func setMaxProcs() {
	var _maxProcs int
	numProcs := runtime.NumCPU()
	if *maxProcs <= 0 {
		if *maxProcs < 0 {
			log.Println("WARNING: max_procs set to less than zero. Setting GOMAXPROCS to default of 1")
		}
		_maxProcs = 1
	} else if *maxProcs > numProcs {
		log.Printf("WARNING: Not allowed to set GOMAXPROCS above number of processors in system. Setting GOMAXPROCS to %v", numProcs)
		_maxProcs = numProcs
	} else {
		_maxProcs = *maxProcs
	}
	log.Printf("Setting GOMAXPROCS to %v\n", _maxProcs)
	runtime.GOMAXPROCS(_maxProcs)

	//Verify setting worked
	actualNumProcs := runtime.GOMAXPROCS(0)
	if actualNumProcs != _maxProcs {
		log.Printf("WARNING: Specified max procs of %v but using %v", _maxProcs, actualNumProcs)
	}
}

func startModule(name string, m coreModule) error {
	log.Printf("Starting Pulse Agent %s module", name)
	return m.Start()
}

func printErrorAndExit(name string, err error) {
	log.Println("ERROR:", err)
	log.Printf("ERROR: Error starting Pulse Agent %s module. Exiting now.", name)
	os.Exit(1)
}

func startInterruptHandling(modules ...coreModule) {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill, syscall.SIGTERM)

	//Let's block until someone tells us to quit
	go func() {
		sig := <-c
		log.Println("Stopping Pulse Agent modules")
		for _, m := range modules {
			m.Stop()
		}
		log.Printf("Exiting given signal: %v", sig)
		os.Exit(0)
	}()
}
<|endoftext|>


<commit_before>// Copyright 2016 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

package libfuse

import (
	"os"
	"sync"
	"time"

	"bazil.org/fuse"
	"bazil.org/fuse/fs"
	"github.com/keybase/client/go/logger"
	"github.com/keybase/kbfs/libfs"
	"github.com/keybase/kbfs/libkbfs"
	"golang.org/x/net/context"
)

// TLF represents the root directory of a TLF. It wraps a lazy-loaded
// Dir.
type TLF struct {
	folder *Folder

	dirLock sync.RWMutex
	dir     *Dir
}

func newTLF(fl *FolderList, h *libkbfs.TlfHandle,
	name libkbfs.PreferredTlfName) *TLF {
	folder := newFolder(fl, h, name)
	tlf := &TLF{
		folder: folder,
	}
	return tlf
}

var _ DirInterface = (*TLF)(nil)

func (tlf *TLF) isPublic() bool {
	return tlf.folder.list.public
}

func (tlf *TLF) getStoredDir() *Dir {
	tlf.dirLock.RLock()
	defer tlf.dirLock.RUnlock()
	return tlf.dir
}

func (tlf *TLF) clearStoredDir() {
	tlf.dirLock.Lock()
	defer tlf.dirLock.Unlock()
	tlf.dir = nil
}

func (tlf *TLF) log() logger.Logger {
	return tlf.folder.fs.log
}

func (tlf *TLF) loadDirHelper(ctx context.Context, mode libkbfs.ErrorModeType,
	filterErr bool) (dir *Dir, exitEarly bool, err error) {
	dir = tlf.getStoredDir()
	if dir != nil {
		return dir, false, nil
	}

	tlf.dirLock.Lock()
	defer tlf.dirLock.Unlock()
	// Need to check for nilness again to avoid racing with other
	// calls to loadDir().
	if tlf.dir != nil {
		return tlf.dir, false, nil
	}

	tlf.log().CDebugf(ctx, "Loading root directory for folder %s "+
		"(public: %t, filter error: %t)", tlf.folder.name(),
		tlf.isPublic(), filterErr)
	defer func() {
		if filterErr {
			exitEarly, err = libfs.FilterTLFEarlyExitError(ctx, err, tlf.log(), tlf.folder.name())
		}
		tlf.folder.reportErr(ctx, mode, err)
	}()

	handle, err := tlf.folder.resolve(ctx)
	if err != nil {
		return nil, false, err
	}

	var rootNode libkbfs.Node
	if filterErr {
		rootNode, _, err = tlf.folder.fs.config.KBFSOps().GetRootNode(
			ctx, handle, libkbfs.MasterBranch)
		if err != nil {
			return nil, false, err
		}
		// If not fake an empty directory.
		if rootNode == nil {
			return nil, false, libfs.TlfDoesNotExist{}
		}
	} else {
		rootNode, _, err = tlf.folder.fs.config.KBFSOps().GetOrCreateRootNode(
			ctx, handle, libkbfs.MasterBranch)
		if err != nil {
			return nil, false, err
		}
	}

	err = tlf.folder.setFolderBranch(rootNode.GetFolderBranch())
	if err != nil {
		return nil, false, err
	}

	tlf.folder.nodes[rootNode.GetID()] = tlf
	tlf.dir = newDir(tlf.folder, rootNode)

	return tlf.dir, false, nil
}

func (tlf *TLF) loadDir(ctx context.Context) (*Dir, error) {
	dir, _, err := tlf.loadDirHelper(ctx, libkbfs.WriteMode, false)
	return dir, err
}

// loadDirAllowNonexistent loads a TLF if it's not already loaded.  If
// the TLF doesn't yet exist, it still returns a nil error and
// indicates that the calling function should pretend it's an empty
// folder.
func (tlf *TLF) loadDirAllowNonexistent(ctx context.Context) (
	*Dir, bool, error) {
	return tlf.loadDirHelper(ctx, libkbfs.ReadMode, true)
}

// Access implements the fs.NodeAccesser interface for *TLF.
func (tlf *TLF) Access(ctx context.Context, r *fuse.AccessRequest) error {
	return tlf.folder.access(ctx, r)
}

// Attr implements the fs.Node interface for TLF.
func (tlf *TLF) Attr(ctx context.Context, a *fuse.Attr) error {
	dir := tlf.getStoredDir()
	if dir == nil {
		tlf.log().CDebugf(
			ctx, "Faking Attr for TLF %s", tlf.folder.name())
		// Have a low non-zero value for Valid to avoid being
		// swamped with requests, while still not showing
		// stale data for too long if we end up loading the
		// dir.
		a.Valid = 1 * time.Second
		a.Mode = os.ModeDir | 0500
		a.Uid = uint32(os.Getuid())
		return nil
	}

	return dir.Attr(ctx, a)
}

// Lookup implements the fs.NodeRequestLookuper interface for TLF.
func (tlf *TLF) Lookup(ctx context.Context, req *fuse.LookupRequest, resp *fuse.LookupResponse) (fs.Node, error) {
	dir, exitEarly, err := tlf.loadDirAllowNonexistent(ctx)
	if err != nil {
		return nil, err
	}
	if exitEarly {
		if node := handleTLFSpecialFile(
			req.Name, tlf.folder, &resp.EntryValid); node != nil {
			return node, nil
		}
		return nil, fuse.ENOENT
	}
	return dir.Lookup(ctx, req, resp)
}

// Create implements the fs.NodeCreater interface for TLF.
func (tlf *TLF) Create(ctx context.Context, req *fuse.CreateRequest, resp *fuse.CreateResponse) (fs.Node, fs.Handle, error) {
	dir, err := tlf.loadDir(ctx)
	if err != nil {
		return nil, nil, err
	}
	return dir.Create(ctx, req, resp)
}

// Mkdir implements the fs.NodeMkdirer interface for TLF.
func (tlf *TLF) Mkdir(ctx context.Context, req *fuse.MkdirRequest) (_ fs.Node, err error) {
	dir, err := tlf.loadDir(ctx)
	if err != nil {
		return nil, err
	}
	return dir.Mkdir(ctx, req)
}

// Symlink implements the fs.NodeSymlinker interface for TLF.
func (tlf *TLF) Symlink(ctx context.Context, req *fuse.SymlinkRequest) (
	fs.Node, error) {
	dir, err := tlf.loadDir(ctx)
	if err != nil {
		return nil, err
	}
	return dir.Symlink(ctx, req)
}

// Rename implements the fs.NodeRenamer interface for TLF.
func (tlf *TLF) Rename(ctx context.Context, req *fuse.RenameRequest,
	newDir fs.Node) error {
	dir, err := tlf.loadDir(ctx)
	if err != nil {
		return err
	}
	return dir.Rename(ctx, req, newDir)
}

// Remove implements the fs.NodeRemover interface for TLF.
func (tlf *TLF) Remove(ctx context.Context, req *fuse.RemoveRequest) error {
	dir, err := tlf.loadDir(ctx)
	if err != nil {
		return err
	}
	return dir.Remove(ctx, req)
}

// ReadDirAll implements the fs.NodeReadDirAller interface for TLF.
func (tlf *TLF) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
	dir, exitEarly, err := tlf.loadDirAllowNonexistent(ctx)
	if err != nil || exitEarly {
		return nil, err
	}
	return dir.ReadDirAll(ctx)
}

// Forget kernel reference to this node.
func (tlf *TLF) Forget() {
	dir := tlf.getStoredDir()
	if dir != nil {
		dir.Forget()
	}
}

// Setattr implements the fs.NodeSetattrer interface for TLF.
func (tlf *TLF) Setattr(ctx context.Context, req *fuse.SetattrRequest, resp *fuse.SetattrResponse) error {
	dir, err := tlf.loadDir(ctx)
	if err != nil {
		return err
	}
	return dir.Setattr(ctx, req, resp)
}

// Fsync implements the fs.NodeFsyncer interface for TLF.
func (tlf *TLF) Fsync(ctx context.Context, req *fuse.FsyncRequest) (err error) {
	dir, err := tlf.loadDir(ctx)
	if err != nil {
		return err
	}
	return dir.Fsync(ctx, req)
}

var _ fs.Handle = (*TLF)(nil)

var _ fs.NodeOpener = (*TLF)(nil)

// Open implements the fs.NodeOpener interface for TLF.
func (tlf *TLF) Open(ctx context.Context, req *fuse.OpenRequest,
	resp *fuse.OpenResponse) (fs.Handle, error) {
	// Explicitly load the directory when a TLF is opened, because
	// some OSX programs like ls have a bug that doesn't report errors
	// on a ReadDirAll.
	_, _, err := tlf.loadDirAllowNonexistent(ctx)
	if err != nil {
		return nil, err
	}
	return tlf, nil
}
<commit_msg>libfuse: don't loadDir on a TLF.Fsync()<commit_after>// Copyright 2016 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

package libfuse

import (
	"os"
	"sync"
	"time"

	"bazil.org/fuse"
	"bazil.org/fuse/fs"
	"github.com/keybase/client/go/logger"
	"github.com/keybase/kbfs/libfs"
	"github.com/keybase/kbfs/libkbfs"
	"golang.org/x/net/context"
)

// TLF represents the root directory of a TLF. It wraps a lazy-loaded
// Dir.
type TLF struct {
	folder *Folder

	dirLock sync.RWMutex
	dir     *Dir
}

func newTLF(fl *FolderList, h *libkbfs.TlfHandle,
	name libkbfs.PreferredTlfName) *TLF {
	folder := newFolder(fl, h, name)
	tlf := &TLF{
		folder: folder,
	}
	return tlf
}

var _ DirInterface = (*TLF)(nil)

func (tlf *TLF) isPublic() bool {
	return tlf.folder.list.public
}

func (tlf *TLF) getStoredDir() *Dir {
	tlf.dirLock.RLock()
	defer tlf.dirLock.RUnlock()
	return tlf.dir
}

func (tlf *TLF) clearStoredDir() {
	tlf.dirLock.Lock()
	defer tlf.dirLock.Unlock()
	tlf.dir = nil
}

func (tlf *TLF) log() logger.Logger {
	return tlf.folder.fs.log
}

func (tlf *TLF) loadDirHelper(ctx context.Context, mode libkbfs.ErrorModeType,
	filterErr bool) (dir *Dir, exitEarly bool, err error) {
	dir = tlf.getStoredDir()
	if dir != nil {
		return dir, false, nil
	}

	tlf.dirLock.Lock()
	defer tlf.dirLock.Unlock()
	// Need to check for nilness again to avoid racing with other
	// calls to loadDir().
	if tlf.dir != nil {
		return tlf.dir, false, nil
	}

	tlf.log().CDebugf(ctx, "Loading root directory for folder %s "+
		"(public: %t, filter error: %t)", tlf.folder.name(),
		tlf.isPublic(), filterErr)
	defer func() {
		if filterErr {
			exitEarly, err = libfs.FilterTLFEarlyExitError(ctx, err, tlf.log(), tlf.folder.name())
		}
		tlf.folder.reportErr(ctx, mode, err)
	}()

	handle, err := tlf.folder.resolve(ctx)
	if err != nil {
		return nil, false, err
	}

	var rootNode libkbfs.Node
	if filterErr {
		rootNode, _, err = tlf.folder.fs.config.KBFSOps().GetRootNode(
			ctx, handle, libkbfs.MasterBranch)
		if err != nil {
			return nil, false, err
		}
		// If not fake an empty directory.
		if rootNode == nil {
			return nil, false, libfs.TlfDoesNotExist{}
		}
	} else {
		rootNode, _, err = tlf.folder.fs.config.KBFSOps().GetOrCreateRootNode(
			ctx, handle, libkbfs.MasterBranch)
		if err != nil {
			return nil, false, err
		}
	}

	err = tlf.folder.setFolderBranch(rootNode.GetFolderBranch())
	if err != nil {
		return nil, false, err
	}

	tlf.folder.nodes[rootNode.GetID()] = tlf
	tlf.dir = newDir(tlf.folder, rootNode)

	return tlf.dir, false, nil
}

func (tlf *TLF) loadDir(ctx context.Context) (*Dir, error) {
	dir, _, err := tlf.loadDirHelper(ctx, libkbfs.WriteMode, false)
	return dir, err
}

// loadDirAllowNonexistent loads a TLF if it's not already loaded.  If
// the TLF doesn't yet exist, it still returns a nil error and
// indicates that the calling function should pretend it's an empty
// folder.
func (tlf *TLF) loadDirAllowNonexistent(ctx context.Context) (
	*Dir, bool, error) {
	return tlf.loadDirHelper(ctx, libkbfs.ReadMode, true)
}

// Access implements the fs.NodeAccesser interface for *TLF.
func (tlf *TLF) Access(ctx context.Context, r *fuse.AccessRequest) error {
	return tlf.folder.access(ctx, r)
}

// Attr implements the fs.Node interface for TLF.
func (tlf *TLF) Attr(ctx context.Context, a *fuse.Attr) error {
	dir := tlf.getStoredDir()
	if dir == nil {
		tlf.log().CDebugf(
			ctx, "Faking Attr for TLF %s", tlf.folder.name())
		// Have a low non-zero value for Valid to avoid being
		// swamped with requests, while still not showing
		// stale data for too long if we end up loading the
		// dir.
		a.Valid = 1 * time.Second
		a.Mode = os.ModeDir | 0500
		a.Uid = uint32(os.Getuid())
		return nil
	}

	return dir.Attr(ctx, a)
}

// Lookup implements the fs.NodeRequestLookuper interface for TLF.
func (tlf *TLF) Lookup(ctx context.Context, req *fuse.LookupRequest, resp *fuse.LookupResponse) (fs.Node, error) {
	dir, exitEarly, err := tlf.loadDirAllowNonexistent(ctx)
	if err != nil {
		return nil, err
	}
	if exitEarly {
		if node := handleTLFSpecialFile(
			req.Name, tlf.folder, &resp.EntryValid); node != nil {
			return node, nil
		}
		return nil, fuse.ENOENT
	}
	return dir.Lookup(ctx, req, resp)
}

// Create implements the fs.NodeCreater interface for TLF.
func (tlf *TLF) Create(ctx context.Context, req *fuse.CreateRequest, resp *fuse.CreateResponse) (fs.Node, fs.Handle, error) {
	dir, err := tlf.loadDir(ctx)
	if err != nil {
		return nil, nil, err
	}
	return dir.Create(ctx, req, resp)
}

// Mkdir implements the fs.NodeMkdirer interface for TLF.
func (tlf *TLF) Mkdir(ctx context.Context, req *fuse.MkdirRequest) (_ fs.Node, err error) {
	dir, err := tlf.loadDir(ctx)
	if err != nil {
		return nil, err
	}
	return dir.Mkdir(ctx, req)
}

// Symlink implements the fs.NodeSymlinker interface for TLF.
func (tlf *TLF) Symlink(ctx context.Context, req *fuse.SymlinkRequest) (
	fs.Node, error) {
	dir, err := tlf.loadDir(ctx)
	if err != nil {
		return nil, err
	}
	return dir.Symlink(ctx, req)
}

// Rename implements the fs.NodeRenamer interface for TLF.
func (tlf *TLF) Rename(ctx context.Context, req *fuse.RenameRequest,
	newDir fs.Node) error {
	dir, err := tlf.loadDir(ctx)
	if err != nil {
		return err
	}
	return dir.Rename(ctx, req, newDir)
}

// Remove implements the fs.NodeRemover interface for TLF.
func (tlf *TLF) Remove(ctx context.Context, req *fuse.RemoveRequest) error {
	dir, err := tlf.loadDir(ctx)
	if err != nil {
		return err
	}
	return dir.Remove(ctx, req)
}

// ReadDirAll implements the fs.NodeReadDirAller interface for TLF.
func (tlf *TLF) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
	dir, exitEarly, err := tlf.loadDirAllowNonexistent(ctx)
	if err != nil || exitEarly {
		return nil, err
	}
	return dir.ReadDirAll(ctx)
}

// Forget kernel reference to this node.
func (tlf *TLF) Forget() {
	dir := tlf.getStoredDir()
	if dir != nil {
		dir.Forget()
	}
}

// Setattr implements the fs.NodeSetattrer interface for TLF.
func (tlf *TLF) Setattr(ctx context.Context, req *fuse.SetattrRequest, resp *fuse.SetattrResponse) error {
	dir, err := tlf.loadDir(ctx)
	if err != nil {
		return err
	}
	return dir.Setattr(ctx, req, resp)
}

// Fsync implements the fs.NodeFsyncer interface for TLF.
func (tlf *TLF) Fsync(ctx context.Context, req *fuse.FsyncRequest) (err error) {
	dir := tlf.getStoredDir()
	if dir == nil {
		// The directory hasn't been loaded yet, so there's nothing to do.
		return nil
	}

	return dir.Fsync(ctx, req)
}

var _ fs.Handle = (*TLF)(nil)

var _ fs.NodeOpener = (*TLF)(nil)

// Open implements the fs.NodeOpener interface for TLF.
func (tlf *TLF) Open(ctx context.Context, req *fuse.OpenRequest,
	resp *fuse.OpenResponse) (fs.Handle, error) {
	// Explicitly load the directory when a TLF is opened, because
	// some OSX programs like ls have a bug that doesn't report errors
	// on a ReadDirAll.
	_, _, err := tlf.loadDirAllowNonexistent(ctx)
	if err != nil {
		return nil, err
	}
	return tlf, nil
}
<|endoftext|>


<commit_before>package main_test

import (
	"github.com/cloudfoundry-incubator/bbs/cmd/bbs/testrunner"
	"github.com/cloudfoundry-incubator/locket"
	"github.com/pivotal-golang/clock"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/ginkgomon"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Ping API", func() {
	AfterEach(func() {
		if bbsProcess != nil {
			ginkgomon.Kill(bbsProcess)
		}
	})

	Describe("Ping", func() {
		Context("when the BBS Server is up", func() {
			BeforeEach(func() {
				bbsRunner = testrunner.New(bbsBinPath, bbsArgs)
				bbsProcess = ginkgomon.Invoke(bbsRunner)
			})

			It("returns true", func() {
				Expect(client.Ping()).To(BeTrue())
			})
		})

		Context("when the BBS Server is not the leader", func() {
			var competingBBSLockProcess ifrit.Process
			BeforeEach(func() {
				competingBBSLock := locket.NewLock(logger, consulClient, locket.LockSchemaPath("bbs_lock"), []byte{}, clock.NewClock(), locket.RetryInterval, locket.LockTTL)
				competingBBSLockProcess = ifrit.Invoke(competingBBSLock)

				bbsRunner = testrunner.New(bbsBinPath, bbsArgs)
				bbsRunner.StartCheck = "bbs.lock.acquiring-lock"

				bbsProcess = ginkgomon.Invoke(bbsRunner)
			})

			AfterEach(func() {
				ginkgomon.Kill(competingBBSLockProcess)
			})

			It("returns false", func() {
				Expect(client.Ping()).To(BeFalse())
			})
		})

		Context("when the BBS Server down", func() {
			It("returns false", func() {
				Expect(client.Ping()).To(BeFalse())
			})
		})
	})
})
<commit_msg>Simplify cmd/bbs Ping() test<commit_after>package main_test

import (
	"github.com/cloudfoundry-incubator/bbs/cmd/bbs/testrunner"
	"github.com/cloudfoundry-incubator/locket"
	"github.com/pivotal-golang/clock"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/ginkgomon"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Ping API", func() {
	Describe("Ping", func() {
		It("returns true when the bbs is running", func() {
			defer ginkgomon.Kill(bbsProcess)

			By("having the bbs down", func() {
				Expect(client.Ping()).To(BeFalse())
			})

			By("starting the bbs without a lock", func() {
				competingBBSLock := locket.NewLock(logger, consulClient, locket.LockSchemaPath("bbs_lock"), []byte{}, clock.NewClock(), locket.RetryInterval, locket.LockTTL)
				competingBBSLockProcess := ifrit.Invoke(competingBBSLock)
				defer ginkgomon.Kill(competingBBSLockProcess)

				bbsRunner = testrunner.New(bbsBinPath, bbsArgs)
				bbsRunner.StartCheck = "bbs.lock.acquiring-lock"
				bbsProcess = ginkgomon.Invoke(bbsRunner)

				Expect(client.Ping()).To(BeFalse())
			})

			By("finally acquiring the lock", func() {
				Eventually(client.Ping).Should(BeTrue())
			})
		})
	})
})
<|endoftext|>


<commit_before>// Copyright (c) 2013-2015 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"io/ioutil"
	"net"
	"os"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/btcsuite/btcd/btcjson"
	"github.com/btcsuite/btcutil"
	flags "github.com/jessevdk/go-flags"
)

const (
	// unusableFlags are the command usage flags which this utility are not
	// able to use.  In particular it doesn't support websockets and
	// consequently notifications.
	unusableFlags = btcjson.UFWebsocketOnly | btcjson.UFNotification
)

var (
	btcdHomeDir           = btcutil.AppDataDir("btcd", false)
	btcctlHomeDir         = btcutil.AppDataDir("btcctl", false)
	btcwalletHomeDir      = btcutil.AppDataDir("btcwallet", false)
	defaultConfigFile     = filepath.Join(btcctlHomeDir, "btcctl.conf")
	defaultRPCServer      = "localhost"
	defaultRPCCertFile    = filepath.Join(btcdHomeDir, "rpc.cert")
	defaultWalletCertFile = filepath.Join(btcwalletHomeDir, "rpc.cert")
)

// listCommands categorizes and lists all of the usable commands along with
// their one-line usage.
func listCommands() {
	const (
		categoryChain uint8 = iota
		categoryWallet
		numCategories
	)

	// Get a list of registered commands and categorize and filter them.
	cmdMethods := btcjson.RegisteredCmdMethods()
	categorized := make([][]string, numCategories)
	for _, method := range cmdMethods {
		flags, err := btcjson.MethodUsageFlags(method)
		if err != nil {
			// This should never happen since the method was just
			// returned from the package, but be safe.
			continue
		}

		// Skip the commands that aren't usable from this utility.
		if flags&unusableFlags != 0 {
			continue
		}

		usage, err := btcjson.MethodUsageText(method)
		if err != nil {
			// This should never happen since the method was just
			// returned from the package, but be safe.
			continue
		}

		// Categorize the command based on the usage flags.
		category := categoryChain
		if flags&btcjson.UFWalletOnly != 0 {
			category = categoryWallet
		}
		categorized[category] = append(categorized[category], usage)
	}

	// Display the command according to their categories.
	categoryTitles := make([]string, numCategories)
	categoryTitles[categoryChain] = "Chain Server Commands:"
	categoryTitles[categoryWallet] = "Wallet Server Commands (--wallet):"
	for category := uint8(0); category < numCategories; category++ {
		fmt.Println(categoryTitles[category])
		for _, usage := range categorized[category] {
			fmt.Println(usage)
		}
		fmt.Println()
	}
}

// config defines the configuration options for btcctl.
//
// See loadConfig for details on the configuration load process.
type config struct {
	ShowVersion   bool   `short:"V" long:"version" description:"Display version information and exit"`
	ListCommands  bool   `short:"l" long:"listcommands" description:"List all of the supported commands and exit"`
	ConfigFile    string `short:"C" long:"configfile" description:"Path to configuration file"`
	RPCUser       string `short:"u" long:"rpcuser" description:"RPC username"`
	RPCPassword   string `short:"P" long:"rpcpass" default-mask:"-" description:"RPC password"`
	RPCServer     string `short:"s" long:"rpcserver" description:"RPC server to connect to"`
	RPCCert       string `short:"c" long:"rpccert" description:"RPC server certificate chain for validation"`
	NoTLS         bool   `long:"notls" description:"Disable TLS"`
	Proxy         string `long:"proxy" description:"Connect via SOCKS5 proxy (eg. 127.0.0.1:9050)"`
	ProxyUser     string `long:"proxyuser" description:"Username for proxy server"`
	ProxyPass     string `long:"proxypass" default-mask:"-" description:"Password for proxy server"`
	TestNet3      bool   `long:"testnet" description:"Connect to testnet"`
	SimNet        bool   `long:"simnet" description:"Connect to the simulation test network"`
	TLSSkipVerify bool   `long:"skipverify" description:"Do not verify tls certificates (not recommended!)"`
	Wallet        bool   `long:"wallet" description:"Connect to wallet"`
}

// normalizeAddress returns addr with the passed default port appended if
// there is not already a port specified.
func normalizeAddress(addr string, useTestNet3, useSimNet, useWallet bool) string {
	_, _, err := net.SplitHostPort(addr)
	if err != nil {
		var defaultPort string
		switch {
		case useTestNet3:
			if useWallet {
				defaultPort = "18332"
			} else {
				defaultPort = "18334"
			}
		case useSimNet:
			if useWallet {
				defaultPort = "18554"
			} else {
				defaultPort = "18556"
			}
		default:
			if useWallet {
				defaultPort = "8332"
			} else {
				defaultPort = "8334"
			}
		}

		return net.JoinHostPort(addr, defaultPort)
	}
	return addr
}

// cleanAndExpandPath expands environement variables and leading ~ in the
// passed path, cleans the result, and returns it.
func cleanAndExpandPath(path string) string {
	// Expand initial ~ to OS specific home directory.
	if strings.HasPrefix(path, "~") {
		homeDir := filepath.Dir(btcctlHomeDir)
		path = strings.Replace(path, "~", homeDir, 1)
	}

	// NOTE: The os.ExpandEnv doesn't work with Windows-style %VARIABLE%,
	// but they variables can still be expanded via POSIX-style $VARIABLE.
	return filepath.Clean(os.ExpandEnv(path))
}

// loadConfig initializes and parses the config using a config file and command
// line options.
//
// The configuration proceeds as follows:
// 	1) Start with a default config with sane settings
// 	2) Pre-parse the command line to check for an alternative config file
// 	3) Load configuration file overwriting defaults with any specified options
// 	4) Parse CLI options and overwrite/add any specified options
//
// The above results in functioning properly without any config settings
// while still allowing the user to override settings with config files and
// command line options.  Command line options always take precedence.
func loadConfig() (*config, []string, error) {
	// Default config.
	cfg := config{
		ConfigFile: defaultConfigFile,
		RPCServer:  defaultRPCServer,
		RPCCert:    defaultRPCCertFile,
	}

	// Pre-parse the command line options to see if an alternative config
	// file, the version flag, or the list commands flag was specified.  Any
	// errors aside from the help message error can be ignored here since
	// they will be caught by the final parse below.
	preCfg := cfg
	preParser := flags.NewParser(&preCfg, flags.HelpFlag)
	_, err := preParser.Parse()
	if err != nil {
		if e, ok := err.(*flags.Error); ok && e.Type == flags.ErrHelp {
			fmt.Fprintln(os.Stderr, err)
			fmt.Fprintln(os.Stderr, "")
			fmt.Fprintln(os.Stderr, "The special parameter `-` "+
				"indicates that a parameter should be read "+
				"from the\nnext unread line from standard "+
				"input.")
			return nil, nil, err
		}
	}

	// Show the version and exit if the version flag was specified.
	appName := filepath.Base(os.Args[0])
	appName = strings.TrimSuffix(appName, filepath.Ext(appName))
	usageMessage := fmt.Sprintf("Use %s -h to show options", appName)
	if preCfg.ShowVersion {
		fmt.Println(appName, "version", version())
		os.Exit(0)
	}

	// Show the available commands and exit if the associated flag was
	// specified.
	if preCfg.ListCommands {
		listCommands()
		os.Exit(0)
	}

	if _, err := os.Stat(preCfg.ConfigFile); os.IsNotExist(err) {
		err := createDefaultConfigFile(preCfg.ConfigFile)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error creating a default config file: %v\n", err)
		}
	}

	// Load additional config from file.
	parser := flags.NewParser(&cfg, flags.Default)
	err = flags.NewIniParser(parser).ParseFile(preCfg.ConfigFile)
	if err != nil {
		if _, ok := err.(*os.PathError); !ok {
			fmt.Fprintf(os.Stderr, "Error parsing config file: %v\n",
				err)
			fmt.Fprintln(os.Stderr, usageMessage)
			return nil, nil, err
		}
	}

	// Parse command line options again to ensure they take precedence.
	remainingArgs, err := parser.Parse()
	if err != nil {
		if e, ok := err.(*flags.Error); !ok || e.Type != flags.ErrHelp {
			fmt.Fprintln(os.Stderr, usageMessage)
		}
		return nil, nil, err
	}

	// Multiple networks can't be selected simultaneously.
	numNets := 0
	if cfg.TestNet3 {
		numNets++
	}
	if cfg.SimNet {
		numNets++
	}
	if numNets > 1 {
		str := "%s: The testnet and simnet params can't be used " +
			"together -- choose one of the two"
		err := fmt.Errorf(str, "loadConfig")
		fmt.Fprintln(os.Stderr, err)
		return nil, nil, err
	}

	// Override the RPC certificate if the --wallet flag was specified and
	// the user did not specify one.
	if cfg.Wallet && cfg.RPCCert == defaultRPCCertFile {
		cfg.RPCCert = defaultWalletCertFile
	}

	// Handle environment variable expansion in the RPC certificate path.
	cfg.RPCCert = cleanAndExpandPath(cfg.RPCCert)

	// Add default port to RPC server based on --testnet and --wallet flags
	// if needed.
	cfg.RPCServer = normalizeAddress(cfg.RPCServer, cfg.TestNet3,
		cfg.SimNet, cfg.Wallet)

	return &cfg, remainingArgs, nil
}

// createDefaultConfig creates a basic config file at the given destination path.
// For this it tries to read the btcd config file at its default path, and extract
// the RPC user and password from it.
func createDefaultConfigFile(destinationPath string) error {
	// Read btcd.conf from its default path
	btcdConfigPath := filepath.Join(btcdHomeDir, "btcd.conf")
	btcdConfigFile, err := os.Open(btcdConfigPath)
	if err != nil {
		return err
	}
	defer btcdConfigFile.Close()
	content, err := ioutil.ReadAll(btcdConfigFile)
	if err != nil {
		return err
	}

	// Extract the rpcuser
	rpcUserRegexp, err := regexp.Compile(`(?m)^\s*rpcuser=([^\s]+)`)
	if err != nil {
		return err
	}
	userSubmatches := rpcUserRegexp.FindSubmatch(content)
	if userSubmatches == nil {
		// No user found, nothing to do
		return nil
	}

	// Extract the rpcpass
	rpcPassRegexp, err := regexp.Compile(`(?m)^\s*rpcpass=([^\s]+)`)
	if err != nil {
		return err
	}
	passSubmatches := rpcPassRegexp.FindSubmatch(content)
	if passSubmatches == nil {
		// No password found, nothing to do
		return nil
	}

	// Create the destination directory if it does not exists
	err = os.MkdirAll(filepath.Dir(destinationPath), 0700)
	if err != nil {
		return err
	}

	// Create the destination file and write the rpcuser and rpcpass to it
	dest, err := os.OpenFile(destinationPath,
		os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		return err
	}
	defer dest.Close()

	dest.WriteString(fmt.Sprintf("rpcuser=%s\nrpcpass=%s",
		string(userSubmatches[1]), string(passSubmatches[1])))

	return nil
}
<commit_msg>btcctl: Inherit notls config from btcd.conf<commit_after>// Copyright (c) 2013-2015 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"io/ioutil"
	"net"
	"os"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/btcsuite/btcd/btcjson"
	"github.com/btcsuite/btcutil"
	flags "github.com/jessevdk/go-flags"
)

const (
	// unusableFlags are the command usage flags which this utility are not
	// able to use.  In particular it doesn't support websockets and
	// consequently notifications.
	unusableFlags = btcjson.UFWebsocketOnly | btcjson.UFNotification
)

var (
	btcdHomeDir           = btcutil.AppDataDir("btcd", false)
	btcctlHomeDir         = btcutil.AppDataDir("btcctl", false)
	btcwalletHomeDir      = btcutil.AppDataDir("btcwallet", false)
	defaultConfigFile     = filepath.Join(btcctlHomeDir, "btcctl.conf")
	defaultRPCServer      = "localhost"
	defaultRPCCertFile    = filepath.Join(btcdHomeDir, "rpc.cert")
	defaultWalletCertFile = filepath.Join(btcwalletHomeDir, "rpc.cert")
)

// listCommands categorizes and lists all of the usable commands along with
// their one-line usage.
func listCommands() {
	const (
		categoryChain uint8 = iota
		categoryWallet
		numCategories
	)

	// Get a list of registered commands and categorize and filter them.
	cmdMethods := btcjson.RegisteredCmdMethods()
	categorized := make([][]string, numCategories)
	for _, method := range cmdMethods {
		flags, err := btcjson.MethodUsageFlags(method)
		if err != nil {
			// This should never happen since the method was just
			// returned from the package, but be safe.
			continue
		}

		// Skip the commands that aren't usable from this utility.
		if flags&unusableFlags != 0 {
			continue
		}

		usage, err := btcjson.MethodUsageText(method)
		if err != nil {
			// This should never happen since the method was just
			// returned from the package, but be safe.
			continue
		}

		// Categorize the command based on the usage flags.
		category := categoryChain
		if flags&btcjson.UFWalletOnly != 0 {
			category = categoryWallet
		}
		categorized[category] = append(categorized[category], usage)
	}

	// Display the command according to their categories.
	categoryTitles := make([]string, numCategories)
	categoryTitles[categoryChain] = "Chain Server Commands:"
	categoryTitles[categoryWallet] = "Wallet Server Commands (--wallet):"
	for category := uint8(0); category < numCategories; category++ {
		fmt.Println(categoryTitles[category])
		for _, usage := range categorized[category] {
			fmt.Println(usage)
		}
		fmt.Println()
	}
}

// config defines the configuration options for btcctl.
//
// See loadConfig for details on the configuration load process.
type config struct {
	ShowVersion   bool   `short:"V" long:"version" description:"Display version information and exit"`
	ListCommands  bool   `short:"l" long:"listcommands" description:"List all of the supported commands and exit"`
	ConfigFile    string `short:"C" long:"configfile" description:"Path to configuration file"`
	RPCUser       string `short:"u" long:"rpcuser" description:"RPC username"`
	RPCPassword   string `short:"P" long:"rpcpass" default-mask:"-" description:"RPC password"`
	RPCServer     string `short:"s" long:"rpcserver" description:"RPC server to connect to"`
	RPCCert       string `short:"c" long:"rpccert" description:"RPC server certificate chain for validation"`
	NoTLS         bool   `long:"notls" description:"Disable TLS"`
	Proxy         string `long:"proxy" description:"Connect via SOCKS5 proxy (eg. 127.0.0.1:9050)"`
	ProxyUser     string `long:"proxyuser" description:"Username for proxy server"`
	ProxyPass     string `long:"proxypass" default-mask:"-" description:"Password for proxy server"`
	TestNet3      bool   `long:"testnet" description:"Connect to testnet"`
	SimNet        bool   `long:"simnet" description:"Connect to the simulation test network"`
	TLSSkipVerify bool   `long:"skipverify" description:"Do not verify tls certificates (not recommended!)"`
	Wallet        bool   `long:"wallet" description:"Connect to wallet"`
}

// normalizeAddress returns addr with the passed default port appended if
// there is not already a port specified.
func normalizeAddress(addr string, useTestNet3, useSimNet, useWallet bool) string {
	_, _, err := net.SplitHostPort(addr)
	if err != nil {
		var defaultPort string
		switch {
		case useTestNet3:
			if useWallet {
				defaultPort = "18332"
			} else {
				defaultPort = "18334"
			}
		case useSimNet:
			if useWallet {
				defaultPort = "18554"
			} else {
				defaultPort = "18556"
			}
		default:
			if useWallet {
				defaultPort = "8332"
			} else {
				defaultPort = "8334"
			}
		}

		return net.JoinHostPort(addr, defaultPort)
	}
	return addr
}

// cleanAndExpandPath expands environement variables and leading ~ in the
// passed path, cleans the result, and returns it.
func cleanAndExpandPath(path string) string {
	// Expand initial ~ to OS specific home directory.
	if strings.HasPrefix(path, "~") {
		homeDir := filepath.Dir(btcctlHomeDir)
		path = strings.Replace(path, "~", homeDir, 1)
	}

	// NOTE: The os.ExpandEnv doesn't work with Windows-style %VARIABLE%,
	// but they variables can still be expanded via POSIX-style $VARIABLE.
	return filepath.Clean(os.ExpandEnv(path))
}

// loadConfig initializes and parses the config using a config file and command
// line options.
//
// The configuration proceeds as follows:
// 	1) Start with a default config with sane settings
// 	2) Pre-parse the command line to check for an alternative config file
// 	3) Load configuration file overwriting defaults with any specified options
// 	4) Parse CLI options and overwrite/add any specified options
//
// The above results in functioning properly without any config settings
// while still allowing the user to override settings with config files and
// command line options.  Command line options always take precedence.
func loadConfig() (*config, []string, error) {
	// Default config.
	cfg := config{
		ConfigFile: defaultConfigFile,
		RPCServer:  defaultRPCServer,
		RPCCert:    defaultRPCCertFile,
	}

	// Pre-parse the command line options to see if an alternative config
	// file, the version flag, or the list commands flag was specified.  Any
	// errors aside from the help message error can be ignored here since
	// they will be caught by the final parse below.
	preCfg := cfg
	preParser := flags.NewParser(&preCfg, flags.HelpFlag)
	_, err := preParser.Parse()
	if err != nil {
		if e, ok := err.(*flags.Error); ok && e.Type == flags.ErrHelp {
			fmt.Fprintln(os.Stderr, err)
			fmt.Fprintln(os.Stderr, "")
			fmt.Fprintln(os.Stderr, "The special parameter `-` "+
				"indicates that a parameter should be read "+
				"from the\nnext unread line from standard "+
				"input.")
			return nil, nil, err
		}
	}

	// Show the version and exit if the version flag was specified.
	appName := filepath.Base(os.Args[0])
	appName = strings.TrimSuffix(appName, filepath.Ext(appName))
	usageMessage := fmt.Sprintf("Use %s -h to show options", appName)
	if preCfg.ShowVersion {
		fmt.Println(appName, "version", version())
		os.Exit(0)
	}

	// Show the available commands and exit if the associated flag was
	// specified.
	if preCfg.ListCommands {
		listCommands()
		os.Exit(0)
	}

	if _, err := os.Stat(preCfg.ConfigFile); os.IsNotExist(err) {
		err := createDefaultConfigFile(preCfg.ConfigFile)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error creating a default config file: %v\n", err)
		}
	}

	// Load additional config from file.
	parser := flags.NewParser(&cfg, flags.Default)
	err = flags.NewIniParser(parser).ParseFile(preCfg.ConfigFile)
	if err != nil {
		if _, ok := err.(*os.PathError); !ok {
			fmt.Fprintf(os.Stderr, "Error parsing config file: %v\n",
				err)
			fmt.Fprintln(os.Stderr, usageMessage)
			return nil, nil, err
		}
	}

	// Parse command line options again to ensure they take precedence.
	remainingArgs, err := parser.Parse()
	if err != nil {
		if e, ok := err.(*flags.Error); !ok || e.Type != flags.ErrHelp {
			fmt.Fprintln(os.Stderr, usageMessage)
		}
		return nil, nil, err
	}

	// Multiple networks can't be selected simultaneously.
	numNets := 0
	if cfg.TestNet3 {
		numNets++
	}
	if cfg.SimNet {
		numNets++
	}
	if numNets > 1 {
		str := "%s: The testnet and simnet params can't be used " +
			"together -- choose one of the two"
		err := fmt.Errorf(str, "loadConfig")
		fmt.Fprintln(os.Stderr, err)
		return nil, nil, err
	}

	// Override the RPC certificate if the --wallet flag was specified and
	// the user did not specify one.
	if cfg.Wallet && cfg.RPCCert == defaultRPCCertFile {
		cfg.RPCCert = defaultWalletCertFile
	}

	// Handle environment variable expansion in the RPC certificate path.
	cfg.RPCCert = cleanAndExpandPath(cfg.RPCCert)

	// Add default port to RPC server based on --testnet and --wallet flags
	// if needed.
	cfg.RPCServer = normalizeAddress(cfg.RPCServer, cfg.TestNet3,
		cfg.SimNet, cfg.Wallet)

	return &cfg, remainingArgs, nil
}

// createDefaultConfig creates a basic config file at the given destination path.
// For this it tries to read the btcd config file at its default path, and extract
// the RPC user and password from it.
func createDefaultConfigFile(destinationPath string) error {
	// Read btcd.conf from its default path
	btcdConfigPath := filepath.Join(btcdHomeDir, "btcd.conf")
	btcdConfigFile, err := os.Open(btcdConfigPath)
	if err != nil {
		return err
	}
	defer btcdConfigFile.Close()
	content, err := ioutil.ReadAll(btcdConfigFile)
	if err != nil {
		return err
	}

	// Extract the rpcuser
	rpcUserRegexp, err := regexp.Compile(`(?m)^\s*rpcuser=([^\s]+)`)
	if err != nil {
		return err
	}
	userSubmatches := rpcUserRegexp.FindSubmatch(content)
	if userSubmatches == nil {
		// No user found, nothing to do
		return nil
	}

	// Extract the rpcpass
	rpcPassRegexp, err := regexp.Compile(`(?m)^\s*rpcpass=([^\s]+)`)
	if err != nil {
		return err
	}
	passSubmatches := rpcPassRegexp.FindSubmatch(content)
	if passSubmatches == nil {
		// No password found, nothing to do
		return nil
	}

	// Extract the notls
	noTLSRegexp, err := regexp.Compile(`(?m)^\s*notls=(0|1)(?:\s|$)`)
	if err != nil {
		return err
	}
	noTLSSubmatches := noTLSRegexp.FindSubmatch(content)

	// Create the destination directory if it does not exists
	err = os.MkdirAll(filepath.Dir(destinationPath), 0700)
	if err != nil {
		return err
	}

	// Create the destination file and write the rpcuser and rpcpass to it
	dest, err := os.OpenFile(destinationPath,
		os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		return err
	}
	defer dest.Close()

	destString := fmt.Sprintf("rpcuser=%s\nrpcpass=%s\n",
		string(userSubmatches[1]), string(passSubmatches[1]))
	if noTLSSubmatches != nil {
		destString += fmt.Sprintf("notls=%s\n", noTLSSubmatches[1])
	}

	dest.WriteString(destString)

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	"github.com/docker/docker/cow"
	"github.com/docker/docker/pkg/mflag"
)

func exist(flags *mflag.FlagSet, action string, m cow.Mall, args []string) int {
	if len(args) < 1 {
		return 1
	}
	allExist := true
	for _, what := range args {
		exists := m.Exists(what)
		fmt.Fprintf(os.Stderr, "%s: %v\n", what, exists)
		allExist = allExist && exists
	}
	if !allExist {
		return 1
	}
	return 0
}

func init() {
	commands = append(commands, command{
		names:       []string{"exists"},
		optionsHelp: "[LayerOrImageOrContainerNameOrID [...]]",
		usage:       "Check if a layer or image or container exists",
		minArgs:     1,
		action:      exist,
	})
}
<commit_msg>Make "exists" print to stdout, add a -q option<commit_after>package main

import (
	"fmt"

	"github.com/docker/docker/cow"
	"github.com/docker/docker/pkg/mflag"
)

var existQuiet = false

func exist(flags *mflag.FlagSet, action string, m cow.Mall, args []string) int {
	if len(args) < 1 {
		return 1
	}
	allExist := true
	for _, what := range args {
		exists := m.Exists(what)
		if !existQuiet {
			fmt.Printf("%s: %v\n", what, exists)
		}
		allExist = allExist && exists
	}
	if !allExist {
		return 1
	}
	return 0
}

func init() {
	commands = append(commands, command{
		names:       []string{"exists"},
		optionsHelp: "[LayerOrImageOrContainerNameOrID [...]]",
		usage:       "Check if a layer or image or container exists",
		minArgs:     1,
		action:      exist,
		addFlags: func(flags *mflag.FlagSet, cmd *command) {
			flags.BoolVar(&existQuiet, []string{"-quiet", "q"}, existQuiet, "Don't print names")
		},
	})
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"

	"github.com/google/uuid"
	"github.com/pkg/errors"
)

type Scout struct {
	installID string
	index     int
	metadata  map[string]interface{}
}

type ScoutMeta struct {
	Key   string
	Value interface{}
}

func NewScout(mode string) (s *Scout) {
	// Fixed (growing) metadata passed with every report
	metadata := make(map[string]interface{})
	metadata["mode"] = mode
	metadata["trace_id"] = uuid.New().String()

	// The result
	s = &Scout{metadata: metadata}

	// Get or create the persistent install ID for Edge Control
	err := func() error {
		// We store the persistent ID in ~/.config/edgectl/id to be consistent
		// with Telepresence. We could instead use os.UserConfigDir() as the
		// root of the destination, which may be the same on Linux, but is
		// definitely different on MacOS.
		home, err := os.UserHomeDir()
		if err != nil {
			return err
		}
		configDir := filepath.Join(home, ".config", "edgectl")
		if err := os.MkdirAll(configDir, 0755); err != nil {
			return err
		}
		idFilename := filepath.Join(configDir, "id")

		// Try to read an existing install ID
		if installIDBytes, err := ioutil.ReadFile(idFilename); err == nil {
			s.installID = string(installIDBytes)
			// Validate UUID format
			if _, err := uuid.Parse(s.installID); err == nil {
				metadata["new_install"] = false
				return nil
			} // else the value is not a UUID
		} // else file doesn't exist, etc.

		// Try to create a new install ID
		s.installID = uuid.New().String()
		metadata["new_install"] = true
		if err := ioutil.WriteFile(idFilename, []byte(s.installID), 0755); err != nil {
			return err
		}
		return nil
	}()
	if err != nil {
		s.installID = "00000000-0000-0000-0000-000000000000"
		metadata["new_install"] = true
		metadata["install_id_error"] = err.Error()
	}

	return
}

func (s *Scout) SetMetadatum(key string, value interface{}) {
	oldValue, ok := s.metadata[key]
	if ok {
		panic(fmt.Sprintf("trying to replace metadata[%q] = %q with %q", key, oldValue, value))
	}
	s.metadata[key] = value
}

func (s *Scout) Report(action string, meta ...ScoutMeta) error {
	if os.Getenv("SCOUT_DISABLE") != "" {
		return nil
	}

	// Construct the report's metadata. Include the fixed (growing) set of
	// metadata in the Scout structure and the pairs passed as arguments to this
	// call. Also include and increment the index, which can be used to
	// determine the correct order of reported events for this installation
	// attempt (correlated by the trace_id set at the start).
	s.index++
	metadata := map[string]interface{}{
		"action": action,
		"index":  s.index,
	}
	for metaKey, metaValue := range s.metadata {
		metadata[metaKey] = metaValue
	}
	for _, metaItem := range meta {
		metadata[metaItem.Key] = metaItem.Value
	}

	data := map[string]interface{}{
		"application": "edgectl",
		"install_id":  s.installID,
		"version":     Version,
		"metadata":    metadata,
	}

	body, err := json.MarshalIndent(data, "", "  ")
	if err != nil {
		panic(err)
	}
	metritonEndpoint := "https://metriton.datawire.io/scout"
	resp, err := http.Post(metritonEndpoint, "application/json", bytes.NewBuffer(body))
	if err != nil {
		return errors.Wrap(err, "scout report")
	}

	// TODO: Do something useful (?) with the response?
	_, _ = ioutil.ReadAll(resp.Body)
	_ = resp.Body.Close()

	return nil
}
<commit_msg>Add a common pkg/metriton (mimicing scout.py) so we can stop reinventing that wheel<commit_after>package main

import (
	"fmt"

	"github.com/google/uuid"
	"github.com/pkg/errors"

	"github.com/datawire/ambassador/pkg/metriton"
)

type Scout struct {
	index    int
	reporter *metriton.Reporter
}

type ScoutMeta struct {
	Key   string
	Value interface{}
}

func NewScout(mode string) (s *Scout) {
	return &Scout{
		reporter: &metriton.Reporter{
			Application: "edgectl",
			Version:     Version,
			GetInstallID: func(r *metriton.Reporter) (string, error) {
				id, err := metriton.InstallIDFromFilesystem(r)
				if err != nil {
					id = "00000000-0000-0000-0000-000000000000"
					r.BaseMetadata["new_install"] = true
					r.BaseMetadata["install_id_error"] = err.Error()
				}
				return id, nil
			},
			// Fixed (growing) metadata passed with every report
			BaseMetadata: map[string]interface{}{
				"mode":     mode,
				"trace_id": uuid.New().String(),
			},
		},
	}
}

func (s *Scout) SetMetadatum(key string, value interface{}) {
	oldValue, ok := s.reporter.BaseMetadata[key]
	if ok {
		panic(fmt.Sprintf("trying to replace metadata[%q] = %q with %q", key, oldValue, value))
	}
	s.reporter.BaseMetadata[key] = value
}

func (s *Scout) Report(action string, meta ...ScoutMeta) error {
	// Construct the report's metadata. Include the fixed (growing) set of
	// metadata in the Scout structure and the pairs passed as arguments to this
	// call. Also include and increment the index, which can be used to
	// determine the correct order of reported events for this installation
	// attempt (correlated by the trace_id set at the start).
	s.index++
	metadata := map[string]interface{}{
		"action": action,
		"index":  s.index,
	}
	for _, metaItem := range meta {
		metadata[metaItem.Key] = metaItem.Value
	}

	_, err := s.reporter.Report(metadata)
	if err != nil {
		return errors.Wrap(err, "scout report")
	}
	// TODO: Do something useful (alert the user if there's an available
	// upgrade?) with the response (discarded as "_" above)?

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"os"

	"github.com/google/go-github/github"
	"github.com/spf13/cobra"
	"k8s.io/kops/util/pkg/tables"
)

type GetRepoOptions struct {
	Name      string
	IsPrivate string
}

func NewCmdGetRepos(out io.Writer) *cobra.Command {
	options := &GetRepoOptions{}

	cmd := &cobra.Command{
		Use:   "repos",
		Short: "Get repo",
		Long:  `Gets the list of Github repos for the logged user`,
		Run: func(cmd *cobra.Command, args []string) {
			err := RunGetRepos(cmd, args, out, options)
			if err != nil {
				exitWithError(err)
			}
		},
	}

	return cmd
}

func RunGetRepos(cmd *cobra.Command, args []string, out io.Writer, c *GetRepoOptions) error {
	var user string
	if len(args) > 0 {
		return cmd.Help()
	}
	client := rootCommand.gclient.GetClient()
	if len(args) == 0 {
		user = rootCommand.gclient.User
	}
	opt := &github.RepositoryListOptions{Type: "all", Sort: "updated"}
	repos, _, err := client.Repositories.List(user, opt)
	if err != nil {
		exitWithError(fmt.Errorf("Error Getting Repos"))
	}
	if len(repos) == 0 {
		fmt.Fprintf(os.Stderr, "No repos found\n")
		return nil
	}
	t := &tables.Table{}
	t.AddColumn("REPO", func(r *github.Repository) string {
		return *r.HTMLURL
	})
	t.AddColumn("LANGUAGE", func(r *github.Repository) string {
		if r.Language != nil {
			return *r.Language
		} else {
			return "-"
		}
	})
	t.AddColumn("STARS", func(r *github.Repository) int {
		return *r.StargazersCount
	})
	t.AddColumn("FORKS", func(r *github.Repository) int {
		return *r.ForksCount
	})
	return t.Render(repos, os.Stdout, "REPO", "LANGUAGE", "STARS", "FORKS")
}
<commit_msg>Add tablewrite and remove k8s.io/tables<commit_after>package main

import (
	"fmt"
	"io"
	"os"
	"strconv"

	"github.com/google/go-github/github"
	"github.com/olekukonko/tablewriter"
	"github.com/spf13/cobra"
)

type GetRepoOptions struct {
	Name      string
	IsPrivate string
}

func NewCmdGetRepos(out io.Writer) *cobra.Command {
	options := &GetRepoOptions{}

	cmd := &cobra.Command{
		Use:   "repos",
		Short: "Get repo",
		Long:  `Gets the list of Github repos for the logged user`,
		Run: func(cmd *cobra.Command, args []string) {
			err := RunGetRepos(cmd, args, out, options)
			if err != nil {
				exitWithError(err)
			}
		},
	}

	return cmd
}

func RunGetRepos(cmd *cobra.Command, args []string, out io.Writer, c *GetRepoOptions) error {
	var user string
	if len(args) > 0 {
		return cmd.Help()
	}
	client := rootCommand.gclient.GetClient()
	if len(args) == 0 {
		user = rootCommand.gclient.User
	}
	opt := &github.RepositoryListOptions{Type: "all", Sort: "updated"}
	repos, _, err := client.Repositories.List(user, opt)
	if err != nil {
		exitWithError(fmt.Errorf("Error Getting Repos"))
	}
	if len(repos) == 0 {
		fmt.Fprintf(os.Stderr, "No repos found\n")
		return nil
	}

	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"REPO", "LANGUAGE", "STARS", "FORKS"})

	for _, repo := range repos {
		table.Append([]string{*repo.HTMLURL, *repo.Language,
			strconv.Itoa(*repo.StargazersCount),
			strconv.Itoa(*repo.ForksCount)})
	}

	table.Render()

	return nil
}
<|endoftext|>


<commit_before>// The go-vcs program exposes go-vcs's library functionality through a
// command-line interface.
package main

import (
	"flag"
	"fmt"
	"log"
	"net/url"
	"os"
	"path/filepath"

	"github.com/kr/text"
	"github.com/sourcegraph/go-vcs/vcs"
	_ "github.com/sourcegraph/go-vcs/vcs/git_libgit2"
)

var (
	sshKeyFile = flag.String("i", "", "ssh key file")
)

func main() {
	log.SetFlags(0)
	flag.Parse()

	if flag.NArg() == 0 {
		log.Fatal("Must specify a subcommand.")
	}

	subcmd := flag.Arg(0)
	args := flag.Args()[1:]
	switch subcmd {
	case "git-clone-mirror":
		if len(args) != 2 {
			log.Fatal("git-clone requires 2 args: clone URL and dir.")
		}
		cloneURLStr, dir := args[0], args[1]

		cloneURL, err := url.Parse(cloneURLStr)
		if err != nil {
			log.Fatal(err)
		}

		if _, err := os.Stat(dir); !os.IsNotExist(err) {
			log.Fatalf("Clone destination dir must not exist: %s.", dir)
		}
		if _, err := os.Stat(filepath.Join(dir, "..")); err != nil {
			log.Fatalf("Clone destination dir parent must exist: %s.", filepath.Join(dir, ".."))
		}

		log.Printf("Cloning %s to %s...", cloneURL, dir)

		repo, err := vcs.CloneMirror("git", cloneURL.String(), dir)
		if err != nil {
			log.Fatal(err)
		}

		log.Printf("Cloned: %T.", repo)

	case "log":
		dir := args[0]

		repo, err := vcs.Open("git", dir)
		if err != nil {
			log.Fatal(err)
		}

		master, err := repo.ResolveRevision("master")
		if err != nil {
			log.Fatal(err)
		}

		commits, total, err := repo.Commits(vcs.CommitsOptions{Head: master})
		if err != nil {
			log.Fatal(err)
		}

		fmt.Printf("# Commits (%d total):", total)
		for _, c := range commits {
			fmt.Printf("%s\n%s <%s> at %s\n%s\n\n", c.ID, c.Author.Name, c.Author.Email, c.Author.Date, text.Indent(c.Message, "\t"))
		}
	}
}
<commit_msg>add "show" subcmd<commit_after>// The go-vcs program exposes go-vcs's library functionality through a
// command-line interface.
package main

import (
	"flag"
	"fmt"
	"log"
	"net/url"
	"os"
	"path/filepath"

	"github.com/kr/text"
	"github.com/sourcegraph/go-vcs/vcs"
	_ "github.com/sourcegraph/go-vcs/vcs/git_libgit2"
)

var (
	sshKeyFile = flag.String("i", "", "ssh key file")
)

func main() {
	log.SetFlags(0)
	flag.Parse()

	if flag.NArg() == 0 {
		log.Fatal("Must specify a subcommand.")
	}

	subcmd := flag.Arg(0)
	args := flag.Args()[1:]
	switch subcmd {
	case "git-clone-mirror":
		if len(args) != 2 {
			log.Fatal("git-clone requires 2 args: clone URL and dir.")
		}
		cloneURLStr, dir := args[0], args[1]

		cloneURL, err := url.Parse(cloneURLStr)
		if err != nil {
			log.Fatal(err)
		}

		if _, err := os.Stat(dir); !os.IsNotExist(err) {
			log.Fatalf("Clone destination dir must not exist: %s.", dir)
		}
		if _, err := os.Stat(filepath.Join(dir, "..")); err != nil {
			log.Fatalf("Clone destination dir parent must exist: %s.", filepath.Join(dir, ".."))
		}

		log.Printf("Cloning %s to %s...", cloneURL, dir)

		repo, err := vcs.CloneMirror("git", cloneURL.String(), dir)
		if err != nil {
			log.Fatal(err)
		}

		log.Printf("Cloned: %T.", repo)

	case "show":
		if len(args) != 1 {
			log.Fatal("show takes 1 argument (revspec).")
		}
		revspec := args[0]

		repo, err := vcs.Open("git", ".")
		if err != nil {
			log.Fatal(err)
		}

		commitID, err := repo.ResolveRevision(revspec)
		if err != nil {
			log.Fatal(err)
		}

		commit, err := repo.GetCommit(commitID)
		if err != nil {
			log.Fatal(err)
		}

		fmt.Printf("# Revspec %q resolves to commit %s:\n", revspec, commitID)
		printCommit(commit)

	case "log":
		if len(args) != 0 {
			log.Fatal("log takes no arguments.")
		}

		repo, err := vcs.Open("git", ".")
		if err != nil {
			log.Fatal(err)
		}

		master, err := repo.ResolveRevision("master")
		if err != nil {
			log.Fatal(err)
		}

		commits, total, err := repo.Commits(vcs.CommitsOptions{Head: master})
		if err != nil {
			log.Fatal(err)
		}

		fmt.Printf("# Commits (%d total):\n", total)
		for _, c := range commits {
			printCommit(c)
		}
	}
}

func printCommit(c *vcs.Commit) {
	fmt.Printf("%s\n%s <%s> at %s\n%s\n\n", c.ID, c.Author.Name, c.Author.Email, c.Author.Date, text.Indent(c.Message, "\t"))
}
<|endoftext|>


<commit_before>package main

import (
	"net/http"

	_ "net/http/pprof"

	"github.com/dzhou121/gonvim"
	"github.com/dzhou121/ui"
)

func main() {
	go func() {
		http.ListenAndServe("0.0.0.0:6080", nil)
	}()
	err := ui.Main(func() {
		gonvim.InitEditor()
	})
	if err != nil {
		panic(err)
	}
}
<commit_msg>Listen only on localhost<commit_after>package main

import (
	"net/http"

	_ "net/http/pprof"

	"github.com/dzhou121/gonvim"
	"github.com/dzhou121/ui"
)

func main() {
	go func() {
		http.ListenAndServe("localhost:6080", nil)
	}()
	err := ui.Main(func() {
		gonvim.InitEditor()
	})
	if err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"os/user"
	"path/filepath"

	"github.com/codegangsta/cli"
	"github.com/inconshreveable/log15"
	"github.com/materials-commons/config"
	"github.com/materials-commons/config/cfg"
	"github.com/materials-commons/config/handler"
	"github.com/materials-commons/config/loader"
	"github.com/materials-commons/gohandy/file"
	"github.com/materials-commons/mcstore/cmd/mccli"
	"github.com/materials-commons/mcstore/pkg/app"
)

// init sets up the package by loading and configuring the config package.
func init() {
	handler := setupConfigHandler()
	config.Init(handler)
	setLoggingLevel()
}

func main() {
	app := cli.NewApp()
	app.Version = "0.0.1"
	app.Authors = []cli.Author{
		{
			Name:  "V. Glenn Tarcea",
			Email: "gtarcea@umich.edu",
		},
	}
	app.Commands = []cli.Command{
		mccli.CreateCommand,
		mccli.SetupCommand,
		mccli.ShowCommand,
		mccli.UploadCommand,
		mccli.MkdirsCommand,
	}
	app.Run(os.Args)
}

// setupConfigHandler creates the handler for the mc package. It sets up a
// multi handler. If the user has setup a config.json in their .materialscommons
// directory then it will add that to the handler list. Handlers are searched in
// the following order: env - (optional) config file - defaults.
//
// This means that configuration set in the environment will override all other
// settings, then it will check the config file (if one is setup), and finally
// it will use the defaults.
func setupConfigHandler() cfg.Handler {
	u, err := user.Current()
	if err != nil {
		panic(fmt.Sprintf("Couldn't determine current user: %s", err))
	}

	// Set up the handlers. The order matters as it will search for
	// configuration entries first to last, stopping when it finds
	// one. This means that each entry overrides settings below it.
	handlers := []cfg.Handler{
		handler.Env(),
	}

	configFile := filepath.Join(u.HomeDir, ".materialscommons/config.json")
	if loader := getUserConfigLoader(configFile); loader != nil {
		handlers = append(handlers, handler.Loader(loader))
	}

	defaultHandler := handler.Map()
	loadDefaults(defaultHandler)
	handlers = append(handlers, defaultHandler)
	return handler.Sync(handler.Multi(handlers...))
}

// getUserConfigLoader returns a json loader if the $HOME/.materialscommons/config.json
// file exists. It will panic if the file exists but cannot be read.
func getUserConfigLoader(configFile string) cfg.Loader {
	if file.Exists(configFile) {
		contents, err := ioutil.ReadFile(configFile)
		if err != nil {
			panic(fmt.Sprintf("%s exists but can't be read: %s", configFile, err))
		}
		return loader.JSON(bytes.NewReader(contents))
	}
	return nil
}

// loadDefaults sets up the default values for the following configuration keys:
//     mcurl: https://materialscommons.org/api
//     mclogging: info
func loadDefaults(h cfg.Handler) {
	h.Set("mcurl", "https://materialscommons.org/api")
	h.Set("mclogging", "info")
}

// setLoggingLevel sets the apps logging level.
func setLoggingLevel() {
	level := config.GetString("mclogging")
	if lvl, err := log15.LvlFromString(level); err != nil {
		fmt.Printf("Invalid Log Level: %s, setting to info.\n", level)
		fmt.Println("Valid logging levels are: debug, info, warn, error, crit. The default is info.")
		app.SetLogLvl(log15.LvlInfo)
	} else {
		app.SetLogLvl(lvl)
	}
}
<commit_msg>Add watch command to mc command list.<commit_after>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"os/user"
	"path/filepath"

	"github.com/codegangsta/cli"
	"github.com/inconshreveable/log15"
	"github.com/materials-commons/config"
	"github.com/materials-commons/config/cfg"
	"github.com/materials-commons/config/handler"
	"github.com/materials-commons/config/loader"
	"github.com/materials-commons/gohandy/file"
	"github.com/materials-commons/mcstore/cmd/mccli"
	"github.com/materials-commons/mcstore/pkg/app"
)

// init sets up the package by loading and configuring the config package.
func init() {
	handler := setupConfigHandler()
	config.Init(handler)
	setLoggingLevel()
}

func main() {
	app := cli.NewApp()
	app.Version = "0.0.1"
	app.Authors = []cli.Author{
		{
			Name:  "V. Glenn Tarcea",
			Email: "gtarcea@umich.edu",
		},
	}
	app.Commands = []cli.Command{
		mccli.CreateCommand,
		mccli.SetupCommand,
		mccli.ShowCommand,
		mccli.UploadCommand,
		mccli.MkdirsCommand,
		mccli.WatchCommand,
	}
	app.Run(os.Args)
}

// setupConfigHandler creates the handler for the mc package. It sets up a
// multi handler. If the user has setup a config.json in their .materialscommons
// directory then it will add that to the handler list. Handlers are searched in
// the following order: env - (optional) config file - defaults.
//
// This means that configuration set in the environment will override all other
// settings, then it will check the config file (if one is setup), and finally
// it will use the defaults.
func setupConfigHandler() cfg.Handler {
	u, err := user.Current()
	if err != nil {
		panic(fmt.Sprintf("Couldn't determine current user: %s", err))
	}

	// Set up the handlers. The order matters as it will search for
	// configuration entries first to last, stopping when it finds
	// one. This means that each entry overrides settings below it.
	handlers := []cfg.Handler{
		handler.Env(),
	}

	configFile := filepath.Join(u.HomeDir, ".materialscommons/config.json")
	if loader := getUserConfigLoader(configFile); loader != nil {
		handlers = append(handlers, handler.Loader(loader))
	}

	defaultHandler := handler.Map()
	loadDefaults(defaultHandler)
	handlers = append(handlers, defaultHandler)
	return handler.Sync(handler.Multi(handlers...))
}

// getUserConfigLoader returns a json loader if the $HOME/.materialscommons/config.json
// file exists. It will panic if the file exists but cannot be read.
func getUserConfigLoader(configFile string) cfg.Loader {
	if file.Exists(configFile) {
		contents, err := ioutil.ReadFile(configFile)
		if err != nil {
			panic(fmt.Sprintf("%s exists but can't be read: %s", configFile, err))
		}
		return loader.JSON(bytes.NewReader(contents))
	}
	return nil
}

// loadDefaults sets up the default values for the following configuration keys:
//     mcurl: https://materialscommons.org/api
//     mclogging: info
func loadDefaults(h cfg.Handler) {
	h.Set("mcurl", "https://materialscommons.org/api")
	h.Set("mclogging", "info")
}

// setLoggingLevel sets the apps logging level.
func setLoggingLevel() {
	level := config.GetString("mclogging")
	if lvl, err := log15.LvlFromString(level); err != nil {
		fmt.Printf("Invalid Log Level: %s, setting to info.\n", level)
		fmt.Println("Valid logging levels are: debug, info, warn, error, crit. The default is info.")
		app.SetLogLvl(log15.LvlInfo)
	} else {
		app.SetLogLvl(lvl)
	}
}
<|endoftext|>