<commit_before>/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package migrator

import (
	"fmt"

	"k8s.io/test-infra/ghclient"

	"github.com/golang/glog"
	"github.com/google/go-github/github"
)

var (
	stateAny = "ANY_STATE"
	stateDNE = "DOES_NOT_EXIST"
)

// contextCondition is a struct that describes a condition about the state or existence of a context.
type contextCondition struct {
	// context is the status context that this condition applies to.
	context string
	// state is the status state that the condition accepts, or one of the special values "ANY_STATE"
	// and "DOES_NOT_EXIST".
	state string
}

// Mode is a struct that describes the behavior of a status migration. The behavior is described as
// a list of conditions and a function that determines the actions to be taken when the conditions
// are met.
type Mode struct {
	conditions []*contextCondition
	// actions returns the status updates to make based on the current statuses and the sha.
	// When actions is called, the Mode may assume that it's conditions are met.
	actions func(statuses []github.RepoStatus, sha string) []*github.RepoStatus
}

// MoveMode creates a mode that both copies and retires.
// The mode creates a new context on every PR with the old context but not the new one, setting the
// state of the new context to that of the old context before retiring the old context.
func MoveMode(origContext, newContext string) *Mode {
	dup := copyAction(origContext, newContext)
	dep := retireAction(origContext, newContext)

	return &Mode{
		conditions: []*contextCondition{
			{context: origContext, state: stateAny},
			{context: newContext, state: stateDNE},
		},
		actions: func(statuses []github.RepoStatus, sha string) []*github.RepoStatus {
			return append(dup(statuses, sha), dep(statuses, sha)...)
		},
	}
}

// CopyMode makes a mode that creates a new context in every PR that has the old context, but not the new one.
// The state, description and target URL of the new context are made the same as those of the old context.
func CopyMode(origContext, newContext string) *Mode {
	return &Mode{
		conditions: []*contextCondition{
			{context: origContext, state: stateAny},
			{context: newContext, state: stateDNE},
		},
		actions: copyAction(origContext, newContext),
	}
}

// RetireMode creates a mode that retires an old context on all PRs.
// If newContext is the empty string, origContext is retired without replacement. Its state is set to
// 'success' and its description is set to indicate that the context is retired.
// If newContext is not the empty string it is considered the replacement of origContext. This means
// that only PRs that have the newContext in addition to the origContext will be considered and the
// description of the retired context will indicate that it was replaced by newContext.
func RetireMode(origContext, newContext string) *Mode {
	conditions := []*contextCondition{{context: origContext, state: stateAny}}
	if newContext != "" {
		conditions = append(conditions, &contextCondition{context: newContext, state: stateAny})
	}
	return &Mode{
		conditions: conditions,
		actions:    retireAction(origContext, newContext),
	}
}

// copyAction creates a function that returns a copy action.
// Specifically the returned function returns a RepoStatus that will create a status for newContext
// with state set to the state of origContext.
func copyAction(origContext, newContext string) func(statuses []github.RepoStatus, sha string) []*github.RepoStatus {
	return func(statuses []github.RepoStatus, sha string) []*github.RepoStatus {
		var oldStatus *github.RepoStatus
		for _, status := range statuses {
			if status.Context != nil && *status.Context == origContext {
				oldStatus = &status
				break
			}
		}
		if oldStatus == nil {
			// This means the conditions were not met! Should never have called this function, but it is a recoverable error.
			glog.Errorf("failed to find original context in status list thus conditions for this duplicate action were not met. This should never happen!")
			return nil
		}
		return []*github.RepoStatus{
			{
				Context:     &newContext,
				State:       oldStatus.State,
				TargetURL:   oldStatus.TargetURL,
				Description: oldStatus.Description,
			},
		}
	}
}

// retireAction creates a function that returns a retire action.
// Specifically the returned function returns a RepoStatus that will update the origContext status
// to 'success' and set it's description to mark it as retired and replaced by newContext.
func retireAction(origContext, newContext string) func(statuses []github.RepoStatus, sha string) []*github.RepoStatus {
	stateSuccess := "success"
	var desc string
	if newContext == "" {
		desc = fmt.Sprint("Context retired without replacement.")
	} else {
		desc = fmt.Sprintf("Context retired. Status moved to \"%s\".", newContext)
	}
	return func(statuses []github.RepoStatus, sha string) []*github.RepoStatus {
		return []*github.RepoStatus{
			{
				Context:     &origContext,
				State:       &stateSuccess,
				TargetURL:   nil,
				Description: &desc,
			},
		}
	}
}

// processStatuses checks the mode against the combined status of a PR and emits the actions to take.
func (m Mode) processStatuses(combStatus *github.CombinedStatus) []*github.RepoStatus {
	var sha string
	if combStatus.SHA != nil {
		sha = *combStatus.SHA
	}

	for _, cond := range m.conditions {
		var match *github.RepoStatus
		match = nil
		for _, status := range combStatus.Statuses {
			if status.Context == nil {
				glog.Errorf("a status context for SHA ref '%s' had a nil Context field.", sha)
				continue
			}
			if *status.Context == cond.context {
				match = &status
				break
			}
		}

		switch cond.state {
		case stateDNE:
			if match != nil {
				return nil
			}
		case stateAny:
			if match == nil {
				return nil
			}
		default:
			// Looking for a specific state in this case.
			if match == nil {
				// Did not find the context.
				return nil
			}
			if match.State == nil {
				glog.Errorf("context '%s' of SHA ref '%s' has a nil state.", cond.context, sha)
				return nil
			}
			if *match.State != cond.state {
				// Context had a different state than what the condition requires.
				return nil
			}
		}
	}
	return m.actions(combStatus.Statuses, sha)
}

// Migrator will search github for PRs with a given context and migrate/retire/move them.
type Migrator struct {
	org             string
	repo            string
	continueOnError bool

	client *ghclient.Client
	Mode
}

// New creates a new migrator with specified options.
//
// If dryRun is true it will only perform GET requests that do not change github.
func New(mode Mode, token, org, repo string, dryRun, continueOnError bool) *Migrator {
	return &Migrator{
		org:             org,
		repo:            repo,
		continueOnError: continueOnError,
		client:          ghclient.NewClient(token, dryRun),
		Mode:            mode,
	}
}

func (m *Migrator) processPR(pr *github.PullRequest) error {
	if pr == nil {
		return fmt.Errorf("migrator cannot process a nil PullRequest")
	}
	if pr.Head == nil {
		return fmt.Errorf("migrator cannot process a PullRequest with a nil 'Head' field")
	}
	if pr.Head.SHA == nil {
		return fmt.Errorf("migrator cannot process a PullRequest with a nil 'Head.SHA' field")
	}

	combined, err := m.client.GetCombinedStatus(m.org, m.repo, *pr.Head.SHA)
	if err != nil {
		return err
	}
	actions := m.processStatuses(combined)

	for _, action := range actions {
		if _, err = m.client.CreateStatus(m.org, m.repo, *pr.Head.SHA, action); err != nil {
			return err
		}
	}
	return nil
}

// Migrate will retire/migrate/copy statuses for all matching PRs.
func (m *Migrator) Migrate(prOptions *github.PullRequestListOptions) error {
	return m.client.ForEachPR(m.org, m.repo, prOptions, m.continueOnError, m.processPR)
}
<commit_msg>fix logging calls<commit_after>/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package migrator

import (
	"fmt"

	"k8s.io/test-infra/ghclient"

	"github.com/golang/glog"
	"github.com/google/go-github/github"
)

var (
	stateAny = "ANY_STATE"
	stateDNE = "DOES_NOT_EXIST"
)

// contextCondition is a struct that describes a condition about the state or existence of a context.
type contextCondition struct {
	// context is the status context that this condition applies to.
	context string
	// state is the status state that the condition accepts, or one of the special values "ANY_STATE"
	// and "DOES_NOT_EXIST".
	state string
}

// Mode is a struct that describes the behavior of a status migration. The behavior is described as
// a list of conditions and a function that determines the actions to be taken when the conditions
// are met.
type Mode struct {
	conditions []*contextCondition
	// actions returns the status updates to make based on the current statuses and the sha.
	// When actions is called, the Mode may assume that it's conditions are met.
	actions func(statuses []github.RepoStatus, sha string) []*github.RepoStatus
}

// MoveMode creates a mode that both copies and retires.
// The mode creates a new context on every PR with the old context but not the new one, setting the
// state of the new context to that of the old context before retiring the old context.
func MoveMode(origContext, newContext string) *Mode {
	dup := copyAction(origContext, newContext)
	dep := retireAction(origContext, newContext)

	return &Mode{
		conditions: []*contextCondition{
			{context: origContext, state: stateAny},
			{context: newContext, state: stateDNE},
		},
		actions: func(statuses []github.RepoStatus, sha string) []*github.RepoStatus {
			return append(dup(statuses, sha), dep(statuses, sha)...)
		},
	}
}

// CopyMode makes a mode that creates a new context in every PR that has the old context, but not the new one.
// The state, description and target URL of the new context are made the same as those of the old context.
func CopyMode(origContext, newContext string) *Mode {
	return &Mode{
		conditions: []*contextCondition{
			{context: origContext, state: stateAny},
			{context: newContext, state: stateDNE},
		},
		actions: copyAction(origContext, newContext),
	}
}

// RetireMode creates a mode that retires an old context on all PRs.
// If newContext is the empty string, origContext is retired without replacement. Its state is set to
// 'success' and its description is set to indicate that the context is retired.
// If newContext is not the empty string it is considered the replacement of origContext. This means
// that only PRs that have the newContext in addition to the origContext will be considered and the
// description of the retired context will indicate that it was replaced by newContext.
func RetireMode(origContext, newContext string) *Mode {
	conditions := []*contextCondition{{context: origContext, state: stateAny}}
	if newContext != "" {
		conditions = append(conditions, &contextCondition{context: newContext, state: stateAny})
	}
	return &Mode{
		conditions: conditions,
		actions:    retireAction(origContext, newContext),
	}
}

// copyAction creates a function that returns a copy action.
// Specifically the returned function returns a RepoStatus that will create a status for newContext
// with state set to the state of origContext.
func copyAction(origContext, newContext string) func(statuses []github.RepoStatus, sha string) []*github.RepoStatus {
	return func(statuses []github.RepoStatus, sha string) []*github.RepoStatus {
		var oldStatus *github.RepoStatus
		for _, status := range statuses {
			if status.Context != nil && *status.Context == origContext {
				oldStatus = &status
				break
			}
		}
		if oldStatus == nil {
			// This means the conditions were not met! Should never have called this function, but it is a recoverable error.
			glog.Error("failed to find original context in status list thus conditions for this duplicate action were not met. This should never happen!")
			return nil
		}
		return []*github.RepoStatus{
			{
				Context:     &newContext,
				State:       oldStatus.State,
				TargetURL:   oldStatus.TargetURL,
				Description: oldStatus.Description,
			},
		}
	}
}

// retireAction creates a function that returns a retire action.
// Specifically the returned function returns a RepoStatus that will update the origContext status
// to 'success' and set it's description to mark it as retired and replaced by newContext.
func retireAction(origContext, newContext string) func(statuses []github.RepoStatus, sha string) []*github.RepoStatus {
	stateSuccess := "success"
	var desc string
	if newContext == "" {
		desc = fmt.Sprint("Context retired without replacement.")
	} else {
		desc = fmt.Sprintf("Context retired. Status moved to \"%s\".", newContext)
	}
	return func(statuses []github.RepoStatus, sha string) []*github.RepoStatus {
		return []*github.RepoStatus{
			{
				Context:     &origContext,
				State:       &stateSuccess,
				TargetURL:   nil,
				Description: &desc,
			},
		}
	}
}

// processStatuses checks the mode against the combined status of a PR and emits the actions to take.
func (m Mode) processStatuses(combStatus *github.CombinedStatus) []*github.RepoStatus {
	var sha string
	if combStatus.SHA != nil {
		sha = *combStatus.SHA
	}

	for _, cond := range m.conditions {
		var match *github.RepoStatus
		match = nil
		for _, status := range combStatus.Statuses {
			if status.Context == nil {
				glog.Errorf("a status context for SHA ref '%s' had a nil Context field.", sha)
				continue
			}
			if *status.Context == cond.context {
				match = &status
				break
			}
		}

		switch cond.state {
		case stateDNE:
			if match != nil {
				return nil
			}
		case stateAny:
			if match == nil {
				return nil
			}
		default:
			// Looking for a specific state in this case.
			if match == nil {
				// Did not find the context.
				return nil
			}
			if match.State == nil {
				glog.Errorf("context '%s' of SHA ref '%s' has a nil state.", cond.context, sha)
				return nil
			}
			if *match.State != cond.state {
				// Context had a different state than what the condition requires.
				return nil
			}
		}
	}
	return m.actions(combStatus.Statuses, sha)
}

// Migrator will search github for PRs with a given context and migrate/retire/move them.
type Migrator struct {
	org             string
	repo            string
	continueOnError bool

	client *ghclient.Client
	Mode
}

// New creates a new migrator with specified options.
//
// If dryRun is true it will only perform GET requests that do not change github.
func New(mode Mode, token, org, repo string, dryRun, continueOnError bool) *Migrator {
	return &Migrator{
		org:             org,
		repo:            repo,
		continueOnError: continueOnError,
		client:          ghclient.NewClient(token, dryRun),
		Mode:            mode,
	}
}

func (m *Migrator) processPR(pr *github.PullRequest) error {
	if pr == nil {
		return fmt.Errorf("migrator cannot process a nil PullRequest")
	}
	if pr.Head == nil {
		return fmt.Errorf("migrator cannot process a PullRequest with a nil 'Head' field")
	}
	if pr.Head.SHA == nil {
		return fmt.Errorf("migrator cannot process a PullRequest with a nil 'Head.SHA' field")
	}

	combined, err := m.client.GetCombinedStatus(m.org, m.repo, *pr.Head.SHA)
	if err != nil {
		return err
	}
	actions := m.processStatuses(combined)

	for _, action := range actions {
		if _, err = m.client.CreateStatus(m.org, m.repo, *pr.Head.SHA, action); err != nil {
			return err
		}
	}
	return nil
}

// Migrate will retire/migrate/copy statuses for all matching PRs.
func (m *Migrator) Migrate(prOptions *github.PullRequestListOptions) error {
	return m.client.ForEachPR(m.org, m.repo, prOptions, m.continueOnError, m.processPR)
}
<|endoftext|>


<commit_before>package widgets

import (
	"fmt"

	"github.com/ambientsound/pms/mpd"
	"github.com/ambientsound/pms/song"
	"github.com/ambientsound/pms/utils"

	"github.com/gdamore/tcell"
	"github.com/gdamore/tcell/views"
)

type PlaybarWidget struct {
	status mpd.PlayerStatus
	view   views.View
	song   song.Song
	styles StyleMap

	widget
	views.WidgetWatchers
}

var playRunes = map[string]rune{
	mpd.StatePlay:    '\u25b6',
	mpd.StatePause:   '\u23f8',
	mpd.StateStop:    '\u23f9',
	mpd.StateUnknown: '\u2bd1',
}

func StatusRune(r rune, val bool) rune {
	if val {
		return r
	}
	return '-'
}

func NewPlaybarWidget() *PlaybarWidget {
	return &PlaybarWidget{}
}

func (w *PlaybarWidget) SetPlayerStatus(s mpd.PlayerStatus) {
	w.status = s
	w.PostEventWidgetContent(w)
}

func (w *PlaybarWidget) SetSong(s *song.Song) {
	if s != nil {
		w.song = *s
	} else {
		w.song = song.Song{}
	}
	w.PostEventWidgetContent(w)
}

func (w *PlaybarWidget) drawNext(x, y int, runes []rune, style tcell.Style) int {
	strlen := 0
	for p, r := range runes {
		w.view.SetContent(x+p, y, r, nil, style)
		strlen++
	}
	return x + strlen
}

func (w *PlaybarWidget) drawNextChar(x, y int, r rune, style tcell.Style) int {
	w.view.SetContent(x, y, r, nil, style)
	return x + 1
}

func (w *PlaybarWidget) Draw() {
	if len(w.song.Tags["file"]) == 0 {
		w.drawNotPlaying()
	} else {
		w.drawCurrentSong()
	}
	w.drawStatus()
}

func (w *PlaybarWidget) drawNotPlaying() {
	w.drawNext(0, 0, []rune("No current song."), w.Style("noCurrentSong"))
}

func (w *PlaybarWidget) drawStatus() {
	x, y := 0, 1

	// 54% ----   00:00 ■ 00:00   Artist - Title

	volume := fmt.Sprintf("%d%%", w.status.Volume)
	x = w.drawNext(x, y, []rune(volume), w.Style("volume"))

	x = w.drawNextChar(x+1, y, StatusRune('c', w.status.Consume), w.Style("switches"))
	x = w.drawNextChar(x+0, y, StatusRune('z', w.status.Random), w.Style("switches"))
	x = w.drawNextChar(x+0, y, StatusRune('s', w.status.Single), w.Style("switches"))
	x = w.drawNextChar(x+0, y, StatusRune('r', w.status.Repeat), w.Style("switches"))

	x = w.drawNext(x+1, y, []rune(utils.TimeString(int(w.status.Elapsed))), w.Style("elapsed"))
	x = w.drawNextChar(x+1, y, playRunes[w.status.State], w.Style("symbol"))
	x = w.drawNext(x+1, y, []rune(utils.TimeString(w.status.Time)), w.Style("time"))
}

func (w *PlaybarWidget) drawCurrentSong() {
	x, y := 0, 0

	x = w.drawNext(x, y, w.song.Tags["artist"], w.Style("artist"))

	x = w.drawNextChar(x+1, y, '"', w.Style("album"))
	x = w.drawNext(x, y, w.song.Tags["album"], w.Style("album"))
	x = w.drawNextChar(x, y, '"', w.Style("album"))

	if len(w.song.Tags["year"]) > 0 {
		x = w.drawNextChar(x+1, y, '(', w.Style("year"))
		x = w.drawNext(x, y, w.song.Tags["year"], w.Style("year"))
		x = w.drawNextChar(x, y, ')', w.Style("year"))
	}

	x = w.drawNextChar(x+1, y, '-', w.Style("separator"))
	x = w.drawNext(x+1, y, w.song.Tags["title"], w.Style("title"))
}

func (w *PlaybarWidget) SetView(v views.View) {
	w.view = v
}

func (w *PlaybarWidget) Size() (int, int) {
	x, _ := w.view.Size()
	return x, 3
}

func (w *PlaybarWidget) Resize() {
}

func (w *PlaybarWidget) HandleEvent(ev tcell.Event) bool {
	return false
}
<commit_msg>Use non-unicode symbols for topbar: play, pause, stop, unknown<commit_after>package widgets

import (
	"fmt"

	"github.com/ambientsound/pms/mpd"
	"github.com/ambientsound/pms/song"
	"github.com/ambientsound/pms/utils"

	"github.com/gdamore/tcell"
	"github.com/gdamore/tcell/views"
)

type PlaybarWidget struct {
	status mpd.PlayerStatus
	view   views.View
	song   song.Song
	styles StyleMap

	widget
	views.WidgetWatchers
}

var playRunes = map[string]rune{
	mpd.StatePlay:    '\u25b6',
	mpd.StatePause:   '\u23f8',
	mpd.StateStop:    '\u23f9',
	mpd.StateUnknown: '\u2bd1',
}

var playStrings = map[string]string{
	mpd.StatePlay:    "|>",
	mpd.StatePause:   "||",
	mpd.StateStop:    "[]",
	mpd.StateUnknown: "??",
}

func StatusRune(r rune, val bool) rune {
	if val {
		return r
	}
	return '-'
}

func NewPlaybarWidget() *PlaybarWidget {
	return &PlaybarWidget{}
}

func (w *PlaybarWidget) SetPlayerStatus(s mpd.PlayerStatus) {
	w.status = s
	w.PostEventWidgetContent(w)
}

func (w *PlaybarWidget) SetSong(s *song.Song) {
	if s != nil {
		w.song = *s
	} else {
		w.song = song.Song{}
	}
	w.PostEventWidgetContent(w)
}

func (w *PlaybarWidget) drawNext(x, y int, runes []rune, style tcell.Style) int {
	strlen := 0
	for p, r := range runes {
		w.view.SetContent(x+p, y, r, nil, style)
		strlen++
	}
	return x + strlen
}

func (w *PlaybarWidget) drawNextChar(x, y int, r rune, style tcell.Style) int {
	w.view.SetContent(x, y, r, nil, style)
	return x + 1
}

func (w *PlaybarWidget) Draw() {
	if len(w.song.Tags["file"]) == 0 {
		w.drawNotPlaying()
	} else {
		w.drawCurrentSong()
	}
	w.drawStatus()
}

func (w *PlaybarWidget) drawNotPlaying() {
	w.drawNext(0, 0, []rune("No current song."), w.Style("noCurrentSong"))
}

func (w *PlaybarWidget) drawStatus() {
	x, y := 0, 1

	// 54% ----   00:00 ■ 00:00   Artist - Title

	volume := fmt.Sprintf("%d%%", w.status.Volume)
	x = w.drawNext(x, y, []rune(volume), w.Style("volume"))

	x = w.drawNextChar(x+1, y, StatusRune('c', w.status.Consume), w.Style("switches"))
	x = w.drawNextChar(x+0, y, StatusRune('z', w.status.Random), w.Style("switches"))
	x = w.drawNextChar(x+0, y, StatusRune('s', w.status.Single), w.Style("switches"))
	x = w.drawNextChar(x+0, y, StatusRune('r', w.status.Repeat), w.Style("switches"))

	x = w.drawNext(x+1, y, []rune(utils.TimeString(int(w.status.Elapsed))), w.Style("elapsed"))
	x = w.drawNext(x+1, y, []rune(playStrings[w.status.State]), w.Style("symbol"))
	x = w.drawNext(x+1, y, []rune(utils.TimeString(w.status.Time)), w.Style("time"))
}

func (w *PlaybarWidget) drawCurrentSong() {
	x, y := 0, 0

	x = w.drawNext(x, y, w.song.Tags["artist"], w.Style("artist"))

	x = w.drawNextChar(x+1, y, '"', w.Style("album"))
	x = w.drawNext(x, y, w.song.Tags["album"], w.Style("album"))
	x = w.drawNextChar(x, y, '"', w.Style("album"))

	if len(w.song.Tags["year"]) > 0 {
		x = w.drawNextChar(x+1, y, '(', w.Style("year"))
		x = w.drawNext(x, y, w.song.Tags["year"], w.Style("year"))
		x = w.drawNextChar(x, y, ')', w.Style("year"))
	}

	x = w.drawNextChar(x+1, y, '-', w.Style("separator"))
	x = w.drawNext(x+1, y, w.song.Tags["title"], w.Style("title"))
}

func (w *PlaybarWidget) SetView(v views.View) {
	w.view = v
}

func (w *PlaybarWidget) Size() (int, int) {
	x, _ := w.view.Size()
	return x, 3
}

func (w *PlaybarWidget) Resize() {
}

func (w *PlaybarWidget) HandleEvent(ev tcell.Event) bool {
	return false
}
<|endoftext|>


<commit_before>package notify

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
	"net/url"

	log "github.com/Sirupsen/logrus"
)

type slackNotifications struct {
	UseSlack  bool
	slackAddr string
}

var SlackNotify slackNotifications

type Params map[string]string

func InitSlack(slackAddr string) {
	if slackAddr != "" {
		SlackNotify.UseSlack = true
		SlackNotify.slackAddr = slackAddr
	}
}

func (s *slackNotifications) SendToSlack(ipAddr string, domain string, addOrRemove string, dryRun bool) {
	log.Debugln("Dry Run is True, sending Slack notification", "https://hooks.slack.com/services/"+s.slackAddr)
	text := ""
	if dryRun {
		text = "Dry Run set to True.  Would have " + addOrRemove + " " + ipAddr + " and configured entries from/to domain " + domain + " "
	} else {
		text = "Dry Run set to False. " + addOrRemove + " " + ipAddr + " and configured entries from/to domain " + domain + " "
	}
	var p Params = map[string]string{
		"text": text,
	}
	json, _ := json.Marshal(p)
	resp, _ := http.PostForm("https://hooks.slack.com/services/"+s.slackAddr, url.Values{"payload": []string{string(json)}})
	if resp.StatusCode != http.StatusOK {
		body, _ := ioutil.ReadAll(resp.Body)
		defer resp.Body.Close()
		log.Errorf("status code: %d, response body: %s", resp.StatusCode, body)
	}

}
<commit_msg>small tweak in notification message<commit_after>package notify

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
	"net/url"

	log "github.com/Sirupsen/logrus"
)

type slackNotifications struct {
	UseSlack  bool
	slackAddr string
}

var SlackNotify slackNotifications

type Params map[string]string

func InitSlack(slackAddr string) {
	if slackAddr != "" {
		SlackNotify.UseSlack = true
		SlackNotify.slackAddr = slackAddr
	}
}

func (s *slackNotifications) SendToSlack(ipAddr string, domain string, addOrRemove string, dryRun bool) {
	log.Debugln("Dry Run is True, sending Slack notification", "https://hooks.slack.com/services/"+s.slackAddr)
	text := ""
	if dryRun {
		text = "Dry Run set to True.  Agent would have " + addOrRemove + " " + ipAddr + " and configured entries from/to domain " + domain + " "
	} else {
		text = "Dry Run set to False. Agent " + addOrRemove + " " + ipAddr + " and configured entries from/to domain " + domain + " "
	}
	var p Params = map[string]string{
		"text": text,
	}
	json, _ := json.Marshal(p)
	resp, _ := http.PostForm("https://hooks.slack.com/services/"+s.slackAddr, url.Values{"payload": []string{string(json)}})
	if resp.StatusCode != http.StatusOK {
		body, _ := ioutil.ReadAll(resp.Body)
		defer resp.Body.Close()
		log.Errorf("status code: %d, response body: %s", resp.StatusCode, body)
	}

}
<|endoftext|>


<commit_before>// Copyright 2016-2019 The Libsacloud Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package types

// EGSLBHealthCheckProtocol GSLB 監視プロトコル
type EGSLBHealthCheckProtocol string

// GSLBHealthCheckProtocols GSLB 監視プロトコル
var GSLBHealthCheckProtocols = struct {
	// Unknown 不明
	Unknown EGSLBHealthCheckProtocol
	// HTTP http
	HTTP EGSLBHealthCheckProtocol
	// HTTPS https
	HTTPS EGSLBHealthCheckProtocol
	// TCP tcp
	TCP EGSLBHealthCheckProtocol
	// Ping ping
	Ping EGSLBHealthCheckProtocol
}{
	Unknown: EGSLBHealthCheckProtocol(""),
	HTTP:    EGSLBHealthCheckProtocol("http"),
	HTTPS:   EGSLBHealthCheckProtocol("https"),
	TCP:     EGSLBHealthCheckProtocol("tcp"),
	Ping:    EGSLBHealthCheckProtocol("ping"),
}
<commit_msg>Add constants: GSLBHealthCheckProtocols<commit_after>// Copyright 2016-2019 The Libsacloud Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package types

// EGSLBHealthCheckProtocol GSLB 監視プロトコル
type EGSLBHealthCheckProtocol string

// String EGSLBHealthCheckProtocolの文字列表現
func (p EGSLBHealthCheckProtocol) String() string {
	return string(p)
}

// GSLBHealthCheckProtocols GSLB 監視プロトコル
var GSLBHealthCheckProtocols = struct {
	// Unknown 不明
	Unknown EGSLBHealthCheckProtocol
	// HTTP http
	HTTP EGSLBHealthCheckProtocol
	// HTTPS https
	HTTPS EGSLBHealthCheckProtocol
	// TCP tcp
	TCP EGSLBHealthCheckProtocol
	// Ping ping
	Ping EGSLBHealthCheckProtocol
}{
	Unknown: EGSLBHealthCheckProtocol(""),
	HTTP:    EGSLBHealthCheckProtocol("http"),
	HTTPS:   EGSLBHealthCheckProtocol("https"),
	TCP:     EGSLBHealthCheckProtocol("tcp"),
	Ping:    EGSLBHealthCheckProtocol("ping"),
}

// GSLBHealthCheckProtocolsStrings 有効なGSLB監視プロトコルを示す文字列のリスト
//
// Unknown(空文字)は含まない
func GSLBHealthCheckProtocolsStrings() []string {
	return []string{
		GSLBHealthCheckProtocols.HTTP.String(),
		GSLBHealthCheckProtocols.HTTPS.String(),
		GSLBHealthCheckProtocols.TCP.String(),
		GSLBHealthCheckProtocols.Ping.String(),
	}
}
<|endoftext|>


<commit_before>package test_helpers

import (
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"os/signal"
	"runtime"
	"strings"
	"syscall"
	"testing"
	"time"
)

// Indexed by mountpoint. Initialized in doInit().
var MountInfo map[string]mountInfo

type mountInfo struct {
	// PID of the running gocryptfs process. Set by Mount().
	Pid int
	// List of open FDs of the running gocrypts process. Set by Mount().
	Fds []string
}

// Mount CIPHERDIR "c" on PLAINDIR "p"
// Creates "p" if it does not exist.
func Mount(c string, p string, showOutput bool, extraArgs ...string) error {
	args := []string{"-q", "-wpanic", "-nosyslog", "-fg", fmt.Sprintf("-notifypid=%d", os.Getpid())}
	args = append(args, extraArgs...)
	//args = append(args, "-fusedebug")
	//args = append(args, "-d")
	args = append(args, c, p)

	if _, err := os.Stat(p); err != nil {
		err = os.Mkdir(p, 0777)
		if err != nil {
			return err
		}
	}

	cmd := exec.Command(GocryptfsBinary, args...)
	if showOutput {
		// The Go test logic waits for our stdout to close, and when we share
		// it with the subprocess, it will wait for it to close it as well.
		// Use an intermediate pipe so the tests do not hang when unmouting
		// fails.
		pr, pw, err := os.Pipe()
		if err != nil {
			return err
		}
		// We can close the fd after cmd.Run() has executed
		defer pw.Close()
		cmd.Stderr = pw
		cmd.Stdout = pw
		go func() {
			io.Copy(os.Stdout, pr)
			pr.Close()
		}()
	}

	// Two things can happen:
	// 1) The mount fails and the process exits
	// 2) The mount succeeds and the process sends us USR1
	chanExit := make(chan error, 1)
	chanUsr1 := make(chan os.Signal, 1)
	signal.Notify(chanUsr1, syscall.SIGUSR1)

	// Start the process and save the PID
	err := cmd.Start()
	if err != nil {
		return err
	}
	pid := cmd.Process.Pid

	// Wait for exit or usr1
	go func() {
		chanExit <- cmd.Wait()
	}()
	select {
	case err := <-chanExit:
		return err
	case <-chanUsr1:
		// noop
	case <-time.After(1 * time.Second):
		log.Panicf("Timeout waiting for process %d", pid)
	}

	// Save PID and open FDs
	MountInfo[p] = mountInfo{pid, ListFds(pid)}
	return nil
}

// MountOrExit calls Mount() and exits on failure.
func MountOrExit(c string, p string, extraArgs ...string) {
	err := Mount(c, p, true, extraArgs...)
	if err != nil {
		fmt.Printf("mount failed: %v\n", err)
		os.Exit(1)
	}
}

// MountOrFatal calls Mount() and calls t.Fatal() on failure.
func MountOrFatal(t *testing.T, c string, p string, extraArgs ...string) {
	err := Mount(c, p, true, extraArgs...)
	if err != nil {
		t.Fatal(fmt.Errorf("mount failed: %v", err))
	}
}

// UnmountPanic tries to umount "dir" and panics on error.
func UnmountPanic(dir string) {
	err := UnmountErr(dir)
	if err != nil {
		fmt.Printf("UnmountPanic: %v. Running lsof %s\n", err, dir)
		cmd := exec.Command("lsof", dir)
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		cmd.Run()
		panic("UnmountPanic: unmount failed: " + err.Error())
	}
}

// UnmountErr tries to unmount "dir", retrying 10 times, and returns the
// resulting error.
func UnmountErr(dir string) (err error) {
	var fdsNow []string
	pid := MountInfo[dir].Pid
	fds := MountInfo[dir].Fds
	if pid <= 0 {
		fmt.Printf("UnmountErr: %q was not found in MountInfo, cannot check for FD leaks\n", dir)
	}

	max := 10
	// When a new filesystem is mounted, Gnome tries to read files like
	// .xdg-volume-info, autorun.inf, .Trash.
	// If we try to unmount before Gnome is done, the unmount fails with
	// "Device or resource busy", causing spurious test failures.
	// Retry a few times to hide that problem.
	for i := 1; i <= max; i++ {
		if pid > 0 {
			fdsNow = ListFds(pid)
			if len(fdsNow) > len(fds) {
				// File close on FUSE is asynchronous, closing a socket
				// when testing -ctlsock as well. Wait one extra millisecond
				// and hope that all close commands get through to the gocryptfs
				// process.
				time.Sleep(1 * time.Millisecond)
				fdsNow = ListFds(pid)
			}
		}
		cmd := exec.Command(UnmountScript, "-u", dir)
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		err = cmd.Run()
		if err == nil {
			if len(fdsNow) > len(fds) {
				return fmt.Errorf("FD leak? pid=%d dir=%q, fds:\nold=%v \nnew=%v\n", pid, dir, fds, fdsNow)
			}
			return nil
		}
		code := ExtractCmdExitCode(err)
		fmt.Printf("UnmountErr: got exit code %d, retrying (%d/%d)\n", code, i, max)
		time.Sleep(100 * time.Millisecond)
	}
	return err
}

// ListFds lists the open file descriptors for process "pid". Pass pid=0 for
// ourselves.
func ListFds(pid int) []string {
	// We need /proc to get the list of fds for other processes. Only exists
	// on Linux.
	if runtime.GOOS != "linux" && pid > 0 {
		return nil
	}
	// Both Linux and MacOS have /dev/fd
	dir := "/dev/fd"
	if pid > 0 {
		dir = fmt.Sprintf("/proc/%d/fd", pid)
	}
	f, err := os.Open(dir)
	if err != nil {
		log.Panic(err)
	}
	defer f.Close()
	// Note: Readdirnames filters "." and ".."
	names, err := f.Readdirnames(0)
	if err != nil {
		log.Panic(err)
	}
	var out []string
	hidden := 0
	for _, n := range names {
		fdPath := dir + "/" + n
		fi, err := os.Lstat(fdPath)
		if err != nil {
			// fd was closed in the meantime
			continue
		}
		if fi.Mode()&0400 > 0 {
			n += "r"
		}
		if fi.Mode()&0200 > 0 {
			n += "w"
		}
		target, err := os.Readlink(fdPath)
		if err != nil {
			// fd was closed in the meantime
			continue
		}
		if strings.HasPrefix(target, "pipe:") || strings.HasPrefix(target, "anon_inode:[eventpoll]") {
			// The Go runtime creates pipes on demand for splice(), which
			// creates spurious test failures. Ignore all pipes.
			// Also get rid of the "eventpoll" fd that is always there and not
			// interesting.
			hidden++
			continue
		}
		out = append(out, n+"="+target)
	}
	out = append(out, fmt.Sprintf("(hidden:%d)", hidden))
	return out
}
<commit_msg>tests: retry longer when we see a fd leak<commit_after>package test_helpers

import (
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"os/signal"
	"runtime"
	"strings"
	"syscall"
	"testing"
	"time"
)

// Indexed by mountpoint. Initialized in doInit().
var MountInfo map[string]mountInfo

type mountInfo struct {
	// PID of the running gocryptfs process. Set by Mount().
	Pid int
	// List of open FDs of the running gocrypts process. Set by Mount().
	Fds []string
}

// Mount CIPHERDIR "c" on PLAINDIR "p"
// Creates "p" if it does not exist.
func Mount(c string, p string, showOutput bool, extraArgs ...string) error {
	args := []string{"-q", "-wpanic", "-nosyslog", "-fg", fmt.Sprintf("-notifypid=%d", os.Getpid())}
	args = append(args, extraArgs...)
	//args = append(args, "-fusedebug")
	//args = append(args, "-d")
	args = append(args, c, p)

	if _, err := os.Stat(p); err != nil {
		err = os.Mkdir(p, 0777)
		if err != nil {
			return err
		}
	}

	cmd := exec.Command(GocryptfsBinary, args...)
	if showOutput {
		// The Go test logic waits for our stdout to close, and when we share
		// it with the subprocess, it will wait for it to close it as well.
		// Use an intermediate pipe so the tests do not hang when unmouting
		// fails.
		pr, pw, err := os.Pipe()
		if err != nil {
			return err
		}
		// We can close the fd after cmd.Run() has executed
		defer pw.Close()
		cmd.Stderr = pw
		cmd.Stdout = pw
		go func() {
			io.Copy(os.Stdout, pr)
			pr.Close()
		}()
	}

	// Two things can happen:
	// 1) The mount fails and the process exits
	// 2) The mount succeeds and the process sends us USR1
	chanExit := make(chan error, 1)
	chanUsr1 := make(chan os.Signal, 1)
	signal.Notify(chanUsr1, syscall.SIGUSR1)

	// Start the process and save the PID
	err := cmd.Start()
	if err != nil {
		return err
	}
	pid := cmd.Process.Pid

	// Wait for exit or usr1
	go func() {
		chanExit <- cmd.Wait()
	}()
	select {
	case err := <-chanExit:
		return err
	case <-chanUsr1:
		// noop
	case <-time.After(1 * time.Second):
		log.Panicf("Timeout waiting for process %d", pid)
	}

	// Save PID and open FDs
	MountInfo[p] = mountInfo{pid, ListFds(pid)}
	return nil
}

// MountOrExit calls Mount() and exits on failure.
func MountOrExit(c string, p string, extraArgs ...string) {
	err := Mount(c, p, true, extraArgs...)
	if err != nil {
		fmt.Printf("mount failed: %v\n", err)
		os.Exit(1)
	}
}

// MountOrFatal calls Mount() and calls t.Fatal() on failure.
func MountOrFatal(t *testing.T, c string, p string, extraArgs ...string) {
	err := Mount(c, p, true, extraArgs...)
	if err != nil {
		t.Fatal(fmt.Errorf("mount failed: %v", err))
	}
}

// UnmountPanic tries to umount "dir" and panics on error.
func UnmountPanic(dir string) {
	err := UnmountErr(dir)
	if err != nil {
		fmt.Printf("UnmountPanic: %v. Running lsof %s\n", err, dir)
		cmd := exec.Command("lsof", dir)
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		cmd.Run()
		panic("UnmountPanic: unmount failed: " + err.Error())
	}
}

// UnmountErr tries to unmount "dir", retrying 10 times, and returns the
// resulting error.
func UnmountErr(dir string) (err error) {
	var fdsNow []string
	pid := MountInfo[dir].Pid
	fds := MountInfo[dir].Fds
	if pid <= 0 {
		fmt.Printf("UnmountErr: %q was not found in MountInfo, cannot check for FD leaks\n", dir)
	}

	max := 10
	// When a new filesystem is mounted, Gnome tries to read files like
	// .xdg-volume-info, autorun.inf, .Trash.
	// If we try to unmount before Gnome is done, the unmount fails with
	// "Device or resource busy", causing spurious test failures.
	// Retry a few times to hide that problem.
	for i := 1; i <= max; i++ {
		if pid > 0 {
			for j := 1; j <= max; j++ {
				// File close on FUSE is asynchronous, closing a socket
				// when testing "-ctlsock" is as well. Wait a little and
				// hope that all close commands get through to the gocryptfs
				// process.
				fdsNow = ListFds(pid)
				if len(fdsNow) <= len(fds) {
					break
				}
				fmt.Printf("UnmountErr: fdsOld=%d fdsNow=%d, retrying\n", len(fds), len(fdsNow))
				time.Sleep(10 * time.Millisecond)
				fdsNow = ListFds(pid)
			}
		}
		cmd := exec.Command(UnmountScript, "-u", dir)
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		err = cmd.Run()
		if err == nil {
			if len(fdsNow) > len(fds) {
				return fmt.Errorf("FD leak? pid=%d dir=%q, fds:\nold=%v \nnew=%v\n", pid, dir, fds, fdsNow)
			}
			return nil
		}
		code := ExtractCmdExitCode(err)
		fmt.Printf("UnmountErr: got exit code %d, retrying (%d/%d)\n", code, i, max)
		time.Sleep(100 * time.Millisecond)
	}
	return err
}

// ListFds lists the open file descriptors for process "pid". Pass pid=0 for
// ourselves.
func ListFds(pid int) []string {
	// We need /proc to get the list of fds for other processes. Only exists
	// on Linux.
	if runtime.GOOS != "linux" && pid > 0 {
		return nil
	}
	// Both Linux and MacOS have /dev/fd
	dir := "/dev/fd"
	if pid > 0 {
		dir = fmt.Sprintf("/proc/%d/fd", pid)
	}
	f, err := os.Open(dir)
	if err != nil {
		log.Panic(err)
	}
	defer f.Close()
	// Note: Readdirnames filters "." and ".."
	names, err := f.Readdirnames(0)
	if err != nil {
		log.Panic(err)
	}
	var out []string
	hidden := 0
	for _, n := range names {
		fdPath := dir + "/" + n
		fi, err := os.Lstat(fdPath)
		if err != nil {
			// fd was closed in the meantime
			continue
		}
		if fi.Mode()&0400 > 0 {
			n += "r"
		}
		if fi.Mode()&0200 > 0 {
			n += "w"
		}
		target, err := os.Readlink(fdPath)
		if err != nil {
			// fd was closed in the meantime
			continue
		}
		if strings.HasPrefix(target, "pipe:") || strings.HasPrefix(target, "anon_inode:[eventpoll]") {
			// The Go runtime creates pipes on demand for splice(), which
			// creates spurious test failures. Ignore all pipes.
			// Also get rid of the "eventpoll" fd that is always there and not
			// interesting.
			hidden++
			continue
		}
		out = append(out, n+"="+target)
	}
	out = append(out, fmt.Sprintf("(hidden:%d)", hidden))
	return out
}
<|endoftext|>


<commit_before>package hookworm

import (
	"bytes"
	"fmt"
	"log"
	"sort"
	"strings"
	"text/template"
	"time"
)

var (
	rfc2822DateFmt        = "Mon, 01 Jan 15:04:05 -0700"
	secretCommitEmailTmpl = template.Must(template.New("email").Parse(`From: {{.From}}
To: {{.Recipients}}
Subject: [hookworm] Secret commit! {{.Repo}} {{.Ref}} {{.HeadCommitId}}
Date: {{.Date}}
Message-ID: {{.MessageId}}
Content-Type: text/html; charset=utf8

Secret commit detected on {{.Repo}} {{.Ref}}

Id

{{.HeadCommitId}}

Message

{{.HeadCommitMessage}}

Author

{{.HeadCommitAuthor}}

Committer

{{.HeadCommitCommitter}}

Timestamp

{{.HeadCommitTimestamp}}

`))
)

type SecretSquirrelCommitHandler struct {
	emailer        *Emailer
	fromAddr       string
	recipients     []string
	stableBranches []string
	nextHandler    Handler
}

type secretCommitEmailContext struct {
	From                string
	Recipients          string
	Date                string
	MessageId           string
	Repo                string
	Ref                 string
	HeadCommitId        string
	HeadCommitUrl       string
	HeadCommitAuthor    string
	HeadCommitCommitter string
	HeadCommitMessage   string
	HeadCommitTimestamp string
}

func (me *SecretSquirrelCommitHandler) HandlePayload(payload *Payload) error {
	me.checkIfSecretSquirrelCommit(payload)
	return nil
}

func (me *SecretSquirrelCommitHandler) SetNextHandler(handler Handler) {
	me.nextHandler = handler
}

func (me *SecretSquirrelCommitHandler) NextHandler() Handler {
	return me.nextHandler
}

func (me *SecretSquirrelCommitHandler) checkIfSecretSquirrelCommit(payload *Payload) {
	if !me.isStableBranch(payload.Ref.String()) {
		return
	}

	if payload.IsPullRequestMerge() {
		return
	}

	if err := me.alert(payload); err != nil {
		log.Printf("ERROR sending alert: %+v\n", err)
		return
	}

	log.Printf("Sent alert to %+v\n", me.recipients)
}

func (me *SecretSquirrelCommitHandler) isStableBranch(ref string) bool {
	return sort.SearchStrings(me.stableBranches, ref) > -1
}

func (me *SecretSquirrelCommitHandler) alert(payload *Payload) error {
	// FIXME use the emailer thing here
	log.Printf("WARNING secret squirrel commit! %+v\n", payload)
	if len(me.recipients) == 0 {
		log.Println("No email recipients specified, so no emailing!")
	}

	hc := payload.HeadCommit
	ctx := &secretCommitEmailContext{
		From:       me.fromAddr,
		Recipients: strings.Join(me.recipients, ", "),
		Date:       time.Now().UTC().Format(rfc2822DateFmt),
		MessageId:  fmt.Sprintf("%v", time.Now().UTC().UnixNano()),
		Repo: fmt.Sprintf("%s/%s", payload.Repository.Owner.Name.String(),
			payload.Repository.Name.String()),
		Ref:                 payload.Ref.String(),
		HeadCommitId:        hc.Id.String(),
		HeadCommitUrl:       hc.Url.String(),
		HeadCommitAuthor:    hc.Author.Name.String(),
		HeadCommitCommitter: hc.Committer.Name.String(),
		HeadCommitMessage:   hc.Message.String(),
		HeadCommitTimestamp: hc.Timestamp.String(),
	}
	var emailBuf bytes.Buffer

	err := secretCommitEmailTmpl.Execute(&emailBuf, ctx)
	if err != nil {
		return err
	}

	log.Printf("Email message:\n%v\n", string(emailBuf.Bytes()))
	return me.emailer.Send(me.fromAddr, me.recipients, emailBuf.Bytes())
}
<commit_msg>Date format and message id fixes per whiny gmail smtp server<commit_after>package hookworm

import (
	"bytes"
	"fmt"
	"log"
	"os"
	"sort"
	"strings"
	"text/template"
	"time"
)

var (
	rfc2822DateFmt        = "Mon, 02 Jan 2006 15:04:05 -0700"
	hostname              string
	secretCommitEmailTmpl = template.Must(template.New("email").Parse(`From: {{.From}}
To: {{.Recipients}}
Subject: [hookworm] Secret commit! {{.Repo}} {{.Ref}} {{.HeadCommitId}}
Date: {{.Date}}
Message-ID: <{{.MessageId}}@{{.Hostname}}>
Content-Type: text/html; charset=utf8

Secret commit detected on {{.Repo}} {{.Ref}}

Id

{{.HeadCommitId}}

Message

{{.HeadCommitMessage}}

Author

{{.HeadCommitAuthor}}

Committer

{{.HeadCommitCommitter}}

Timestamp

{{.HeadCommitTimestamp}}

`))
)

func init() {
	var err error
	hostname, err = os.Hostname()
	if err != nil {
		hostname = "somewhere.local"
	}
}

type SecretSquirrelCommitHandler struct {
	emailer        *Emailer
	fromAddr       string
	recipients     []string
	stableBranches []string
	nextHandler    Handler
}

type secretCommitEmailContext struct {
	From                string
	Recipients          string
	Date                string
	MessageId           string
	Hostname            string
	Repo                string
	Ref                 string
	HeadCommitId        string
	HeadCommitUrl       string
	HeadCommitAuthor    string
	HeadCommitCommitter string
	HeadCommitMessage   string
	HeadCommitTimestamp string
}

func (me *SecretSquirrelCommitHandler) HandlePayload(payload *Payload) error {
	me.checkIfSecretSquirrelCommit(payload)
	return nil
}

func (me *SecretSquirrelCommitHandler) SetNextHandler(handler Handler) {
	me.nextHandler = handler
}

func (me *SecretSquirrelCommitHandler) NextHandler() Handler {
	return me.nextHandler
}

func (me *SecretSquirrelCommitHandler) checkIfSecretSquirrelCommit(payload *Payload) {
	if !me.isStableBranch(payload.Ref.String()) {
		return
	}

	if payload.IsPullRequestMerge() {
		return
	}

	if err := me.alert(payload); err != nil {
		log.Printf("ERROR sending alert: %+v\n", err)
		return
	}

	log.Printf("Sent alert to %+v\n", me.recipients)
}

func (me *SecretSquirrelCommitHandler) isStableBranch(ref string) bool {
	return sort.SearchStrings(me.stableBranches, ref) > -1
}

func (me *SecretSquirrelCommitHandler) alert(payload *Payload) error {
	// FIXME use the emailer thing here
	log.Printf("WARNING secret squirrel commit! %+v\n", payload)
	if len(me.recipients) == 0 {
		log.Println("No email recipients specified, so no emailing!")
	}

	hc := payload.HeadCommit
	ctx := &secretCommitEmailContext{
		From:       me.fromAddr,
		Recipients: strings.Join(me.recipients, ", "),
		Date:       time.Now().UTC().Format(rfc2822DateFmt),
		MessageId:  fmt.Sprintf("%v", time.Now().UTC().UnixNano()),
		Hostname:   hostname,
		Repo: fmt.Sprintf("%s/%s", payload.Repository.Owner.Name.String(),
			payload.Repository.Name.String()),
		Ref:                 payload.Ref.String(),
		HeadCommitId:        hc.Id.String(),
		HeadCommitUrl:       hc.Url.String(),
		HeadCommitAuthor:    hc.Author.Name.String(),
		HeadCommitCommitter: hc.Committer.Name.String(),
		HeadCommitMessage:   hc.Message.String(),
		HeadCommitTimestamp: hc.Timestamp.String(),
	}
	var emailBuf bytes.Buffer

	err := secretCommitEmailTmpl.Execute(&emailBuf, ctx)
	if err != nil {
		return err
	}

	log.Printf("Email message:\n%v\n", string(emailBuf.Bytes()))
	return me.emailer.Send(me.fromAddr, me.recipients, emailBuf.Bytes())
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/golang/freetype"
	"github.com/golang/freetype/truetype"
	"fmt"
	"github.com/errnoh/term.color"
	"image"
	"image/color/palette"
	"image/draw"
	"github.com/james4k/terminal"
	"os"
)

var font *truetype.Font

const fontSize = 18

func init() {
	fontData, err := Asset("font/Anonymous Pro Minus.ttf")
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	font, err = freetype.ParseFont(fontData)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

// Capture draws virtual terminal and return paletted image
func (g *GifGenerator) Capture(state *terminal.State) (paletted *image.Paletted, err error) {
	fb := font.Bounds(fontSize)
	cursorX, cursorY := state.Cursor()
	paletted = image.NewPaletted(image.Rect(0, 0, g.Col*int(fb.Max.X-fb.Min.X)+10, g.Row*int(fb.Max.Y-fb.Min.Y)+10), palette.WebSafe)

	c := freetype.NewContext()
	c.SetFontSize(fontSize)
	c.SetFont(font)
	c.SetDst(paletted)
	c.SetClip(paletted.Bounds())
	for row := 0; row < g.Row; row++ {
		for col := 0; col < g.Col; col++ {
			ch, fg, bg := state.Cell(col, row)
			var uniform *image.Uniform
			// background color
			if bg != terminal.DefaultBG {
				if bg == terminal.DefaultFG {
					uniform = image.White
				} else {
					uniform = image.NewUniform(color.Term256{Val: uint8(bg)})
				}
			}
			// cursor
			if state.CursorVisible() && (row == cursorY && col == cursorX) {
				uniform = image.White
			}
			if uniform != nil {
				draw.Draw(paletted, image.Rect(5+col*int(fb.Max.X-fb.Min.X), row*int(fb.Max.Y-fb.Min.Y)-int(fb.Min.Y), 5+(col+1)*int(fb.Max.X-fb.Min.X), (row+1)*int(fb.Max.Y-fb.Min.Y)-int(fb.Min.Y)), uniform, image.ZP, draw.Src)
			}
			// foreground color
			switch fg {
			case terminal.DefaultFG:
				c.SetSrc(image.White)
			case terminal.DefaultBG:
				c.SetSrc(image.Black)
			default:
				c.SetSrc(image.NewUniform(color.Term256{Val: uint8(fg)}))
			}
			_, err = c.DrawString(string(ch), freetype.Pt(5+col*int(fb.Max.X-fb.Min.X), (row+1)*int(fb.Max.Y-fb.Min.Y)))
			if err != nil {
				return
			}
		}
	}
	return paletted, nil
}
<commit_msg>reorder imports<commit_after>package main

import (
	"fmt"
	"github.com/errnoh/term.color"
	"github.com/golang/freetype"
	"github.com/golang/freetype/truetype"
	"github.com/james4k/terminal"
	"image"
	"image/color/palette"
	"image/draw"
	"os"
)

var font *truetype.Font

const fontSize = 18

func init() {
	fontData, err := Asset("font/Anonymous Pro Minus.ttf")
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	font, err = freetype.ParseFont(fontData)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

// Capture draws virtual terminal and return paletted image
func (g *GifGenerator) Capture(state *terminal.State) (paletted *image.Paletted, err error) {
	fb := font.Bounds(fontSize)
	cursorX, cursorY := state.Cursor()
	paletted = image.NewPaletted(image.Rect(0, 0, g.Col*int(fb.Max.X-fb.Min.X)+10, g.Row*int(fb.Max.Y-fb.Min.Y)+10), palette.WebSafe)

	c := freetype.NewContext()
	c.SetFontSize(fontSize)
	c.SetFont(font)
	c.SetDst(paletted)
	c.SetClip(paletted.Bounds())
	for row := 0; row < g.Row; row++ {
		for col := 0; col < g.Col; col++ {
			ch, fg, bg := state.Cell(col, row)
			var uniform *image.Uniform
			// background color
			if bg != terminal.DefaultBG {
				if bg == terminal.DefaultFG {
					uniform = image.White
				} else {
					uniform = image.NewUniform(color.Term256{Val: uint8(bg)})
				}
			}
			// cursor
			if state.CursorVisible() && (row == cursorY && col == cursorX) {
				uniform = image.White
			}
			if uniform != nil {
				draw.Draw(paletted, image.Rect(5+col*int(fb.Max.X-fb.Min.X), row*int(fb.Max.Y-fb.Min.Y)-int(fb.Min.Y), 5+(col+1)*int(fb.Max.X-fb.Min.X), (row+1)*int(fb.Max.Y-fb.Min.Y)-int(fb.Min.Y)), uniform, image.ZP, draw.Src)
			}
			// foreground color
			switch fg {
			case terminal.DefaultFG:
				c.SetSrc(image.White)
			case terminal.DefaultBG:
				c.SetSrc(image.Black)
			default:
				c.SetSrc(image.NewUniform(color.Term256{Val: uint8(fg)}))
			}
			_, err = c.DrawString(string(ch), freetype.Pt(5+col*int(fb.Max.X-fb.Min.X), (row+1)*int(fb.Max.Y-fb.Min.Y)))
			if err != nil {
				return
			}
		}
	}
	return paletted, nil
}
<|endoftext|>


<commit_before>// Copyright 2013 Fredrik Ehnbom
// Use of this source code is governed by a 2-clause
// BSD-style license that can be found in the LICENSE file.

package text

import (
	"reflect"
	"testing"
)

// Verified against ST3
func TestRegionSetAdjust(t *testing.T) {
	var r RegionSet

	r.AddAll([]Region{
		{10, 20},
		{25, 35},
	})

	r.Adjust(2, 5)
	if !reflect.DeepEqual(r.regions, []Region{{15, 25}, {30, 40}}) {
		t.Errorf("Not as expected: %v", r)
	}

	r.Adjust(30, 1)
	if !reflect.DeepEqual(r.regions, []Region{{15, 25}, {31, 41}}) {
		t.Errorf("Not as expected: %v", r)
	}

	r.Adjust(41, 1)
	if !reflect.DeepEqual(r.regions, []Region{{15, 25}, {31, 42}}) {
		t.Errorf("Not as expected: %v", r)
	}

	r.Adjust(43, 1)
	if !reflect.DeepEqual(r.regions, []Region{{15, 25}, {31, 42}}) {
		t.Errorf("Not as expected: %v", r)
	}

	r.Adjust(44, -5)
	if !reflect.DeepEqual(r.regions, []Region{{15, 25}, {31, 39}}) {
		t.Errorf("Not as expected: %v", r)
	}
	r.Adjust(44, -5)
	if !reflect.DeepEqual(r.regions, []Region{{15, 25}, {31, 39}}) {
		t.Errorf("Not as expected: %v", r)
	}
	r.Adjust(43, -5)
	if !reflect.DeepEqual(r.regions, []Region{{15, 25}, {31, 38}}) {
		t.Errorf("Not as expected: %v", r)
	}
}

// Verified against ST3
func TestRegionSetflush(t *testing.T) {
	var r RegionSet
	r.Add(Region{10, 20})
	r.Add(Region{15, 23})
	if !reflect.DeepEqual(r.regions, []Region{{10, 23}}) {
		t.Errorf("Not as expected: %v", r)
	}
	r.Add(Region{5, 10})
	if !reflect.DeepEqual(r.regions, []Region{{10, 23}, {5, 10}}) {
		t.Errorf("Not as expected: %v", r)
	}

	r.Add(Region{2, 6})
	if !reflect.DeepEqual(r.regions, []Region{{10, 23}, {2, 10}}) {
		t.Errorf("Not as expected: %v", r)
	}
	r.Clear()
	r.Add(Region{10, 10})
	r.Add(Region{10, 11})
	if !reflect.DeepEqual(r.regions, []Region{{10, 11}}) {
		t.Errorf("Not as expected: %v", r)
	}
}

// Verified against ST3
func TestRegionSetAdjust2(t *testing.T) {
	var r RegionSet

	r.AddAll([]Region{
		{10, 20},
		{25, 35},
	})

	r.Adjust(43, -25)
	if !reflect.DeepEqual(r.regions, []Region{{10, 18}, {18, 18}}) {
		t.Errorf("Not as expected: %v", r)
	}
}

func TestRegionSetCut(t *testing.T) {
	tests := []struct {
		A, B Region
		Out  RegionSet
	}{
		{Region{10, 20}, Region{0, 5}, RegionSet{regions: []Region{{10, 20}}}},
		{Region{10, 20}, Region{12, 15}, RegionSet{regions: []Region{{10, 12}, {15, 20}}}},
		{Region{10, 20}, Region{5, 15}, RegionSet{regions: []Region{{15, 20}}}},
		{Region{10, 20}, Region{15, 20}, RegionSet{regions: []Region{{10, 15}}}},
	}
	for i, test := range tests {
		var rs RegionSet
		rs.Add(test.A)
		t.Log(rs)
		if res := rs.Cut(test.B); !reflect.DeepEqual(res, test.Out) {
			t.Errorf("Test %d; Expected %v, got: %v", i, test.Out, res)
		}
	}
}

func TestRegionSetAdd(t *testing.T) {
	tests := []struct {
		A   []Region
		B   Region
		Out []Region
	}{
		{[]Region{{10, 20}}, Region{0, 5}, []Region{{10, 20}, {0, 5}}},
		{[]Region{{10, 20}}, Region{12, 15}, []Region{{10, 20}}},
		{[]Region{{10, 20}}, Region{5, 15}, []Region{{5, 20}}},
		{[]Region{{10, 20}}, Region{15, 25}, []Region{{10, 25}}},
		{[]Region{{10, 20}}, Region{20, 25}, []Region{{10, 20}, {20, 25}}},
		{[]Region{{10, 15}, {20, 25}}, Region{12, 23}, []Region{{10, 25}}},
	}
	for i, test := range tests {
		var v RegionSet
		v.AddAll(test.A)
		v.Add(test.B)
		if !reflect.DeepEqual(v.Regions(), test.Out) {
			t.Errorf("Test %d; Expected %v, got: %v", i, test.Out, v.Regions())
		}
	}
}

func TestRegionSubtract(t *testing.T) {
	tests := []struct {
		A      []Region
		B      Region
		expect []Region
	}{
		{
			[]Region{{1, 4}, {6, 10}, {15, 25}},
			Region{6, 10},
			[]Region{{1, 4}, {15, 25}},
		},
		{
			[]Region{{6, 10}, {15, 25}},
			Region{7, 9},
			[]Region{{6, 7}, {9, 10}, {15, 25}},
		},
	}
	for i, test := range tests {
		var v RegionSet
		v.AddAll(test.A)
		v.Substract(test.B)
		if !reflect.DeepEqual(v.Regions(), test.expect) {
			t.Errorf("Test %d; Expected %v, got: %v", i, test.expect, v.Regions())
		}
	}
}
<commit_msg>Add some tests for adding many regions at once.<commit_after>// Copyright 2013 Fredrik Ehnbom
// Use of this source code is governed by a 2-clause
// BSD-style license that can be found in the LICENSE file.

package text

import (
	"reflect"
	"testing"
)

// Verified against ST3
func TestRegionSetAdjust(t *testing.T) {
	var r RegionSet

	r.AddAll([]Region{
		{10, 20},
		{25, 35},
	})

	r.Adjust(2, 5)
	if !reflect.DeepEqual(r.regions, []Region{{15, 25}, {30, 40}}) {
		t.Errorf("Not as expected: %v", r)
	}

	r.Adjust(30, 1)
	if !reflect.DeepEqual(r.regions, []Region{{15, 25}, {31, 41}}) {
		t.Errorf("Not as expected: %v", r)
	}

	r.Adjust(41, 1)
	if !reflect.DeepEqual(r.regions, []Region{{15, 25}, {31, 42}}) {
		t.Errorf("Not as expected: %v", r)
	}

	r.Adjust(43, 1)
	if !reflect.DeepEqual(r.regions, []Region{{15, 25}, {31, 42}}) {
		t.Errorf("Not as expected: %v", r)
	}

	r.Adjust(44, -5)
	if !reflect.DeepEqual(r.regions, []Region{{15, 25}, {31, 39}}) {
		t.Errorf("Not as expected: %v", r)
	}
	r.Adjust(44, -5)
	if !reflect.DeepEqual(r.regions, []Region{{15, 25}, {31, 39}}) {
		t.Errorf("Not as expected: %v", r)
	}
	r.Adjust(43, -5)
	if !reflect.DeepEqual(r.regions, []Region{{15, 25}, {31, 38}}) {
		t.Errorf("Not as expected: %v", r)
	}
}

// Verified against ST3
func TestRegionSetflush(t *testing.T) {
	var r RegionSet
	r.Add(Region{10, 20})
	r.Add(Region{15, 23})
	if !reflect.DeepEqual(r.regions, []Region{{10, 23}}) {
		t.Errorf("Not as expected: %v", r)
	}
	r.Add(Region{5, 10})
	if !reflect.DeepEqual(r.regions, []Region{{10, 23}, {5, 10}}) {
		t.Errorf("Not as expected: %v", r)
	}

	r.Add(Region{2, 6})
	if !reflect.DeepEqual(r.regions, []Region{{10, 23}, {2, 10}}) {
		t.Errorf("Not as expected: %v", r)
	}
	r.Clear()
	r.Add(Region{10, 10})
	r.Add(Region{10, 11})
	if !reflect.DeepEqual(r.regions, []Region{{10, 11}}) {
		t.Errorf("Not as expected: %v", r)
	}
}

// Verified against ST3
func TestRegionSetAdjust2(t *testing.T) {
	var r RegionSet

	r.AddAll([]Region{
		{10, 20},
		{25, 35},
	})

	r.Adjust(43, -25)
	if !reflect.DeepEqual(r.regions, []Region{{10, 18}, {18, 18}}) {
		t.Errorf("Not as expected: %v", r)
	}
}

func TestRegionSetCut(t *testing.T) {
	tests := []struct {
		A, B Region
		Out  RegionSet
	}{
		{Region{10, 20}, Region{0, 5}, RegionSet{regions: []Region{{10, 20}}}},
		{Region{10, 20}, Region{12, 15}, RegionSet{regions: []Region{{10, 12}, {15, 20}}}},
		{Region{10, 20}, Region{5, 15}, RegionSet{regions: []Region{{15, 20}}}},
		{Region{10, 20}, Region{15, 20}, RegionSet{regions: []Region{{10, 15}}}},
	}
	for i, test := range tests {
		var rs RegionSet
		rs.Add(test.A)
		t.Log(rs)
		if res := rs.Cut(test.B); !reflect.DeepEqual(res, test.Out) {
			t.Errorf("Test %d; Expected %v, got: %v", i, test.Out, res)
		}
	}
}

func TestRegionSetAdd(t *testing.T) {
	tests := []struct {
		A   []Region
		B   Region
		Out []Region
	}{
		{[]Region{{10, 20}}, Region{0, 5}, []Region{{10, 20}, {0, 5}}},
		{[]Region{{10, 20}}, Region{12, 15}, []Region{{10, 20}}},
		{[]Region{{10, 20}}, Region{5, 15}, []Region{{5, 20}}},
		{[]Region{{10, 20}}, Region{15, 25}, []Region{{10, 25}}},
		{[]Region{{10, 20}}, Region{20, 25}, []Region{{10, 20}, {20, 25}}},
		{[]Region{{10, 15}, {20, 25}}, Region{12, 23}, []Region{{10, 25}}},
	}
	for i, test := range tests {
		var v RegionSet
		v.AddAll(test.A)
		v.Add(test.B)
		if !reflect.DeepEqual(v.Regions(), test.Out) {
			t.Errorf("Test %d; Expected %v, got: %v", i, test.Out, v.Regions())
		}
	}
}

func TestRegionSetAddAll(t *testing.T) {
	tests := []struct {
		in  []Region
		exp []Region
	}{
		{
			[]Region{{5, 15}, {0, 20}, {100, 90}, {10, 25}, {45, 30}},
			[]Region{{0, 25}, {100, 90}, {45, 30}},
		},
		{
			[]Region{{100, 50}, {20, 5}, {0, 10}, {30, 40}, {15, 25}},
			[]Region{{100, 50}, {25, 0}, {30, 40}},
		},
	}
	for i, test := range tests {
		var v RegionSet
		v.AddAll(test.in)
		if !reflect.DeepEqual(v.Regions(), test.exp) {
			t.Errorf("Test %d; Expected %v, got: %v", i, test.exp, v.Regions())
		}
	}
}

func TestRegionSubtract(t *testing.T) {
	tests := []struct {
		A      []Region
		B      Region
		expect []Region
	}{
		{
			[]Region{{1, 4}, {6, 10}, {15, 25}},
			Region{6, 10},
			[]Region{{1, 4}, {15, 25}},
		},
		{
			[]Region{{6, 10}, {15, 25}},
			Region{7, 9},
			[]Region{{6, 7}, {9, 10}, {15, 25}},
		},
	}
	for i, test := range tests {
		var v RegionSet
		v.AddAll(test.A)
		v.Substract(test.B)
		if !reflect.DeepEqual(v.Regions(), test.expect) {
			t.Errorf("Test %d; Expected %v, got: %v", i, test.expect, v.Regions())
		}
	}
}
<|endoftext|>


<commit_before>package assert

import (
	"reflect"
	"testing"
)

type failFunc func(format string, args ...interface{})

type Results struct {
	results []interface{}
	onFail  failFunc
}

type DoTestFunc func(args ...interface{}) *Results

func isNillable(v interface{}) bool {
	if v == nil {
		return true
	}

	k := reflect.TypeOf(v).Kind()
	return k == reflect.Ptr || k == reflect.Chan || k == reflect.Func ||
		k == reflect.Interface || k == reflect.Map || k == reflect.Slice
}

func isNil(val interface{}) bool {
	return val == nil || reflect.ValueOf(val).IsNil()
}

func Make(t *testing.T, f ...failFunc) DoTestFunc {
	onFail := t.Errorf

	if len(f) > 0 {
		onFail = f[0]
	}

	return func(args ...interface{}) *Results {
		return &Results{args, onFail}
	}
}

func (r *Results) Equal(expect ...interface{}) *Results {

	if len(r.results) != len(expect) {
		r.onFail("Equal Failed with Parameter count mismatch expected: [%v] got: [%v]\n%s", expect, r.results, SourceInfo(2))
	}

	for i := range r.results {
		// if return value is a pointer then derefernce it to the value before comparison
		if !isNil(r.results[i]) && reflect.TypeOf(r.results[i]).Kind() == reflect.Ptr {
			r.results[i] = reflect.ValueOf(r.results[i]).Elem().Interface()
		}

		if !reflect.DeepEqual(r.results[i], expect[i]) {
			r.onFail("Equal Expected: [%v] got: [%v]\n%s", expect, r.results, SourceInfo(2))
		}
	}
	return r
}

func (r *Results) NotEqual(expect ...interface{}) *Results {

	if len(r.results) != len(expect) {
		r.onFail("Not Equal Failed with Parameter count mismatch expected: [%v] got: [%v]\n%s", expect, r.results, SourceInfo(2))
	}

	if reflect.DeepEqual(r.results, expect) {
		r.onFail("NotEqual Not Expecting: [%v] got: [%v]\n%s", expect, r.results, SourceInfo(2))
	}
	return r
}

func (r *Results) NoError() *Results {
	for _, v := range r.results {
		if err, ok := v.(error); ok {
			r.onFail("NoError Expecting: [no error] got error: [%v]\n%s", err, SourceInfo(2))
		}
	}
	return r
}

func (r *Results) HasError() *Results {
	for _, v := range r.results {
		if _, ok := v.(error); ok {
			return r
		}
	}
	r.onFail("NoError Expecting: [error] got no error:\n%s", SourceInfo(2))
	return r
}

func (r *Results) IsNil() *Results {
	for _, val := range r.results {
		if val != nil && isNillable(val) && !reflect.ValueOf(val).IsNil() {
			r.onFail("IsNil Expecting: [nil] got: [%v]\n%s", val, SourceInfo(2))
		}
	}
	return r
}

func (r *Results) NotNil() *Results {
	for _, val := range r.results {
		if val == nil || (isNillable(val) && reflect.ValueOf(val).IsNil()) {
			r.onFail("NotNil Expecting: [not nil] got: [%v]\n%s", val, SourceInfo(2))
		}
	}
	return r
}
<commit_msg>fixed panic in isNil on non nillable values<commit_after>package assert

import (
	"reflect"
	"testing"
)

type failFunc func(format string, args ...interface{})

type Results struct {
	results []interface{}
	onFail  failFunc
}

type DoTestFunc func(args ...interface{}) *Results

func isNillable(v interface{}) bool {
	if v == nil {
		return true
	}

	k := reflect.TypeOf(v).Kind()
	return k == reflect.Ptr || k == reflect.Chan || k == reflect.Func ||
		k == reflect.Interface || k == reflect.Map || k == reflect.Slice
}

func isNil(val interface{}) bool {
	return isNillable(val) && (val == nil || reflect.ValueOf(val).IsNil())
}

func Make(t *testing.T, f ...failFunc) DoTestFunc {
	onFail := t.Errorf

	if len(f) > 0 {
		onFail = f[0]
	}

	return func(args ...interface{}) *Results {
		return &Results{args, onFail}
	}
}

func (r *Results) Equal(expect ...interface{}) *Results {

	if len(r.results) != len(expect) {
		r.onFail("Equal Failed with Parameter count mismatch expected: [%v] got: [%v]\n%s", expect, r.results, SourceInfo(2))
	}

	for i := range r.results {
		// if return value is a pointer then derefernce it to the value before comparison
		if !isNil(r.results[i]) && reflect.TypeOf(r.results[i]).Kind() == reflect.Ptr {
			r.results[i] = reflect.ValueOf(r.results[i]).Elem().Interface()
		}

		if !reflect.DeepEqual(r.results[i], expect[i]) {
			r.onFail("Equal Expected: [%v] got: [%v]\n%s", expect, r.results, SourceInfo(2))
		}
	}
	return r
}

func (r *Results) NotEqual(expect ...interface{}) *Results {

	if len(r.results) != len(expect) {
		r.onFail("Not Equal Failed with Parameter count mismatch expected: [%v] got: [%v]\n%s", expect, r.results, SourceInfo(2))
	}

	if reflect.DeepEqual(r.results, expect) {
		r.onFail("NotEqual Not Expecting: [%v] got: [%v]\n%s", expect, r.results, SourceInfo(2))
	}
	return r
}

func (r *Results) NoError() *Results {
	for _, v := range r.results {
		if err, ok := v.(error); ok {
			r.onFail("NoError Expecting: [no error] got error: [%v]\n%s", err, SourceInfo(2))
		}
	}
	return r
}

func (r *Results) HasError() *Results {
	for _, v := range r.results {
		if _, ok := v.(error); ok {
			return r
		}
	}
	r.onFail("NoError Expecting: [error] got no error:\n%s", SourceInfo(2))
	return r
}

func (r *Results) IsNil() *Results {
	for _, val := range r.results {
		if val != nil && isNillable(val) && !reflect.ValueOf(val).IsNil() {
			r.onFail("IsNil Expecting: [nil] got: [%v]\n%s", val, SourceInfo(2))
		}
	}
	return r
}

func (r *Results) NotNil() *Results {
	for _, val := range r.results {
		if val == nil || (isNillable(val) && reflect.ValueOf(val).IsNil()) {
			r.onFail("NotNil Expecting: [not nil] got: [%v]\n%s", val, SourceInfo(2))
		}
	}
	return r
}
<|endoftext|>


<commit_before>package manta

import (
	"encoding/json"

	"github.com/dotabuff/manta/dota"
	"github.com/golang/protobuf/proto"
)

// Field is always filled, table only for sub-tables
type dt_property struct {
	Field *dt_field
	Table *dt
}

// A datatable field
type dt_field struct {
	Name    string
	Encoder string
	Type    string
	Index   int32

	Flags     *int32
	BitCount  *int32
	LowValue  *float32
	HighValue *float32

	Version    *int32
	Serializer *PropertySerializer `json:"-"`
}

// A single datatable
type dt struct {
	Name       string
	Flags      *int32
	Version    int32
	Properties []*dt_property
}

// The flattened serializers object
type flattened_serializers struct {
	Serializers map[string]map[int32]*dt // serializer name -> [versions]
	proto       *dota.CSVCMsg_FlattenedSerializer
	pst         *PropertySerializerTable
}

// Dumps a flattened table as json
func (sers *flattened_serializers) dump_json(name string) string {
	// Can't marshal map[int32]x
	type jContainer struct {
		Version int32
		Data    *dt
	}

	j := make([]jContainer, 0)
	for i, o := range sers.Serializers[name] {
		j = append(j, jContainer{i, o})
	}

	str, _ := json.MarshalIndent(j, "", "  ") // two space ident
	return string(str)
}

// Fills properties for a data table
func (sers *flattened_serializers) recurse_table(cur *dota.ProtoFlattenedSerializerT) *dt {
	// Basic table structure
	table := &dt{
		Name:       sers.proto.GetSymbols()[cur.GetSerializerNameSym()],
		Version:    cur.GetSerializerVersion(),
		Properties: make([]*dt_property, 0),
	}

	props := sers.proto.GetFields()

	// Append all the properties
	for _, idx := range cur.GetFieldsIndex() {
		pField := props[idx]
		prop := &dt_property{nil, nil}

		// Field can always be set
		prop.Field = &dt_field{
			Name:  sers.proto.GetSymbols()[pField.GetVarNameSym()],
			Index: -1,

			Flags:     pField.EncodeFlags,
			BitCount:  pField.BitCount,
			LowValue:  pField.LowValue,
			HighValue: pField.HighValue,

			Type:       (sers.proto.GetSymbols()[pField.GetVarTypeSym()]),
			Version:    pField.FieldSerializerVersion,
			Serializer: nil,
		}

		// Fill the serializer
		sers.pst.FillSerializer(prop.Field)

		// Optional: Attach encoder
		if pField.VarEncoderSym != nil {
			prop.Field.Encoder = sers.proto.GetSymbols()[pField.GetVarEncoderSym()]
		}

		// Optional: Attach the serializer version for the property if applicable
		if pField.FieldSerializerNameSym != nil {
			pFieldName := sers.proto.GetSymbols()[pField.GetFieldSerializerNameSym()]
			pFieldVersion := pField.GetFieldSerializerVersion()
			pSerializer := sers.Serializers[pFieldName][pFieldVersion]

			if pSerializer == nil {
				_panicf("Error: Serializer version %d for %s hasn't been added yet.", pFieldVersion, pFieldName)
			}

			prop.Table = pSerializer
		}

		// Optional: Adjust array fields
		if prop.Field.Serializer.IsArray {
			// Add our own temp table for the array
			tmpDt := &dt{
				Name:       prop.Field.Name,
				Flags:      nil,
				Version:    0,
				Properties: make([]*dt_property, 0),
			}

			// Add each array field to the table
			for i := uint32(0); i < prop.Field.Serializer.Length; i++ {
				tmpDt.Properties = append(tmpDt.Properties, &dt_property{
					Field: &dt_field{
						Name:       _sprintf("%04d", i),
						Encoder:    prop.Field.Encoder,
						Type:       prop.Field.Serializer.Name,
						Index:      int32(i),
						Flags:      prop.Field.Flags,
						BitCount:   prop.Field.BitCount,
						LowValue:   prop.Field.LowValue,
						HighValue:  prop.Field.HighValue,
						Version:    prop.Field.Version,
						Serializer: prop.Field.Serializer.ArraySerializer,
					},
					Table: prop.Table, // This carries on the actual table instead of overriding it
				})

				// Copy parent prop to rename it's name according to the array index
				if prop.Table != nil {
					nTable := *prop.Table
					nTable.Name = _sprintf("%04d", i)
					tmpDt.Properties[len(tmpDt.Properties)-1].Table = &nTable
				}
			}

			prop.Table = tmpDt
		}

		table.Properties = append(
			table.Properties,
			prop,
		)
	}

	return table
}

// Parses a CDemoSendTables packet
func ParseSendTables(m *dota.CDemoSendTables, pst *PropertySerializerTable) *flattened_serializers {
	// This packet just contains a single large buffer
	r := NewReader(m.GetData())

	// The buffer starts with a varint encoded length
	size := int(r.readVarUint32())
	if size != r.remBytes() {
		_panicf("expected %d additional bytes, got %d", size, r.remBytes())
	}

	// Read the rest of the buffer as a CSVCMsg_FlattenedSerializer.
	buf := r.readBytes(size)
	msg := &dota.CSVCMsg_FlattenedSerializer{}
	if err := proto.Unmarshal(buf, msg); err != nil {
		_panicf("cannot decode proto: %s", err)
	}

	// Create the flattened_serializers object and fill it
	fs := &flattened_serializers{
		Serializers: make(map[string]map[int32]*dt),
		proto:       msg,
		pst:         pst,
	}

	// Iterate through all flattened serializers and fill their properties
	for _, o := range msg.GetSerializers() {
		sName := msg.GetSymbols()[o.GetSerializerNameSym()]
		sVer := o.GetSerializerVersion()

		if fs.Serializers[sName] == nil {
			fs.Serializers[sName] = make(map[int32]*dt)
		}

		fs.Serializers[sName][sVer] = fs.recurse_table(o)
	}

	return fs
}

// Internal callback for OnCDemoSendTables.
func (p *Parser) onCDemoSendTables(m *dota.CDemoSendTables) error {
	p.Serializers = ParseSendTables(m, GetDefaultPropertySerializerTable()).Serializers
	return nil
}
<commit_msg>Overwrite encoders for old replays<commit_after>package manta

import (
	"encoding/json"

	"github.com/dotabuff/manta/dota"
	"github.com/golang/protobuf/proto"
)

// Field is always filled, table only for sub-tables
type dt_property struct {
	Field *dt_field
	Table *dt
}

// A datatable field
type dt_field struct {
	Name    string
	Encoder string
	Type    string
	Index   int32

	Flags     *int32
	BitCount  *int32
	LowValue  *float32
	HighValue *float32

	Version    *int32
	Serializer *PropertySerializer `json:"-"`
}

// A single datatable
type dt struct {
	Name       string
	Flags      *int32
	Version    int32
	Properties []*dt_property
}

// The flattened serializers object
type flattened_serializers struct {
	Serializers map[string]map[int32]*dt // serializer name -> [versions]
	proto       *dota.CSVCMsg_FlattenedSerializer
	pst         *PropertySerializerTable
}

// Dumps a flattened table as json
func (sers *flattened_serializers) dump_json(name string) string {
	// Can't marshal map[int32]x
	type jContainer struct {
		Version int32
		Data    *dt
	}

	j := make([]jContainer, 0)
	for i, o := range sers.Serializers[name] {
		j = append(j, jContainer{i, o})
	}

	str, _ := json.MarshalIndent(j, "", "  ") // two space ident
	return string(str)
}

// Fills properties for a data table
func (sers *flattened_serializers) recurse_table(cur *dota.ProtoFlattenedSerializerT) *dt {
	// Basic table structure
	table := &dt{
		Name:       sers.proto.GetSymbols()[cur.GetSerializerNameSym()],
		Version:    cur.GetSerializerVersion(),
		Properties: make([]*dt_property, 0),
	}

	props := sers.proto.GetFields()

	// Append all the properties
	for _, idx := range cur.GetFieldsIndex() {
		pField := props[idx]
		prop := &dt_property{nil, nil}

		// Field can always be set
		prop.Field = &dt_field{
			Name:  sers.proto.GetSymbols()[pField.GetVarNameSym()],
			Index: -1,

			Flags:     pField.EncodeFlags,
			BitCount:  pField.BitCount,
			LowValue:  pField.LowValue,
			HighValue: pField.HighValue,

			Type:       (sers.proto.GetSymbols()[pField.GetVarTypeSym()]),
			Version:    pField.FieldSerializerVersion,
			Serializer: nil,
		}

		// Fill the serializer
		sers.pst.FillSerializer(prop.Field)

		// Optional: Attach encoder
		if pField.VarEncoderSym != nil {
			prop.Field.Encoder = sers.proto.GetSymbols()[pField.GetVarEncoderSym()]
			// Dump decoders: _debugfl(10, "Name: %v (%v), Enc: %v, %v", prop.Field.Name, prop.Field.Type, prop.Field.Encoder, table.Name)
		} else {
			// set manual decoders for old replays
			switch prop.Field.Name {

			// QAngle
			case "m_angRotation":
				fallthrough
			case "m_angInitialAngles":
				fallthrough
			case "m_vLightDirection":
				fallthrough
			case "m_ragAngles":
				fallthrough
			case "angLocalAngles":
				fallthrough
			case "angExtraLocalAngles":
				if table.Name == "CBodyComponentBaseAnimatingOverlay" {
					prop.Field.Encoder = "qangle_pitch_yaw"
				} else {
					prop.Field.Encoder = "QAngle"
				}

			// coord
			case "m_flElasticity":
				fallthrough
			case "m_viewtarget":
				fallthrough
			case "dirPrimary":
				fallthrough
			case "origin":
				fallthrough
			case "localSound":
				fallthrough
			case "m_location":
				fallthrough
			case "m_poolOrigin":
				fallthrough
			case "m_vecLadderDir":
				fallthrough
			case "m_vecPlayerMountPositionTop":
				fallthrough
			case "m_vecPlayerMountPositionBottom":
				fallthrough
			case "m_ragPos":
				fallthrough
			case "vecLocalOrigin":
				fallthrough
			case "m_WorldMins":
				fallthrough
			case "m_WorldMaxs":
				fallthrough
			case "m_vecEndPos":
				prop.Field.Encoder = "coord"

			// normal
			case "m_vecLadderNormal":
				prop.Field.Encoder = "normal"
			}
		}

		// Optional: Attach the serializer version for the property if applicable
		if pField.FieldSerializerNameSym != nil {
			pFieldName := sers.proto.GetSymbols()[pField.GetFieldSerializerNameSym()]
			pFieldVersion := pField.GetFieldSerializerVersion()
			pSerializer := sers.Serializers[pFieldName][pFieldVersion]

			if pSerializer == nil {
				_panicf("Error: Serializer version %d for %s hasn't been added yet.", pFieldVersion, pFieldName)
			}

			prop.Table = pSerializer
		}

		// Optional: Adjust array fields
		if prop.Field.Serializer.IsArray {
			// Add our own temp table for the array
			tmpDt := &dt{
				Name:       prop.Field.Name,
				Flags:      nil,
				Version:    0,
				Properties: make([]*dt_property, 0),
			}

			// Add each array field to the table
			for i := uint32(0); i < prop.Field.Serializer.Length; i++ {
				tmpDt.Properties = append(tmpDt.Properties, &dt_property{
					Field: &dt_field{
						Name:       _sprintf("%04d", i),
						Encoder:    prop.Field.Encoder,
						Type:       prop.Field.Serializer.Name,
						Index:      int32(i),
						Flags:      prop.Field.Flags,
						BitCount:   prop.Field.BitCount,
						LowValue:   prop.Field.LowValue,
						HighValue:  prop.Field.HighValue,
						Version:    prop.Field.Version,
						Serializer: prop.Field.Serializer.ArraySerializer,
					},
					Table: prop.Table, // This carries on the actual table instead of overriding it
				})

				// Copy parent prop to rename it's name according to the array index
				if prop.Table != nil {
					nTable := *prop.Table
					nTable.Name = _sprintf("%04d", i)
					tmpDt.Properties[len(tmpDt.Properties)-1].Table = &nTable
				}
			}

			prop.Table = tmpDt
		}

		table.Properties = append(
			table.Properties,
			prop,
		)
	}

	return table
}

// Parses a CDemoSendTables packet
func ParseSendTables(m *dota.CDemoSendTables, pst *PropertySerializerTable) *flattened_serializers {
	// This packet just contains a single large buffer
	r := NewReader(m.GetData())

	// The buffer starts with a varint encoded length
	size := int(r.readVarUint32())
	if size != r.remBytes() {
		_panicf("expected %d additional bytes, got %d", size, r.remBytes())
	}

	// Read the rest of the buffer as a CSVCMsg_FlattenedSerializer.
	buf := r.readBytes(size)
	msg := &dota.CSVCMsg_FlattenedSerializer{}
	if err := proto.Unmarshal(buf, msg); err != nil {
		_panicf("cannot decode proto: %s", err)
	}

	// Create the flattened_serializers object and fill it
	fs := &flattened_serializers{
		Serializers: make(map[string]map[int32]*dt),
		proto:       msg,
		pst:         pst,
	}

	// Iterate through all flattened serializers and fill their properties
	for _, o := range msg.GetSerializers() {
		sName := msg.GetSymbols()[o.GetSerializerNameSym()]
		sVer := o.GetSerializerVersion()

		if fs.Serializers[sName] == nil {
			fs.Serializers[sName] = make(map[int32]*dt)
		}

		fs.Serializers[sName][sVer] = fs.recurse_table(o)
	}

	return fs
}

// Internal callback for OnCDemoSendTables.
func (p *Parser) onCDemoSendTables(m *dota.CDemoSendTables) error {
	p.Serializers = ParseSendTables(m, GetDefaultPropertySerializerTable()).Serializers
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2015 The rkt Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package networking

import (
	"fmt"
	"net"
	"strconv"

	"github.com/coreos/go-iptables/iptables"
)

func (e *podEnv) forwardPorts(fps []ForwardedPort, defIP net.IP) error {
	if len(fps) == 0 {
		return nil
	}

	ipt, err := iptables.New()
	if err != nil {
		return err
	}

	// Create a separate chain for this pod. This helps with debugging
	// and makes it easier to cleanup
	chain := e.portFwdChain()

	if err = ipt.NewChain("nat", chain); err != nil {
		return err
	}

	rule := e.portFwdRuleSpec(chain)

	for _, entry := range [][]string{
		{"nat", "PREROUTING"}, // outside traffic hitting this host
		{"nat", "OUTPUT"},     // traffic originating on this host
	} {
		exists, err := ipt.Exists(entry[0], entry[1], rule...)
		if err != nil {
			return err
		}
		if !exists {
			err = ipt.Insert(entry[0], entry[1], 1, rule...)
			if err != nil {
				return err
			}
		}
	}

	for _, p := range fps {
		if err = forwardPort(ipt, chain, &p, defIP); err != nil {
			return err
		}
	}

	return nil
}

func forwardPort(ipt *iptables.IPTables, chain string, p *ForwardedPort, defIP net.IP) error {
	dst := fmt.Sprintf("%v:%v", defIP, p.PodPort)
	dport := strconv.Itoa(int(p.HostPort))

	return ipt.AppendUnique("nat", chain, "-p", p.Protocol, "--dport", dport, "-j", "DNAT", "--to-destination", dst)
}

func (e *podEnv) unforwardPorts() error {
	ipt, err := iptables.New()
	if err != nil {
		return err
	}

	chain := e.portFwdChain()

	rule := e.portFwdRuleSpec(chain)

	// There's no clean way now to test if a chain exists or
	// even if a rule exists if the chain is not present.
	// So we swallow the errors for now :(
	// TODO(eyakubovich): move to using libiptc for iptable
	// manipulation

	// outside traffic hitting this hot
	ipt.Delete("nat", "PREROUTING", rule...)

	// traffic originating on this host
	ipt.Delete("nat", "OUTPUT", rule...)

	// there should be no references, delete the chain
	ipt.ClearChain("nat", chain)
	ipt.DeleteChain("nat", chain)

	return nil
}

func (e *podEnv) portFwdChain() string {
	return "RKT-PFWD-" + e.podID.String()[0:8]
}

func (e *podEnv) portFwdRuleSpec(chain string) []string {
	return []string{"-m", "addrtype", "--dst-type", "LOCAL", "-j", chain}
}
<commit_msg>port forwarding: masquerade connections from localhost<commit_after>// Copyright 2015 The rkt Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package networking

import (
	"fmt"
	"net"
	"strconv"

	"github.com/coreos/go-iptables/iptables"
)

func (e *podEnv) forwardPorts(fps []ForwardedPort, defIP net.IP) error {
	if len(fps) == 0 {
		return nil
	}

	ipt, err := iptables.New()
	if err != nil {
		return err
	}

	// Create a separate chain for this pod. This helps with debugging
	// and makes it easier to cleanup
	chainDNAT := e.portFwdChain("DNAT")
	chainSNAT := e.portFwdChain("SNAT")

	if err = ipt.NewChain("nat", chainDNAT); err != nil {
		return err
	}

	if err = ipt.NewChain("nat", chainSNAT); err != nil {
		return err
	}

	chainRuleDNAT := e.portFwdChainRuleSpec(chainDNAT, "DNAT")
	chainRuleSNAT := e.portFwdChainRuleSpec(chainSNAT, "SNAT")

	for _, entry := range []struct {
		chain           string
		customChainRule []string
	}{
		{"POSTROUTING", chainRuleSNAT}, // traffic originating from this host
		{"PREROUTING", chainRuleDNAT},  // outside traffic hitting this host
		{"OUTPUT", chainRuleDNAT},      // traffic originating from this host
	} {
		exists, err := ipt.Exists("nat", entry.chain, entry.customChainRule...)
		if err != nil {
			return err
		}
		if !exists {
			err = ipt.Insert("nat", entry.chain, 1, entry.customChainRule...)
			if err != nil {
				return err
			}
		}
	}

	for _, p := range fps {

		dst := fmt.Sprintf("%v:%v", defIP, p.PodPort)
		dstIP := fmt.Sprintf("%v", defIP)
		dport := strconv.Itoa(int(p.HostPort))

		for _, r := range []struct {
			chain string
			rule  []string
		}{
			{ // Rewrite the destination
				chainDNAT,
				[]string{
					"-p", p.Protocol,
					"--dport", dport,
					"-j", "DNAT",
					"--to-destination", dst,
				},
			},
			{ // Rewrite the source for connections to localhost on the host
				chainSNAT,
				[]string{
					"-p", p.Protocol,
					"-s", "127.0.0.1",
					"-d", dstIP,
					"--dport", dport,
					"-j", "MASQUERADE",
				},
			},
		} {
			if err := ipt.AppendUnique("nat", r.chain, r.rule...); err != nil {
				return err
			}
		}
	}
	return nil
}

func (e *podEnv) unforwardPorts() error {
	ipt, err := iptables.New()
	if err != nil {
		return err
	}

	chainDNAT := e.portFwdChain("DNAT")
	chainSNAT := e.portFwdChain("SNAT")

	chainRuleDNAT := e.portFwdChainRuleSpec(chainDNAT, "DNAT")
	chainRuleSNAT := e.portFwdChainRuleSpec(chainSNAT, "SNAT")

	// There's no clean way now to test if a chain exists or
	// even if a rule exists if the chain is not present.
	// So we swallow the errors for now :(
	// TODO(eyakubovich): move to using libiptc for iptable
	// manipulation

	for _, entry := range []struct {
		chain           string
		customChainRule []string
	}{
		{"POSTROUTING", chainRuleSNAT}, // traffic originating on this host
		{"PREROUTING", chainRuleDNAT},  // outside traffic hitting this host
		{"OUTPUT", chainRuleDNAT},      // traffic originating on this host
	} {
		ipt.Delete("nat", entry.chain, entry.customChainRule...)
	}

	for _, entry := range []string{chainDNAT, chainSNAT} {
		ipt.ClearChain("nat", entry)
		ipt.DeleteChain("nat", entry)
	}
	return nil
}

func (e *podEnv) portFwdChain(name string) string {
	return fmt.Sprintf("RKT-PFWD-%s-%s", name, e.podID.String()[0:8])
}

func (e *podEnv) portFwdChainRuleSpec(chain string, name string) []string {
	switch name {
	case "SNAT":
		return []string{"-s", "127.0.0.1", "!", "-d", "127.0.0.1", "-j", chain}
	case "DNAT":
		return []string{"-m", "addrtype", "--dst-type", "LOCAL", "-j", chain}
	default:
		return nil
	}
}
<|endoftext|>


<commit_before>package w32syscall

import (
	"syscall"
	"unsafe"
)

var (
	modkernel32 = syscall.NewLazyDLL("kernel32.dll")
	modadvapi32 = syscall.NewLazyDLL("advapi32.dll")
	moduser32   = syscall.NewLazyDLL("user32.dll")

	procGetDynamicTimeZoneInformation = modkernel32.NewProc("GetDynamicTimeZoneInformation")
	procSetDynamicTimeZoneInformation = modkernel32.NewProc("SetDynamicTimeZoneInformation")

	procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges")
	procLookupPrivilegeValue  = modadvapi32.NewProc("LookupPrivilegeValueW")
	procRegCreateKeyExW       = modadvapi32.NewProc("RegCreateKeyExW")
	procRegDeleteKeyValueW    = modadvapi32.NewProc("RegDeleteKeyValueW")
	procRegDeleteTreeW        = modadvapi32.NewProc("RegDeleteTreeW")
	procRegGetValueW          = modadvapi32.NewProc("RegGetValueW")
	procRegSetKeyValueW       = modadvapi32.NewProc("RegSetKeyValueW")

	procExitWindowsEx       = moduser32.NewProc("ExitWindowsEx")
	procFindWindowW         = moduser32.NewProc("FindWindowW")
	procGetForegroundWindow = moduser32.NewProc("GetForegroundWindow")
	procSetForegroundWindow = moduser32.NewProc("SetForegroundWindow")
	procSendInput           = moduser32.NewProc("SendInput")
	procSendMessageW        = moduser32.NewProc("SendMessageW")
)

func GetDynamicTimeZoneInformation(timeZoneInformation *DynamicTimeZoneInformation) (err error) {
	r0, _, e1 := syscall.Syscall(procGetDynamicTimeZoneInformation.Addr(), 1,
		uintptr(unsafe.Pointer(timeZoneInformation)),
		0,
		0)
	if r0 == TIME_ZONE_ID_INVALID {
		if e1 != 0 {
			err = error(e1)
		} else {
			err = syscall.EINVAL
		}
	}
	return
}

func SetDynamicTimeZoneInformation(timeZoneInformation *DynamicTimeZoneInformation) (err error) {
	r0, _, e1 := syscall.Syscall(procSetDynamicTimeZoneInformation.Addr(), 1,
		uintptr(unsafe.Pointer(timeZoneInformation)),
		0,
		0)
	if r0 == 0 {
		if e1 != 0 {
			err = error(e1)
		} else {
			err = syscall.EINVAL
		}
	}
	return
}

func AdjustTokenPrivileges(tokenHandle syscall.Token, disableAllPrivileges bool, newState *TokenPrivileges, bufferLength uint32, previousState *TokenPrivileges, returnLength *uint32) (err error) {
	var _p0 uint32
	if disableAllPrivileges {
		_p0 = 1
	} else {
		_p0 = 0
	}
	r1, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6,
		uintptr(tokenHandle),
		uintptr(_p0),
		uintptr(unsafe.Pointer(newState)),
		uintptr(bufferLength),
		uintptr(unsafe.Pointer(previousState)),
		uintptr(unsafe.Pointer(returnLength)))
	if r1 == 0 {
		if e1 != 0 {
			err = error(e1)
		} else {
			err = syscall.EINVAL
		}
	}
	return
}

func LookupPrivilegeValue(systemName, name *uint16, luid *Luid) (err error) {
	r1, _, e1 := syscall.Syscall(procLookupPrivilegeValue.Addr(), 3,
		uintptr(unsafe.Pointer(systemName)),
		uintptr(unsafe.Pointer(name)),
		uintptr(unsafe.Pointer(luid)))
	if r1 == 0 {
		if e1 != 0 {
			err = error(e1)
		} else {
			err = syscall.EINVAL
		}
	}
	return
}

func RegCreateKeyEx(key syscall.Handle, subkey *uint16, reserved uint32, class *uint16, options uint32, desiredAccess uint32, securityAttributes *syscall.SecurityAttributes, result *syscall.Handle, disposition *uint32) (regerrno error) {
	r0, _, _ := syscall.Syscall9(procRegCreateKeyExW.Addr(), 9, uintptr(key), uintptr(unsafe.Pointer(subkey)), uintptr(reserved), uintptr(unsafe.Pointer(class)), uintptr(options), uintptr(desiredAccess), uintptr(unsafe.Pointer(securityAttributes)), uintptr(unsafe.Pointer(result)), uintptr(unsafe.Pointer(disposition)))
	if r0 != 0 {
		regerrno = syscall.Errno(r0)
	}
	return
}

func RegDeleteKeyValue(key syscall.Handle, subkey *uint16, valname *uint16) (regerrno error) {
	r0, _, _ := syscall.Syscall(procRegDeleteKeyValueW.Addr(), 3, uintptr(key), uintptr(unsafe.Pointer(subkey)), uintptr(unsafe.Pointer(valname)))
	if r0 != 0 {
		regerrno = syscall.Errno(r0)
	}
	return
}

func RegDeleteTree(key syscall.Handle, subkey *uint16) (regerrno error) {
	r0, _, _ := syscall.Syscall(procRegDeleteTreeW.Addr(), 2, uintptr(key), uintptr(unsafe.Pointer(subkey)), 0)
	if r0 != 0 {
		regerrno = syscall.Errno(r0)
	}
	return
}

func RegGetValue(key syscall.Handle, subkey *uint16, valname *uint16, flags uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) {
	r0, _, _ := syscall.Syscall9(procRegGetValueW.Addr(), 7, uintptr(key), uintptr(unsafe.Pointer(subkey)), uintptr(unsafe.Pointer(valname)), uintptr(flags), uintptr(unsafe.Pointer(valtype)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(buflen)), 0, 0)
	if r0 != 0 {
		regerrno = syscall.Errno(r0)
	}
	return
}

func RegSetKeyValue(key syscall.Handle, subkey *uint16, valname *uint16, valtype uint32, buf *byte, buflen uint32) (regerrno error) {
	r0, _, _ := syscall.Syscall6(procRegSetKeyValueW.Addr(), 6, uintptr(key), uintptr(unsafe.Pointer(subkey)), uintptr(unsafe.Pointer(valname)), uintptr(valtype), uintptr(unsafe.Pointer(buf)), uintptr(buflen))
	if r0 != 0 {
		regerrno = syscall.Errno(r0)
	}
	return
}

func ExitWindowsEx(flags uint, reason uint32) (err error) {
	r1, _, e1 := syscall.Syscall(procExitWindowsEx.Addr(), 2, uintptr(flags), uintptr(reason), 0)
	if r1 != 0 {
		if e1 != 0 {
			err = error(e1)
		} else {
			err = syscall.EINVAL
		}
	}
	return
}

func FindWindowW(className, windowName *uint16) (handle syscall.Handle, err error) {
	r1, _, e1 := syscall.Syscall(procFindWindowW.Addr(), 2, uintptr(unsafe.Pointer(className)), uintptr(unsafe.Pointer(windowName)), 0)
	if r1 != 0 {
		handle = syscall.Handle(r1)
	} else {
		if e1 != 0 {
			err = error(e1)
		} else {
			err = syscall.EINVAL
		}
	}
	return
}

func SetForegroundWindow(hwnd syscall.Handle) bool {
	r1, _, _ := syscall.Syscall(procSetForegroundWindow.Addr(), 1, uintptr(hwnd), 0, 0)
	return r1 != 0
}

func GetForegroundWindow() syscall.Handle {
	r1, _, _ := syscall.Syscall(procGetForegroundWindow.Addr(), 0, 0, 0, 0)
	return syscall.Handle(r1)
}

func SendInput(inputCount uint, inputs *Input, byteSize int) (count int, err error) {
	r1, _, e1 := syscall.Syscall(procSendInput.Addr(), 3, uintptr(inputCount), uintptr(unsafe.Pointer(inputs)), uintptr(byteSize))
	if r1 != 0 {
		count = int(r1)
	} else {
		if e1 != 0 {
			err = error(e1)
		} else {
			err = syscall.EINVAL
		}
	}
	return
}

func SendMessage(hwnd syscall.Handle, msg uint32, wparam, lparam uintptr) (result uintptr, err error) {
	result, _, e1 := syscall.Syscall6(procSendMessageW.Addr(), 4, uintptr(hwnd), uintptr(msg), wparam, lparam, 0, 0)
	if e1 != 0 {
		err = error(e1)
		return
	}
	return
}
<commit_msg>Add EnumWindows<commit_after>package w32syscall

import (
	"syscall"
	"unsafe"
)

var (
	modkernel32 = syscall.NewLazyDLL("kernel32.dll")
	modadvapi32 = syscall.NewLazyDLL("advapi32.dll")
	moduser32   = syscall.NewLazyDLL("user32.dll")

	procGetDynamicTimeZoneInformation = modkernel32.NewProc("GetDynamicTimeZoneInformation")
	procSetDynamicTimeZoneInformation = modkernel32.NewProc("SetDynamicTimeZoneInformation")

	procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges")
	procLookupPrivilegeValue  = modadvapi32.NewProc("LookupPrivilegeValueW")
	procRegCreateKeyExW       = modadvapi32.NewProc("RegCreateKeyExW")
	procRegDeleteKeyValueW    = modadvapi32.NewProc("RegDeleteKeyValueW")
	procRegDeleteTreeW        = modadvapi32.NewProc("RegDeleteTreeW")
	procRegGetValueW          = modadvapi32.NewProc("RegGetValueW")
	procRegSetKeyValueW       = modadvapi32.NewProc("RegSetKeyValueW")

	procEnumWindows         = moduser32.NewProc("EnumWindows")
	procExitWindowsEx       = moduser32.NewProc("ExitWindowsEx")
	procFindWindowW         = moduser32.NewProc("FindWindowW")
	procGetForegroundWindow = moduser32.NewProc("GetForegroundWindow")
	procSetForegroundWindow = moduser32.NewProc("SetForegroundWindow")
	procSendInput           = moduser32.NewProc("SendInput")
	procSendMessageW        = moduser32.NewProc("SendMessageW")
)

func GetDynamicTimeZoneInformation(timeZoneInformation *DynamicTimeZoneInformation) (err error) {
	r0, _, e1 := syscall.Syscall(procGetDynamicTimeZoneInformation.Addr(), 1,
		uintptr(unsafe.Pointer(timeZoneInformation)),
		0,
		0)
	if r0 == TIME_ZONE_ID_INVALID {
		if e1 != 0 {
			err = error(e1)
		} else {
			err = syscall.EINVAL
		}
	}
	return
}

func SetDynamicTimeZoneInformation(timeZoneInformation *DynamicTimeZoneInformation) (err error) {
	r0, _, e1 := syscall.Syscall(procSetDynamicTimeZoneInformation.Addr(), 1,
		uintptr(unsafe.Pointer(timeZoneInformation)),
		0,
		0)
	if r0 == 0 {
		if e1 != 0 {
			err = error(e1)
		} else {
			err = syscall.EINVAL
		}
	}
	return
}

func AdjustTokenPrivileges(tokenHandle syscall.Token, disableAllPrivileges bool, newState *TokenPrivileges, bufferLength uint32, previousState *TokenPrivileges, returnLength *uint32) (err error) {
	var _p0 uint32
	if disableAllPrivileges {
		_p0 = 1
	} else {
		_p0 = 0
	}
	r1, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6,
		uintptr(tokenHandle),
		uintptr(_p0),
		uintptr(unsafe.Pointer(newState)),
		uintptr(bufferLength),
		uintptr(unsafe.Pointer(previousState)),
		uintptr(unsafe.Pointer(returnLength)))
	if r1 == 0 {
		if e1 != 0 {
			err = error(e1)
		} else {
			err = syscall.EINVAL
		}
	}
	return
}

func LookupPrivilegeValue(systemName, name *uint16, luid *Luid) (err error) {
	r1, _, e1 := syscall.Syscall(procLookupPrivilegeValue.Addr(), 3,
		uintptr(unsafe.Pointer(systemName)),
		uintptr(unsafe.Pointer(name)),
		uintptr(unsafe.Pointer(luid)))
	if r1 == 0 {
		if e1 != 0 {
			err = error(e1)
		} else {
			err = syscall.EINVAL
		}
	}
	return
}

func RegCreateKeyEx(key syscall.Handle, subkey *uint16, reserved uint32, class *uint16, options uint32, desiredAccess uint32, securityAttributes *syscall.SecurityAttributes, result *syscall.Handle, disposition *uint32) (regerrno error) {
	r0, _, _ := syscall.Syscall9(procRegCreateKeyExW.Addr(), 9, uintptr(key), uintptr(unsafe.Pointer(subkey)), uintptr(reserved), uintptr(unsafe.Pointer(class)), uintptr(options), uintptr(desiredAccess), uintptr(unsafe.Pointer(securityAttributes)), uintptr(unsafe.Pointer(result)), uintptr(unsafe.Pointer(disposition)))
	if r0 != 0 {
		regerrno = syscall.Errno(r0)
	}
	return
}

func RegDeleteKeyValue(key syscall.Handle, subkey *uint16, valname *uint16) (regerrno error) {
	r0, _, _ := syscall.Syscall(procRegDeleteKeyValueW.Addr(), 3, uintptr(key), uintptr(unsafe.Pointer(subkey)), uintptr(unsafe.Pointer(valname)))
	if r0 != 0 {
		regerrno = syscall.Errno(r0)
	}
	return
}

func RegDeleteTree(key syscall.Handle, subkey *uint16) (regerrno error) {
	r0, _, _ := syscall.Syscall(procRegDeleteTreeW.Addr(), 2, uintptr(key), uintptr(unsafe.Pointer(subkey)), 0)
	if r0 != 0 {
		regerrno = syscall.Errno(r0)
	}
	return
}

func RegGetValue(key syscall.Handle, subkey *uint16, valname *uint16, flags uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) {
	r0, _, _ := syscall.Syscall9(procRegGetValueW.Addr(), 7, uintptr(key), uintptr(unsafe.Pointer(subkey)), uintptr(unsafe.Pointer(valname)), uintptr(flags), uintptr(unsafe.Pointer(valtype)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(buflen)), 0, 0)
	if r0 != 0 {
		regerrno = syscall.Errno(r0)
	}
	return
}

func RegSetKeyValue(key syscall.Handle, subkey *uint16, valname *uint16, valtype uint32, buf *byte, buflen uint32) (regerrno error) {
	r0, _, _ := syscall.Syscall6(procRegSetKeyValueW.Addr(), 6, uintptr(key), uintptr(unsafe.Pointer(subkey)), uintptr(unsafe.Pointer(valname)), uintptr(valtype), uintptr(unsafe.Pointer(buf)), uintptr(buflen))
	if r0 != 0 {
		regerrno = syscall.Errno(r0)
	}
	return
}

func EnumWindows(callback func(hwnd syscall.Handle, lparam uintptr) bool, lparam uintptr) (err error) {
	cb := func(hwnd syscall.Handle, lparam uintptr) int {
		if callback(hwnd, lparam) {
			return 1
		} else {
			return 0
		}
	}
	r1, _, e1 := syscall.Syscall(procEnumWindows.Addr(), 2, syscall.NewCallback(cb), lparam, 0)
	if r1 != 0 {
		if e1 != 0 {
			err = error(e1)
			return
		}
	}
	return
}

func ExitWindowsEx(flags uint, reason uint32) (err error) {
	r1, _, e1 := syscall.Syscall(procExitWindowsEx.Addr(), 2, uintptr(flags), uintptr(reason), 0)
	if r1 != 0 {
		if e1 != 0 {
			err = error(e1)
		} else {
			err = syscall.EINVAL
		}
	}
	return
}

func FindWindowW(className, windowName *uint16) (handle syscall.Handle, err error) {
	r1, _, e1 := syscall.Syscall(procFindWindowW.Addr(), 2, uintptr(unsafe.Pointer(className)), uintptr(unsafe.Pointer(windowName)), 0)
	if r1 != 0 {
		handle = syscall.Handle(r1)
	} else {
		if e1 != 0 {
			err = error(e1)
		} else {
			err = syscall.EINVAL
		}
	}
	return
}

func SetForegroundWindow(hwnd syscall.Handle) bool {
	r1, _, _ := syscall.Syscall(procSetForegroundWindow.Addr(), 1, uintptr(hwnd), 0, 0)
	return r1 != 0
}

func GetForegroundWindow() syscall.Handle {
	r1, _, _ := syscall.Syscall(procGetForegroundWindow.Addr(), 0, 0, 0, 0)
	return syscall.Handle(r1)
}

func SendInput(inputCount uint, inputs *Input, byteSize int) (count int, err error) {
	r1, _, e1 := syscall.Syscall(procSendInput.Addr(), 3, uintptr(inputCount), uintptr(unsafe.Pointer(inputs)), uintptr(byteSize))
	if r1 != 0 {
		count = int(r1)
	} else {
		if e1 != 0 {
			err = error(e1)
		} else {
			err = syscall.EINVAL
		}
	}
	return
}

func SendMessage(hwnd syscall.Handle, msg uint32, wparam, lparam uintptr) (result uintptr, err error) {
	result, _, e1 := syscall.Syscall6(procSendMessageW.Addr(), 4, uintptr(hwnd), uintptr(msg), wparam, lparam, 0, 0)
	if e1 != 0 {
		err = error(e1)
		return
	}
	return
}
<|endoftext|>