<commit_before>package lib

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/namsral/flag"
)

// ReservedSpace -
const ReservedSpace = 450000000 // 450Mb

// Config -
type Config struct {
	DryRun         bool     `json:"dryRun"`
	NotifyPlan     int      `json:"notifyPlan"`
	NotifyTransfer int      `json:"notifyTransfer"`
	ReservedAmount int64    `json:"reservedAmount"`
	ReservedUnit   string   `json:"reservedUnit"`
	RsyncArgs      []string `json:"rsyncArgs"`
	Version        string   `json:"version"`
	Verbosity      int      `json:"verbosity"`
	CheckForUpdate int      `json:"checkForUpdate"`
}

// NotifyPlan/NotifyTransfer possible values
// 0 - no notification
// 1 - simple notification
// 2 - detailed notification

// Settings -
type Settings struct {
	Config

	Port       string
	LogDir     string
	APIFolders []string

	Location string
	confName string
}

const defaultConfLocation = "/boot/config/plugins/unbalance"

// NewSettings -
func NewSettings(name, version string, locations []string) (*Settings, error) {
	var port, logDir, folders, rsyncFlags, rsyncArgs, apiFolders string
	var dryRun bool
	var notifyCalc, notifyMove, notifyPlan, notifyTransfer, verbosity, checkForUpdate int

	flagset := flag.NewFlagSet(os.Args[0], flag.ContinueOnError)

	flagset.StringVar(&port, "port", "6237", "port to run the server")
	flagset.StringVar(&logDir, "logdir", "/boot/logs", "pathname where log file will be written to")
	flagset.StringVar(&folders, "folders", "", "deprecated - do not use")
	flagset.BoolVar(&dryRun, "dryRun", true, "perform a dry-run rather than actual work")
	flagset.IntVar(&notifyCalc, "notifyCalc", 0, "deprecated - do not use") // deprecated
	flagset.IntVar(&notifyMove, "notifyMove", 0, "deprecated - do not use") // deprecated
	flagset.IntVar(&notifyPlan, "notifyPlan", 0, "notify via email after plan operation has completed (unraid notifications must be set up first): 0 - No notifications; 1 - Simple notifications; 2 - Detailed notifications")
	flagset.IntVar(&notifyTransfer, "notifyTransfer", 0, "notify via email after transfer operation has completed (unraid notifications must be set up first): 0 - No notifications; 1 - Simple notifications; 2 - Detailed notifications")
	flagset.StringVar(&rsyncFlags, "rsyncFlags", "", "deprecated - do not use") // deprecated
	flagset.StringVar(&rsyncArgs, "rsyncArgs", "", "custom rsync arguments")
	flagset.StringVar(&apiFolders, "apiFolders", "/var/local/emhttp", "folders to look for api endpoints")
	flagset.IntVar(&verbosity, "verbosity", 0, "include rsync output in log files: 0 (default) - include; 1 - do not include")
	flagset.IntVar(&checkForUpdate, "checkForUpdate", 1, "checkForUpdate: 0 - dont' check; 1 (default) - check")

	location := SearchFile(name, locations)
	if location != "" {
		flagset.String("config", filepath.Join(location, name), "config location")
	}

	if err := flagset.Parse(os.Args[1:]); err != nil {
		return nil, err
	}

	s := &Settings{}

	if rsyncArgs == "" {
		s.RsyncArgs = []string{""}
	} else {
		s.RsyncArgs = strings.Split(rsyncArgs, "|")
	}

	s.DryRun = dryRun
	s.NotifyPlan = notifyPlan
	s.NotifyTransfer = notifyTransfer
	s.ReservedAmount = ReservedSpace / 1000 / 1000
	s.ReservedUnit = "Mb"
	s.Verbosity = verbosity
	s.CheckForUpdate = checkForUpdate
	s.Version = version

	s.Port = port
	s.LogDir = logDir
	s.APIFolders = strings.Split(apiFolders, "|")
	s.Location = location
	s.confName = name

	return s, nil
}

// ToggleDryRun -
func (s *Settings) ToggleDryRun() {
	s.DryRun = !s.DryRun
}

// Save -
func (s *Settings) Save() (err error) {
	location := s.Location
	if location == "" {
		location = defaultConfLocation
	}

	confLocation := filepath.Join(location, s.confName)
	tmpFile := confLocation + ".tmp"

	if err = WriteLine(tmpFile, fmt.Sprintf("dryRun=%t", s.DryRun)); err != nil {
		return err
	}

	if err = WriteLine(tmpFile, fmt.Sprintf("notifyPlan=%d", s.NotifyPlan)); err != nil {
		return err
	}

	if err = WriteLine(tmpFile, fmt.Sprintf("notifyTransfer=%d", s.NotifyTransfer)); err != nil {
		return err
	}

	rsyncArgs := strings.Join(s.RsyncArgs, "|")
	if err = WriteLine(tmpFile, fmt.Sprintf("rsyncArgs=%s", rsyncArgs)); err != nil {
		return err
	}

	if err = WriteLine(tmpFile, fmt.Sprintf("verbosity=%d", s.Verbosity)); err != nil {
		return err
	}

	err = os.Rename(tmpFile, confLocation)
	if err != nil {
		return err
	}

	return
}
<commit_msg>Closes #112<commit_after>package lib

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/namsral/flag"
)

// ReservedSpace -
const ReservedSpace = 450000000 // 450Mb

// Config -
type Config struct {
	DryRun         bool     `json:"dryRun"`
	NotifyPlan     int      `json:"notifyPlan"`
	NotifyTransfer int      `json:"notifyTransfer"`
	ReservedAmount int64    `json:"reservedAmount"`
	ReservedUnit   string   `json:"reservedUnit"`
	RsyncArgs      []string `json:"rsyncArgs"`
	Version        string   `json:"version"`
	Verbosity      int      `json:"verbosity"`
	CheckForUpdate int      `json:"checkForUpdate"`
}

// NotifyPlan/NotifyTransfer possible values
// 0 - no notification
// 1 - simple notification
// 2 - detailed notification

// Settings -
type Settings struct {
	Config

	Port       string
	LogDir     string
	APIFolders []string

	Location string
	confName string
}

const defaultConfLocation = "/boot/config/plugins/unbalance"

// NewSettings -
func NewSettings(name, version string, locations []string) (*Settings, error) {
	var port, logDir, folders, rsyncFlags, rsyncArgs, apiFolders string
	var dryRun bool
	var notifyCalc, notifyMove, notifyPlan, notifyTransfer, verbosity, checkForUpdate int

	flagset := flag.NewFlagSet(os.Args[0], flag.ContinueOnError)

	flagset.StringVar(&port, "port", "6237", "port to run the server")
	flagset.StringVar(&logDir, "logdir", "/boot/logs", "pathname where log file will be written to")
	flagset.StringVar(&folders, "folders", "", "deprecated - do not use")
	flagset.BoolVar(&dryRun, "dryRun", true, "perform a dry-run rather than actual work")
	flagset.IntVar(&notifyCalc, "notifyCalc", 0, "deprecated - do not use") // deprecated
	flagset.IntVar(&notifyMove, "notifyMove", 0, "deprecated - do not use") // deprecated
	flagset.IntVar(&notifyPlan, "notifyPlan", 0, "notify via email after plan operation has completed (unraid notifications must be set up first): 0 - No notifications; 1 - Simple notifications; 2 - Detailed notifications")
	flagset.IntVar(&notifyTransfer, "notifyTransfer", 0, "notify via email after transfer operation has completed (unraid notifications must be set up first): 0 - No notifications; 1 - Simple notifications; 2 - Detailed notifications")
	flagset.StringVar(&rsyncFlags, "rsyncFlags", "", "deprecated - do not use") // deprecated
	flagset.StringVar(&rsyncArgs, "rsyncArgs", "", "custom rsync arguments")
	flagset.StringVar(&apiFolders, "apiFolders", "/var/local/emhttp", "folders to look for api endpoints")
	flagset.IntVar(&verbosity, "verbosity", 0, "include rsync output in log files: 0 (default) - include; 1 - do not include")
	flagset.IntVar(&checkForUpdate, "checkForUpdate", 1, "checkForUpdate: 0 - dont' check; 1 (default) - check")

	location := SearchFile(name, locations)
	if location != "" {
		flagset.String("config", filepath.Join(location, name), "config location")
	}

	if err := flagset.Parse(os.Args[1:]); err != nil {
		return nil, err
	}

	s := &Settings{}

	if rsyncArgs == "" {
		s.RsyncArgs = make([]string, 0)
	} else {
		s.RsyncArgs = strings.Split(rsyncArgs, "|")
	}

	s.DryRun = dryRun
	s.NotifyPlan = notifyPlan
	s.NotifyTransfer = notifyTransfer
	s.ReservedAmount = ReservedSpace / 1000 / 1000
	s.ReservedUnit = "Mb"
	s.Verbosity = verbosity
	s.CheckForUpdate = checkForUpdate
	s.Version = version

	s.Port = port
	s.LogDir = logDir
	s.APIFolders = strings.Split(apiFolders, "|")
	s.Location = location
	s.confName = name

	return s, nil
}

// ToggleDryRun -
func (s *Settings) ToggleDryRun() {
	s.DryRun = !s.DryRun
}

// Save -
func (s *Settings) Save() (err error) {
	location := s.Location
	if location == "" {
		location = defaultConfLocation
	}

	confLocation := filepath.Join(location, s.confName)
	tmpFile := confLocation + ".tmp"

	if err = WriteLine(tmpFile, fmt.Sprintf("dryRun=%t", s.DryRun)); err != nil {
		return err
	}

	if err = WriteLine(tmpFile, fmt.Sprintf("notifyPlan=%d", s.NotifyPlan)); err != nil {
		return err
	}

	if err = WriteLine(tmpFile, fmt.Sprintf("notifyTransfer=%d", s.NotifyTransfer)); err != nil {
		return err
	}

	rsyncArgs := strings.Join(s.RsyncArgs, "|")
	if err = WriteLine(tmpFile, fmt.Sprintf("rsyncArgs=%s", rsyncArgs)); err != nil {
		return err
	}

	if err = WriteLine(tmpFile, fmt.Sprintf("verbosity=%d", s.Verbosity)); err != nil {
		return err
	}

	err = os.Rename(tmpFile, confLocation)
	if err != nil {
		return err
	}

	return
}
<|endoftext|>


<commit_before>package providers

import (
	"bytes"
	"encoding/json"
	"fmt"
	"html"
	"html/template"
	"net/http"
	"strings"
	"time"

	"golang.org/x/net/websocket"

	"cirello.io/gochatbot/messages"
)

const (
	slackEnvVarName = "GOCHATBOT_SLACK_TOKEN"
	urlSlackAPI     = "https://slack.com/api/"
)

func init() {
	availableProviders = append(availableProviders, func(getenv func(string) string) Provider {
		token := getenv(slackEnvVarName)
		if token == "" {
			return nil
		}
		return Slack(token)
	})
}

type providerSlack struct {
	token  string
	wsURL  string
	wsConn *websocket.Conn
	selfID string

	in  chan messages.Message
	out chan messages.Message
	err error
}

// Slack is the message provider meant to be used in development of rule sets.
func Slack(token string) *providerSlack {
	slack := &providerSlack{
		token: token,
		in:    make(chan messages.Message),
		out:   make(chan messages.Message),
	}
	slack.handshake()
	slack.dial()
	if slack.err == nil {
		go slack.loop()
	}
	return slack
}

func (p *providerSlack) IncomingChannel() chan messages.Message {
	return p.in
}

func (p *providerSlack) OutgoingChannel() chan messages.Message {
	return p.out
}

func (p *providerSlack) Error() error {
	return p.err
}

func (p *providerSlack) handshake() {
	resp, err := http.Get(fmt.Sprint(urlSlackAPI, "rtm.start?no_unreads&simple_latest&token=", p.token))
	if err != nil {
		p.err = err
		return
	}
	defer resp.Body.Close()
	var data struct {
		OK   interface{} `json:"ok"`
		URL  string      `json:"url"`
		Self struct {
			ID string `json:"id"`
		} `json:"self"`
	}
	if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
		p.err = err
		return
	}

	switch v := data.OK.(type) {
	case bool:
		if !v {
			p.err = err
			return

		}
	default:
		p.err = err
		return
	}
	p.wsURL = data.URL
	p.selfID = data.Self.ID
}

func (p *providerSlack) dial() {
	ws, err := websocket.Dial(p.wsURL, "", urlSlackAPI)
	if err != nil {
		p.err = err
		return
	}
	p.wsConn = ws
}

func (p *providerSlack) loop() {
	go func() {
		for {
			var data struct {
				Type    string `json:"type"`
				Channel string `json:"channel"`
				UserID  string `json:"user"`
				Text    string `json:"text"`
			}
			if err := json.NewDecoder(p.wsConn).Decode(&data); err != nil {
				continue
			}
			if data.Type != "message" {
				continue
			}

			msg := messages.Message{
				Room:       data.Channel,
				FromUserID: data.UserID,
				Message:    data.Text,
				Direct:     strings.HasPrefix(data.Channel, "D"),
			}
			p.in <- msg
		}
	}()

	go func() {
		for msg := range p.out {
			// TODO(ccf): find a way in that text/template does not escape username DMs.
			var finalMsg bytes.Buffer
			template.Must(template.New("tmpl").Parse(msg.Message)).Execute(&finalMsg, struct{ User string }{"<@" + msg.ToUserID + ">"})

			data := struct {
				Type    string `json:"type"`
				User    string `json:"user"`
				Channel string `json:"channel"`
				Text    string `json:"text"`
			}{"message", p.selfID, msg.Room, html.UnescapeString(finalMsg.String())}

			// TODO(ccf): look for an idiomatic way of doing limited writers
			b, err := json.Marshal(data)
			if err != nil {
				continue
			}

			wsMsg := string(b)
			if len(wsMsg) > 16*1024 {
				continue
			}
			fmt.Fprint(p.wsConn, wsMsg)
			time.Sleep(1 * time.Second) // https://api.slack.com/docs/rate-limits
		}
	}()
}
<commit_msg>Simple slack reconnect - first iteration<commit_after>package providers

import (
	"bytes"
	"encoding/json"
	"fmt"
	"html"
	"html/template"
	"net/http"
	"strings"
	"time"

	"golang.org/x/net/websocket"

	"cirello.io/gochatbot/messages"
)

const (
	slackEnvVarName = "GOCHATBOT_SLACK_TOKEN"
	urlSlackAPI     = "https://slack.com/api/"
)

func init() {
	availableProviders = append(availableProviders, func(getenv func(string) string) Provider {
		token := getenv(slackEnvVarName)
		if token == "" {
			return nil
		}
		return Slack(token)
	})
}

type providerSlack struct {
	token  string
	wsURL  string
	wsConn *websocket.Conn
	selfID string

	in  chan messages.Message
	out chan messages.Message
	err error
}

// Slack is the message provider meant to be used in development of rule sets.
func Slack(token string) *providerSlack {
	slack := &providerSlack{
		token: token,
		in:    make(chan messages.Message),
		out:   make(chan messages.Message),
	}
	slack.handshake()
	slack.dial()
	if slack.err == nil {
		go slack.loop()
	}
	go slack.reconnect()
	return slack
}

func (p *providerSlack) IncomingChannel() chan messages.Message {
	return p.in
}

func (p *providerSlack) OutgoingChannel() chan messages.Message {
	return p.out
}

func (p *providerSlack) Error() error {
	return p.err
}

func (p *providerSlack) handshake() {
	resp, err := http.Get(fmt.Sprint(urlSlackAPI, "rtm.start?no_unreads&simple_latest&token=", p.token))
	if err != nil {
		p.err = err
		return
	}
	defer resp.Body.Close()
	var data struct {
		OK   interface{} `json:"ok"`
		URL  string      `json:"url"`
		Self struct {
			ID string `json:"id"`
		} `json:"self"`
	}
	if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
		p.err = err
		return
	}

	switch v := data.OK.(type) {
	case bool:
		if !v {
			p.err = err
			return

		}
	default:
		p.err = err
		return
	}
	p.wsURL = data.URL
	p.selfID = data.Self.ID
}

func (p *providerSlack) dial() {
	ws, err := websocket.Dial(p.wsURL, "", urlSlackAPI)
	if err != nil {
		p.err = err
		return
	}
	p.wsConn = ws
}

func (p *providerSlack) loop() {
	go func() {
		for {
			var data struct {
				Type    string `json:"type"`
				Channel string `json:"channel"`
				UserID  string `json:"user"`
				Text    string `json:"text"`
			}
			if err := json.NewDecoder(p.wsConn).Decode(&data); err != nil {
				continue
			}
			if data.Type != "message" {
				continue
			}

			msg := messages.Message{
				Room:       data.Channel,
				FromUserID: data.UserID,
				Message:    data.Text,
				Direct:     strings.HasPrefix(data.Channel, "D"),
			}
			p.in <- msg
		}
	}()

	go func() {
		for msg := range p.out {
			// TODO(ccf): find a way in that text/template does not escape username DMs.
			var finalMsg bytes.Buffer
			template.Must(template.New("tmpl").Parse(msg.Message)).Execute(&finalMsg, struct{ User string }{"<@" + msg.ToUserID + ">"})

			data := struct {
				Type    string `json:"type"`
				User    string `json:"user"`
				Channel string `json:"channel"`
				Text    string `json:"text"`
			}{"message", p.selfID, msg.Room, html.UnescapeString(finalMsg.String())}

			// TODO(ccf): look for an idiomatic way of doing limited writers
			b, err := json.Marshal(data)
			if err != nil {
				continue
			}

			wsMsg := string(b)
			if len(wsMsg) > 16*1024 {
				continue
			}
			fmt.Fprint(p.wsConn, wsMsg)
			time.Sleep(1 * time.Second) // https://api.slack.com/docs/rate-limits
		}
	}()
}

func (p *providerSlack) reconnect() {
	for {
		_, err := p.wsConn.Write([]byte(`{"type":"hello"}`))
		if err != nil {
			p.handshake()
			p.dial()
		}
		time.Sleep(1 * time.Second)
	}
}
<|endoftext|>


<commit_before>package publish_test

import (
	"testing"

	"github.com/jinzhu/gorm"
	"github.com/qor/qor/l10n"
	"github.com/qor/qor/publish"
)

type Book struct {
	gorm.Model
	l10n.Locale
	publish.Status
	Name       string
	CategoryID uint
	Category   Category
	Publisher  Publisher
	Comments   []Comment
	Authors    []Author `gorm:"many2many:author_books"`
}

type Publisher struct {
	gorm.Model
	l10n.Locale
	publish.Status
	Name string
}

type Comment struct {
	gorm.Model
	l10n.Locale
	publish.Status
	Content string
	BookID  uint
}

type Author struct {
	gorm.Model
	l10n.Locale
	publish.Status
	Name string
}

func generateBook(name string) *Book {
	book := Book{
		Name: name,
		Category: Category{
			Name: name + "_category",
		},
		Publisher: Publisher{
			Name: name + "_publisher",
		},
		Comments: []Comment{
			{Content: name + "_comment1"},
			{Content: name + "_comment2"},
		},
		Authors: []Author{
			{Name: name + "_author1"},
			{Name: name + "_author2"},
		},
	}
	return &book
}

func TestBelongsToForL10nResource(t *testing.T) {
	name := "belongs_to_for_l10n"
	book := generateBook(name)
	pbdraft.Save(book)

	pb.Publish(book)

	if pbprod.Where("id = ?", book.ID).First(&Book{}).RecordNotFound() {
		t.Errorf("should find book from production db")
	}

	if pbprod.Where("name LIKE ?", name+"%").First(&Publisher{}).RecordNotFound() {
		t.Errorf("should find publisher from production db")
	}

	if pbprod.Where("name LIKE ?", name+"%").First(&Category{}).RecordNotFound() {
		t.Errorf("should find category from production db")
	}
}
<commit_msg>Fix publish tests<commit_after>package publish_test

import (
	"testing"

	"github.com/jinzhu/gorm"
	"github.com/qor/qor/l10n"
	"github.com/qor/qor/publish"
)

type Book struct {
	gorm.Model
	l10n.Locale
	publish.Status
	Name        string
	CategoryID  uint
	Category    Category
	PublisherID uint
	Publisher   Publisher
	Comments    []Comment
	Authors     []Author `gorm:"many2many:author_books"`
}

type Publisher struct {
	gorm.Model
	publish.Status
	Name string
}

type Comment struct {
	gorm.Model
	l10n.Locale
	publish.Status
	Content string
	BookID  uint
}

type Author struct {
	gorm.Model
	l10n.Locale
	publish.Status
	Name string
}

func generateBook(name string) *Book {
	book := Book{
		Name: name,
		Category: Category{
			Name: name + "_category",
		},
		Publisher: Publisher{
			Name: name + "_publisher",
		},
		Comments: []Comment{
			{Content: name + "_comment1"},
			{Content: name + "_comment2"},
		},
		Authors: []Author{
			{Name: name + "_author1"},
			{Name: name + "_author2"},
		},
	}
	return &book
}

func TestBelongsToForL10nResource(t *testing.T) {
	name := "belongs_to_for_l10n"
	book := generateBook(name)
	pbdraft.Save(book)

	pb.Publish(book)

	if pbprod.Where("id = ?", book.ID).First(&Book{}).RecordNotFound() {
		t.Errorf("should find book from production db")
	}

	if pbprod.Where("name LIKE ?", name+"%").First(&Publisher{}).RecordNotFound() {
		t.Errorf("should find publisher from production db")
	}

	if pbprod.Where("name LIKE ?", name+"%").First(&Category{}).RecordNotFound() {
		t.Errorf("should find category from production db")
	}
}
<|endoftext|>


<commit_before>// +build linux

package fs

import (
	"os"
	"time"

	"github.com/hanwen/go-fuse/fuse"
	"github.com/hanwen/go-fuse/fuse/nodefs"
)

type Node interface {
	nodefs.Node
}

func NewNode() Node {
	return nodefs.NewDefaultNode()
}

func (f *FileInfo) FillAttr(out *fuse.Attr) {
	out.Mode = uint32(f.Mode & os.ModePerm)
	if f.IsDir() {
		out.Mode |= fuse.S_IFDIR
	}
	out.Size = uint64(f.Size)
	out.Atime = uint64(f.LastMod.Unix())
	out.Mtime = uint64(f.LastMod.Unix())
}

func (f *FileInfo) FillDirEntry(out *fuse.DirEntry) {
	out.Name = f.Name
	out.Mode = uint32(f.Mode & os.ModePerm)
	if f.IsDir() {
		out.Mode |= fuse.S_IFDIR
	}
}

func (root *Root) MountAndServe(mtpt string) error {
	opts := nodefs.Options{
		AttrTimeout:  time.Second,
		EntryTimeout: time.Second,
		Debug:        true,
	}
	s, _, err := nodefs.MountRoot(mtpt, root, &opts)
	if err != nil {
		return err
	}
	s.Serve()
	return nil
}

func (root *Root) GetAttr(out *fuse.Attr, file nodefs.File, ctx *fuse.Context) fuse.Status {
	root.FileInfo.FillAttr(out)
	return fuse.OK
}

func (root *Root) OpenDir(ctx *fuse.Context) ([]fuse.DirEntry, fuse.Status) {
	return readDir(root)
}

func (dir *ServiceDir) GetAttr(out *fuse.Attr, file nodefs.File, ctx *fuse.Context) fuse.Status {
	dir.FileInfo.FillAttr(out)
	return fuse.OK
}

func (dir *ServiceDir) OpenDir(ctx *fuse.Context) ([]fuse.DirEntry, fuse.Status) {
	return readDir(dir)
}

func (dir *TaskDir) GetAttr(out *fuse.Attr, file nodefs.File, ctx *fuse.Context) fuse.Status {
	dir.FileInfo.FillAttr(out)
	return fuse.OK
}

func (dir *TaskDir) OpenDir(ctx *fuse.Context) ([]fuse.DirEntry, fuse.Status) {
	return readDir(dir)
}

func (t *Text) GetAttr(out *fuse.Attr, file nodefs.File, ctx *fuse.Context) fuse.Status {
	t.FileInfo.FillAttr(out)
	return fuse.OK
}

func (t *Text) OpenDir(ctx *fuse.Context) ([]fuse.DirEntry, fuse.Status) {
	return nil, fuse.EINVAL
}

func (t *Text) Open(flags uint32, ctx *fuse.Context) (nodefs.File, fuse.Status) {
	if flags&fuse.O_ANYWRITE != 0 {
		return nil, fuse.EPERM
	}
	p, err := t.ReadFile()
	if err != nil {
		return nil, fuse.EIO
	}
	return nodefs.NewDataFile(p), fuse.OK
}

func readDir(dir Dir) ([]fuse.DirEntry, fuse.Status) {
	p := dir.Inode()
	kids, err := dir.ReadDir()
	if err != nil {
		return nil, fuse.EIO
	}
	a := make([]fuse.DirEntry, len(kids))
	for i, kid := range kids {
		info := kid.Stat()
		if p.GetChild(info.Name) == nil {
			p.NewChild(info.Name, info.IsDir(), kid)
		}
		info.FillDirEntry(&a[i])
	}
	return a, fuse.OK
}
<commit_msg>implement Lookup for initialize a node<commit_after>// +build linux

package fs

import (
	"os"
	"time"

	"github.com/hanwen/go-fuse/fuse"
	"github.com/hanwen/go-fuse/fuse/nodefs"
)

type Node interface {
	nodefs.Node
}

func NewNode() Node {
	return nodefs.NewDefaultNode()
}

func (f *FileInfo) FillAttr(out *fuse.Attr) {
	out.Mode = uint32(f.Mode & os.ModePerm)
	if f.IsDir() {
		out.Mode |= fuse.S_IFDIR
	}
	out.Size = uint64(f.Size)
	out.Atime = uint64(f.LastMod.Unix())
	out.Mtime = uint64(f.LastMod.Unix())
}

func (f *FileInfo) FillDirEntry(out *fuse.DirEntry) {
	out.Name = f.Name
	out.Mode = uint32(f.Mode & os.ModePerm)
	if f.IsDir() {
		out.Mode |= fuse.S_IFDIR
	}
}

func (root *Root) MountAndServe(mtpt string) error {
	opts := nodefs.Options{
		AttrTimeout:  time.Second,
		EntryTimeout: time.Second,
		Debug:        false,
	}
	s, _, err := nodefs.MountRoot(mtpt, root, &opts)
	if err != nil {
		return err
	}
	s.Serve()
	return nil
}

func (root *Root) Lookup(out *fuse.Attr, name string, ctx *fuse.Context) (*nodefs.Inode, fuse.Status) {
	return lookupName(root, name, out, ctx)
}

func (root *Root) GetAttr(out *fuse.Attr, file nodefs.File, ctx *fuse.Context) fuse.Status {
	root.FileInfo.FillAttr(out)
	return fuse.OK
}

func (root *Root) OpenDir(ctx *fuse.Context) ([]fuse.DirEntry, fuse.Status) {
	return readDir(root)
}

func (dir *ServiceDir) Lookup(out *fuse.Attr, name string, ctx *fuse.Context) (*nodefs.Inode, fuse.Status) {
	return lookupName(dir, name, out, ctx)
}

func (dir *ServiceDir) GetAttr(out *fuse.Attr, file nodefs.File, ctx *fuse.Context) fuse.Status {
	dir.FileInfo.FillAttr(out)
	return fuse.OK
}

func (dir *ServiceDir) OpenDir(ctx *fuse.Context) ([]fuse.DirEntry, fuse.Status) {
	return readDir(dir)
}

func (dir *TaskDir) Lookup(out *fuse.Attr, name string, ctx *fuse.Context) (*nodefs.Inode, fuse.Status) {
	return lookupName(dir, name, out, ctx)
}

func (dir *TaskDir) GetAttr(out *fuse.Attr, file nodefs.File, ctx *fuse.Context) fuse.Status {
	dir.FileInfo.FillAttr(out)
	return fuse.OK
}

func (dir *TaskDir) OpenDir(ctx *fuse.Context) ([]fuse.DirEntry, fuse.Status) {
	return readDir(dir)
}

func (t *Text) GetAttr(out *fuse.Attr, file nodefs.File, ctx *fuse.Context) fuse.Status {
	t.FileInfo.FillAttr(out)
	return fuse.OK
}

func (t *Text) OpenDir(ctx *fuse.Context) ([]fuse.DirEntry, fuse.Status) {
	return nil, fuse.EINVAL
}

func (t *Text) Open(flags uint32, ctx *fuse.Context) (nodefs.File, fuse.Status) {
	if flags&fuse.O_ANYWRITE != 0 {
		return nil, fuse.EPERM
	}
	p, err := t.ReadFile()
	if err != nil {
		return nil, fuse.EIO
	}
	return nodefs.NewDataFile(p), fuse.OK
}

func lookupName(dir Dir, name string, out *fuse.Attr, ctx *fuse.Context) (*nodefs.Inode, fuse.Status) {
	_, status := readDir(dir)
	if status != fuse.OK {
		return nil, status
	}
	c := dir.Inode().GetChild(name)
	if c == nil {
		return nil, fuse.ENOENT
	}
	status = c.Node().GetAttr(out, nil, ctx)
	if status != fuse.OK {
		return nil, status
	}
	return c, fuse.OK
}

func readDir(dir Dir) ([]fuse.DirEntry, fuse.Status) {
	p := dir.Inode()
	kids, err := dir.ReadDir()
	if err != nil {
		return nil, fuse.EIO
	}
	a := make([]fuse.DirEntry, len(kids))
	for i, kid := range kids {
		info := kid.Stat()
		if p.GetChild(info.Name) == nil {
			p.NewChild(info.Name, info.IsDir(), kid)
		}
		info.FillDirEntry(&a[i])
	}
	return a, fuse.OK
}
<|endoftext|>


<commit_before>// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// backtrack is a regular expression search with submatch
// tracking for small regular expressions and texts. It allocates
// a bit vector with (length of input) * (length of prog) bits,
// to make sure it never explores the same (character position, instruction)
// state multiple times. This limits the search to run in time linear in
// the length of the test.
//
// backtrack is a fast replacement for the NFA code on small
// regexps when onepass cannot be used.

package regexp

import "regexp/syntax"

// A job is an entry on the backtracker's job stack. It holds
// the instruction pc and the position in the input.
type job struct {
	pc  uint32
	arg int
	pos int
}

const (
	visitedBits        = 32
	maxBacktrackProg   = 500        // len(prog.Inst) <= max
	maxBacktrackVector = 256 * 1024 // bit vector size <= max (bits)
)

// bitState holds state for the backtracker.
type bitState struct {
	prog *syntax.Prog

	end     int
	cap     []int
	input   input
	jobs    []job
	visited []uint32
}

var notBacktrack *bitState = nil

// maxBitStateLen returns the maximum length of a string to search with
// the backtracker using prog.
func maxBitStateLen(prog *syntax.Prog) int {
	if !shouldBacktrack(prog) {
		return 0
	}
	return maxBacktrackVector / len(prog.Inst)
}

// newBitState returns a new bitState for the given prog,
// or notBacktrack if the size of the prog exceeds the maximum size that
// the backtracker will be run for.
func newBitState(prog *syntax.Prog) *bitState {
	if !shouldBacktrack(prog) {
		return notBacktrack
	}
	return &bitState{
		prog: prog,
	}
}

// shouldBacktrack reports whether the program is too
// long for the backtracker to run.
func shouldBacktrack(prog *syntax.Prog) bool {
	return len(prog.Inst) <= maxBacktrackProg
}

// reset resets the state of the backtracker.
// end is the end position in the input.
// ncap is the number of captures.
func (b *bitState) reset(end int, ncap int) {
	b.end = end

	if cap(b.jobs) == 0 {
		b.jobs = make([]job, 0, 256)
	} else {
		b.jobs = b.jobs[:0]
	}

	visitedSize := (len(b.prog.Inst)*(end+1) + visitedBits - 1) / visitedBits
	if cap(b.visited) < visitedSize {
		b.visited = make([]uint32, visitedSize, maxBacktrackVector/visitedBits)
	} else {
		b.visited = b.visited[:visitedSize]
		for i := range b.visited {
			b.visited[i] = 0
		}
	}

	if cap(b.cap) < ncap {
		b.cap = make([]int, ncap)
	} else {
		b.cap = b.cap[:ncap]
	}
	for i := range b.cap {
		b.cap[i] = -1
	}
}

// shouldVisit reports whether the combination of (pc, pos) has not
// been visited yet.
func (b *bitState) shouldVisit(pc uint32, pos int) bool {
	n := uint(int(pc)*(b.end+1) + pos)
	if b.visited[n/visitedBits]&(1<<(n&(visitedBits-1))) != 0 {
		return false
	}
	b.visited[n/visitedBits] |= 1 << (n & (visitedBits - 1))
	return true
}

// push pushes (pc, pos, arg) onto the job stack if it should be
// visited.
func (b *bitState) push(pc uint32, pos int, arg int) {
	if b.prog.Inst[pc].Op == syntax.InstFail {
		return
	}

	// Only check shouldVisit when arg == 0.
	// When arg > 0, we are continuing a previous visit.
	if arg == 0 && !b.shouldVisit(pc, pos) {
		return
	}

	b.jobs = append(b.jobs, job{pc: pc, arg: arg, pos: pos})
}

// tryBacktrack runs a backtracking search starting at pos.
func (m *machine) tryBacktrack(b *bitState, i input, pc uint32, pos int) bool {
	longest := m.re.longest
	m.matched = false

	b.push(pc, pos, 0)
	for len(b.jobs) > 0 {
		l := len(b.jobs) - 1
		// Pop job off the stack.
		pc := b.jobs[l].pc
		pos := b.jobs[l].pos
		arg := b.jobs[l].arg
		b.jobs = b.jobs[:l]

		// Optimization: rather than push and pop,
		// code that is going to Push and continue
		// the loop simply updates ip, p, and arg
		// and jumps to CheckAndLoop.  We have to
		// do the ShouldVisit check that Push
		// would have, but we avoid the stack
		// manipulation.
		goto Skip
	CheckAndLoop:
		if !b.shouldVisit(pc, pos) {
			continue
		}
	Skip:

		inst := b.prog.Inst[pc]

		switch inst.Op {
		default:
			panic("bad inst")
		case syntax.InstFail:
			panic("unexpected InstFail")
		case syntax.InstAlt:
			// Cannot just
			//   b.push(inst.Out, pos, 0)
			//   b.push(inst.Arg, pos, 0)
			// If during the processing of inst.Out, we encounter
			// inst.Arg via another path, we want to process it then.
			// Pushing it here will inhibit that. Instead, re-push
			// inst with arg==1 as a reminder to push inst.Arg out
			// later.
			switch arg {
			case 0:
				b.push(pc, pos, 1)
				pc = inst.Out
				goto CheckAndLoop
			case 1:
				// Finished inst.Out; try inst.Arg.
				arg = 0
				pc = inst.Arg
				goto CheckAndLoop
			}
			panic("bad arg in InstAlt")

		case syntax.InstAltMatch:
			// One opcode consumes runes; the other leads to match.
			switch b.prog.Inst[inst.Out].Op {
			case syntax.InstRune, syntax.InstRune1, syntax.InstRuneAny, syntax.InstRuneAnyNotNL:
				// inst.Arg is the match.
				b.push(inst.Arg, pos, 0)
				pc = inst.Arg
				pos = b.end
				goto CheckAndLoop
			}
			// inst.Out is the match - non-greedy
			b.push(inst.Out, b.end, 0)
			pc = inst.Out
			goto CheckAndLoop

		case syntax.InstRune:
			r, width := i.step(pos)
			if !inst.MatchRune(r) {
				continue
			}
			pos += width
			pc = inst.Out
			goto CheckAndLoop

		case syntax.InstRune1:
			r, width := i.step(pos)
			if r != inst.Rune[0] {
				continue
			}
			pos += width
			pc = inst.Out
			goto CheckAndLoop

		case syntax.InstRuneAnyNotNL:
			r, width := i.step(pos)
			if r == '\n' || r == endOfText {
				continue
			}
			pos += width
			pc = inst.Out
			goto CheckAndLoop

		case syntax.InstRuneAny:
			r, width := i.step(pos)
			if r == endOfText {
				continue
			}
			pos += width
			pc = inst.Out
			goto CheckAndLoop

		case syntax.InstCapture:
			switch arg {
			case 0:
				if 0 <= inst.Arg && inst.Arg < uint32(len(b.cap)) {
					// Capture pos to register, but save old value.
					b.push(pc, b.cap[inst.Arg], 1) // come back when we're done.
					b.cap[inst.Arg] = pos
				}
				pc = inst.Out
				goto CheckAndLoop
			case 1:
				// Finished inst.Out; restore the old value.
				b.cap[inst.Arg] = pos
				continue

			}
			panic("bad arg in InstCapture")
			continue

		case syntax.InstEmptyWidth:
			if syntax.EmptyOp(inst.Arg)&^i.context(pos) != 0 {
				continue
			}
			pc = inst.Out
			goto CheckAndLoop

		case syntax.InstNop:
			pc = inst.Out
			goto CheckAndLoop

		case syntax.InstMatch:
			// We found a match. If the caller doesn't care
			// where the match is, no point going further.
			if len(b.cap) == 0 {
				m.matched = true
				return m.matched
			}

			// Record best match so far.
			// Only need to check end point, because this entire
			// call is only considering one start position.
			if len(b.cap) > 1 {
				b.cap[1] = pos
			}
			if !m.matched || (longest && pos > 0 && pos > m.matchcap[1]) {
				copy(m.matchcap, b.cap)
			}
			m.matched = true

			// If going for first match, we're done.
			if !longest {
				return m.matched
			}

			// If we used the entire text, no longer match is possible.
			if pos == b.end {
				return m.matched
			}

			// Otherwise, continue on in hope of a longer match.
			continue
		}
		panic("unreachable")
	}

	return m.matched
}

// backtrack runs a backtracking search of prog on the input starting at pos.
func (m *machine) backtrack(i input, pos int, end int, ncap int) bool {
	if !i.canCheckPrefix() {
		panic("backtrack called for a RuneReader")
	}

	startCond := m.re.cond
	if startCond == ^syntax.EmptyOp(0) { // impossible
		return false
	}
	if startCond&syntax.EmptyBeginText != 0 && pos != 0 {
		// Anchored match, past beginning of text.
		return false
	}

	b := m.b
	b.reset(end, ncap)

	m.matchcap = m.matchcap[:ncap]
	for i := range m.matchcap {
		m.matchcap[i] = -1
	}

	// Anchored search must start at the beginning of the input
	if startCond&syntax.EmptyBeginText != 0 {
		if len(b.cap) > 0 {
			b.cap[0] = pos
		}
		return m.tryBacktrack(b, i, uint32(m.p.Start), pos)
	}

	// Unanchored search, starting from each possible text position.
	// Notice that we have to try the empty string at the end of
	// the text, so the loop condition is pos <= end, not pos < end.
	// This looks like it's quadratic in the size of the text,
	// but we are not clearing visited between calls to TrySearch,
	// so no work is duplicated and it ends up still being linear.
	width := -1
	for ; pos <= end && width != 0; pos += width {
		if len(m.re.prefix) > 0 {
			// Match requires literal prefix; fast search for it.
			advance := i.index(m.re, pos)
			if advance < 0 {
				return false
			}
			pos += advance
		}

		if len(b.cap) > 0 {
			b.cap[0] = pos
		}
		if m.tryBacktrack(b, i, uint32(m.p.Start), pos) {
			// Match must be leftmost; done.
			return true
		}
		_, width = i.step(pos)
	}
	return false
}
<commit_msg>regexp: remove unreachable code<commit_after>// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// backtrack is a regular expression search with submatch
// tracking for small regular expressions and texts. It allocates
// a bit vector with (length of input) * (length of prog) bits,
// to make sure it never explores the same (character position, instruction)
// state multiple times. This limits the search to run in time linear in
// the length of the test.
//
// backtrack is a fast replacement for the NFA code on small
// regexps when onepass cannot be used.

package regexp

import "regexp/syntax"

// A job is an entry on the backtracker's job stack. It holds
// the instruction pc and the position in the input.
type job struct {
	pc  uint32
	arg int
	pos int
}

const (
	visitedBits        = 32
	maxBacktrackProg   = 500        // len(prog.Inst) <= max
	maxBacktrackVector = 256 * 1024 // bit vector size <= max (bits)
)

// bitState holds state for the backtracker.
type bitState struct {
	prog *syntax.Prog

	end     int
	cap     []int
	input   input
	jobs    []job
	visited []uint32
}

var notBacktrack *bitState = nil

// maxBitStateLen returns the maximum length of a string to search with
// the backtracker using prog.
func maxBitStateLen(prog *syntax.Prog) int {
	if !shouldBacktrack(prog) {
		return 0
	}
	return maxBacktrackVector / len(prog.Inst)
}

// newBitState returns a new bitState for the given prog,
// or notBacktrack if the size of the prog exceeds the maximum size that
// the backtracker will be run for.
func newBitState(prog *syntax.Prog) *bitState {
	if !shouldBacktrack(prog) {
		return notBacktrack
	}
	return &bitState{
		prog: prog,
	}
}

// shouldBacktrack reports whether the program is too
// long for the backtracker to run.
func shouldBacktrack(prog *syntax.Prog) bool {
	return len(prog.Inst) <= maxBacktrackProg
}

// reset resets the state of the backtracker.
// end is the end position in the input.
// ncap is the number of captures.
func (b *bitState) reset(end int, ncap int) {
	b.end = end

	if cap(b.jobs) == 0 {
		b.jobs = make([]job, 0, 256)
	} else {
		b.jobs = b.jobs[:0]
	}

	visitedSize := (len(b.prog.Inst)*(end+1) + visitedBits - 1) / visitedBits
	if cap(b.visited) < visitedSize {
		b.visited = make([]uint32, visitedSize, maxBacktrackVector/visitedBits)
	} else {
		b.visited = b.visited[:visitedSize]
		for i := range b.visited {
			b.visited[i] = 0
		}
	}

	if cap(b.cap) < ncap {
		b.cap = make([]int, ncap)
	} else {
		b.cap = b.cap[:ncap]
	}
	for i := range b.cap {
		b.cap[i] = -1
	}
}

// shouldVisit reports whether the combination of (pc, pos) has not
// been visited yet.
func (b *bitState) shouldVisit(pc uint32, pos int) bool {
	n := uint(int(pc)*(b.end+1) + pos)
	if b.visited[n/visitedBits]&(1<<(n&(visitedBits-1))) != 0 {
		return false
	}
	b.visited[n/visitedBits] |= 1 << (n & (visitedBits - 1))
	return true
}

// push pushes (pc, pos, arg) onto the job stack if it should be
// visited.
func (b *bitState) push(pc uint32, pos int, arg int) {
	if b.prog.Inst[pc].Op == syntax.InstFail {
		return
	}

	// Only check shouldVisit when arg == 0.
	// When arg > 0, we are continuing a previous visit.
	if arg == 0 && !b.shouldVisit(pc, pos) {
		return
	}

	b.jobs = append(b.jobs, job{pc: pc, arg: arg, pos: pos})
}

// tryBacktrack runs a backtracking search starting at pos.
func (m *machine) tryBacktrack(b *bitState, i input, pc uint32, pos int) bool {
	longest := m.re.longest
	m.matched = false

	b.push(pc, pos, 0)
	for len(b.jobs) > 0 {
		l := len(b.jobs) - 1
		// Pop job off the stack.
		pc := b.jobs[l].pc
		pos := b.jobs[l].pos
		arg := b.jobs[l].arg
		b.jobs = b.jobs[:l]

		// Optimization: rather than push and pop,
		// code that is going to Push and continue
		// the loop simply updates ip, p, and arg
		// and jumps to CheckAndLoop.  We have to
		// do the ShouldVisit check that Push
		// would have, but we avoid the stack
		// manipulation.
		goto Skip
	CheckAndLoop:
		if !b.shouldVisit(pc, pos) {
			continue
		}
	Skip:

		inst := b.prog.Inst[pc]

		switch inst.Op {
		default:
			panic("bad inst")
		case syntax.InstFail:
			panic("unexpected InstFail")
		case syntax.InstAlt:
			// Cannot just
			//   b.push(inst.Out, pos, 0)
			//   b.push(inst.Arg, pos, 0)
			// If during the processing of inst.Out, we encounter
			// inst.Arg via another path, we want to process it then.
			// Pushing it here will inhibit that. Instead, re-push
			// inst with arg==1 as a reminder to push inst.Arg out
			// later.
			switch arg {
			case 0:
				b.push(pc, pos, 1)
				pc = inst.Out
				goto CheckAndLoop
			case 1:
				// Finished inst.Out; try inst.Arg.
				arg = 0
				pc = inst.Arg
				goto CheckAndLoop
			}
			panic("bad arg in InstAlt")

		case syntax.InstAltMatch:
			// One opcode consumes runes; the other leads to match.
			switch b.prog.Inst[inst.Out].Op {
			case syntax.InstRune, syntax.InstRune1, syntax.InstRuneAny, syntax.InstRuneAnyNotNL:
				// inst.Arg is the match.
				b.push(inst.Arg, pos, 0)
				pc = inst.Arg
				pos = b.end
				goto CheckAndLoop
			}
			// inst.Out is the match - non-greedy
			b.push(inst.Out, b.end, 0)
			pc = inst.Out
			goto CheckAndLoop

		case syntax.InstRune:
			r, width := i.step(pos)
			if !inst.MatchRune(r) {
				continue
			}
			pos += width
			pc = inst.Out
			goto CheckAndLoop

		case syntax.InstRune1:
			r, width := i.step(pos)
			if r != inst.Rune[0] {
				continue
			}
			pos += width
			pc = inst.Out
			goto CheckAndLoop

		case syntax.InstRuneAnyNotNL:
			r, width := i.step(pos)
			if r == '\n' || r == endOfText {
				continue
			}
			pos += width
			pc = inst.Out
			goto CheckAndLoop

		case syntax.InstRuneAny:
			r, width := i.step(pos)
			if r == endOfText {
				continue
			}
			pos += width
			pc = inst.Out
			goto CheckAndLoop

		case syntax.InstCapture:
			switch arg {
			case 0:
				if 0 <= inst.Arg && inst.Arg < uint32(len(b.cap)) {
					// Capture pos to register, but save old value.
					b.push(pc, b.cap[inst.Arg], 1) // come back when we're done.
					b.cap[inst.Arg] = pos
				}
				pc = inst.Out
				goto CheckAndLoop
			case 1:
				// Finished inst.Out; restore the old value.
				b.cap[inst.Arg] = pos
				continue

			}
			panic("bad arg in InstCapture")

		case syntax.InstEmptyWidth:
			if syntax.EmptyOp(inst.Arg)&^i.context(pos) != 0 {
				continue
			}
			pc = inst.Out
			goto CheckAndLoop

		case syntax.InstNop:
			pc = inst.Out
			goto CheckAndLoop

		case syntax.InstMatch:
			// We found a match. If the caller doesn't care
			// where the match is, no point going further.
			if len(b.cap) == 0 {
				m.matched = true
				return m.matched
			}

			// Record best match so far.
			// Only need to check end point, because this entire
			// call is only considering one start position.
			if len(b.cap) > 1 {
				b.cap[1] = pos
			}
			if !m.matched || (longest && pos > 0 && pos > m.matchcap[1]) {
				copy(m.matchcap, b.cap)
			}
			m.matched = true

			// If going for first match, we're done.
			if !longest {
				return m.matched
			}

			// If we used the entire text, no longer match is possible.
			if pos == b.end {
				return m.matched
			}

			// Otherwise, continue on in hope of a longer match.
			continue
		}
	}

	return m.matched
}

// backtrack runs a backtracking search of prog on the input starting at pos.
func (m *machine) backtrack(i input, pos int, end int, ncap int) bool {
	if !i.canCheckPrefix() {
		panic("backtrack called for a RuneReader")
	}

	startCond := m.re.cond
	if startCond == ^syntax.EmptyOp(0) { // impossible
		return false
	}
	if startCond&syntax.EmptyBeginText != 0 && pos != 0 {
		// Anchored match, past beginning of text.
		return false
	}

	b := m.b
	b.reset(end, ncap)

	m.matchcap = m.matchcap[:ncap]
	for i := range m.matchcap {
		m.matchcap[i] = -1
	}

	// Anchored search must start at the beginning of the input
	if startCond&syntax.EmptyBeginText != 0 {
		if len(b.cap) > 0 {
			b.cap[0] = pos
		}
		return m.tryBacktrack(b, i, uint32(m.p.Start), pos)
	}

	// Unanchored search, starting from each possible text position.
	// Notice that we have to try the empty string at the end of
	// the text, so the loop condition is pos <= end, not pos < end.
	// This looks like it's quadratic in the size of the text,
	// but we are not clearing visited between calls to TrySearch,
	// so no work is duplicated and it ends up still being linear.
	width := -1
	for ; pos <= end && width != 0; pos += width {
		if len(m.re.prefix) > 0 {
			// Match requires literal prefix; fast search for it.
			advance := i.index(m.re, pos)
			if advance < 0 {
				return false
			}
			pos += advance
		}

		if len(b.cap) > 0 {
			b.cap[0] = pos
		}
		if m.tryBacktrack(b, i, uint32(m.p.Start), pos) {
			// Match must be leftmost; done.
			return true
		}
		_, width = i.step(pos)
	}
	return false
}
<|endoftext|>


<commit_before>package stats

import (
	"github.com/zpz/matrix.go/dense"
	"math"
	"math/rand"
)

// Normal is a struct for a normal distribution.
type Normal struct {
	mean float64
	sd   float64
}

// NewNormal creates a Normal object and returns a pointer to it.
func NewNormal(mean, sd float64) *Normal {
	assert(sd > 0, "sd must be positive")
	return &Normal{mean: mean, sd: sd}
}

// Density computes the probability density of the given
// values in the normal distribution norm.
// out either has the correct length or is nil,
// in which case a slice is allocated and used.
func (norm *Normal) Density(
	x []float64,
	out []float64) []float64 {

	coef := 1.0 / (Sqrt2Pi * norm.sd)

	out = use_slice(out, len(x))

	for i, v := range x {
		z := (v - norm.mean) / norm.sd
		out[i] = coef * math.Exp(-0.5*z*z)
	}

	return out
}

// Random generates n random numbers from the normal distribution norm.
func (norm *Normal) Random(
	n int,
	_ RandomNumberGenerator,
	out []float64) []float64 {

	out = use_slice(out, n)
	for i := range out {
		out[i] = rand.NormFloat64()*norm.sd + norm.mean
	}
	return out
}

// Mvnormal is a data structure for multivariate normal distribution.
type Mvnormal struct {
	mean        []float64
	cov         *dense.Dense
	cov_det     float64
	log_cov_det float64
}

// NewMvnormal creates a new Mvnormal object and returns a pointer to
// it. Note that the input mean slice and cov matrix are not deeply
// copied. They are simply pointed to by the created Mvnormal object.
func NewMvnormal(mean []float64, cov *dense.Dense) *Mvnormal {
	r, c := cov.Dims()
	assert(r == c && c == len(mean),
		"Dimensionalities of 'mean' and 'cov' mismatch")
	cov_det := cov.Det()
	return &Mvnormal{
		mean:        mean,
		cov:         cov,
		cov_det:     cov_det,
		log_cov_det: math.Log(cov_det)}
}

// Dim returns the dimensionality of the Mvnormal distribution mvn.
func (mvn *Mvnormal) Dim() int {
	return len(mvn.mean)
}

// Density computes the prob density values for each row of x (as a
// case, or observation) in the Mvnormal distribution mvn.
// out either has the correct length (i.e. the number of rows in x)
// or is nil, in which case a slice is allocated and used.
func (mvn *Mvnormal) Density(
	x *dense.Dense,
	// Each row is a case.
	out []float64) []float64 {

	n, p := x.Dims()
	assert(len(mvn.mean) == p,
		"Dimensionalities of input 'x' and distribution mismatch")

	out = use_slice(out, n)

	// Mahalanobis distance
	Mahalanobis(x, mvn.mean, mvn.cov, out)

	coef := 1.0 / math.Sqrt(
		math.Pow(2*math.Pi, float64(p))*mvn.cov_det)

	for i, v := range out {
		out[i] = coef * math.Exp(-0.5*v)
	}

	return out
}

// Random generates random samples from the multivariate normal
// distribution mvn.
// The result is a matrix with each row being a case.
func (mvn *Mvnormal) Random(
	n int,
	_ RandomNumberGenerator,
	out *dense.Dense) *dense.Dense {

	p := len(mvn.mean)

	chol, ok := dense.Chol(mvn.cov)
	assert(ok, "Cholesky failed")

	z := dense.DenseView(NewNormal(0., 1.).Random(p*n, &RNG{}, nil), n, p)

	U := dense.NewDense(p, p)
	dense.CopyLower(U, chol.LU)
	dense.CopyDiag(U, chol.LU)
	// TODO: can we avoid this copying?

	out = dense.Mult(z, U, out)

	for row := 0; row < n; row++ {
		Add(out.RowView(row), mvn.mean, out.RowView(row))
	}

	// Alternative algorithm: see function 'mvrnom' in the R package
	// MASS.

	return out
}
<commit_msg>fix following changes to dense.Chol<commit_after>package stats

import (
	"github.com/zpz/matrix.go/dense"
	"math"
	"math/rand"
)

// Normal is a struct for a normal distribution.
type Normal struct {
	mean float64
	sd   float64
}

// NewNormal creates a Normal object and returns a pointer to it.
func NewNormal(mean, sd float64) *Normal {
	assert(sd > 0, "sd must be positive")
	return &Normal{mean: mean, sd: sd}
}

// Density computes the probability density of the given
// values in the normal distribution norm.
// out either has the correct length or is nil,
// in which case a slice is allocated and used.
func (norm *Normal) Density(
	x []float64,
	out []float64) []float64 {

	coef := 1.0 / (Sqrt2Pi * norm.sd)

	out = use_slice(out, len(x))

	for i, v := range x {
		z := (v - norm.mean) / norm.sd
		out[i] = coef * math.Exp(-0.5*z*z)
	}

	return out
}

// Random generates n random numbers from the normal distribution norm.
func (norm *Normal) Random(
	n int,
	_ RandomNumberGenerator,
	out []float64) []float64 {

	out = use_slice(out, n)
	for i := range out {
		out[i] = rand.NormFloat64()*norm.sd + norm.mean
	}
	return out
}

// Mvnormal is a data structure for multivariate normal distribution.
type Mvnormal struct {
	mean        []float64
	cov         *dense.Dense
	cov_det     float64
	log_cov_det float64
}

// NewMvnormal creates a new Mvnormal object and returns a pointer to
// it. Note that the input mean slice and cov matrix are not deeply
// copied. They are simply pointed to by the created Mvnormal object.
func NewMvnormal(mean []float64, cov *dense.Dense) *Mvnormal {
	r, c := cov.Dims()
	assert(r == c && c == len(mean),
		"Dimensionalities of 'mean' and 'cov' mismatch")
	cov_det := cov.Det()
	return &Mvnormal{
		mean:        mean,
		cov:         cov,
		cov_det:     cov_det,
		log_cov_det: math.Log(cov_det)}
}

// Dim returns the dimensionality of the Mvnormal distribution mvn.
func (mvn *Mvnormal) Dim() int {
	return len(mvn.mean)
}

// Density computes the prob density values for each row of x (as a
// case, or observation) in the Mvnormal distribution mvn.
// out either has the correct length (i.e. the number of rows in x)
// or is nil, in which case a slice is allocated and used.
func (mvn *Mvnormal) Density(
	x *dense.Dense,
	// Each row is a case.
	out []float64) []float64 {

	n, p := x.Dims()
	assert(len(mvn.mean) == p,
		"Dimensionalities of input 'x' and distribution mismatch")

	out = use_slice(out, n)

	// Mahalanobis distance
	Mahalanobis(x, mvn.mean, mvn.cov, out)

	coef := 1.0 / math.Sqrt(
		math.Pow(2*math.Pi, float64(p))*mvn.cov_det)

	for i, v := range out {
		out[i] = coef * math.Exp(-0.5*v)
	}

	return out
}

// Random generates random samples from the multivariate normal
// distribution mvn.
// The result is a matrix with each row being a case.
func (mvn *Mvnormal) Random(
	n int,
	_ RandomNumberGenerator,
	out *dense.Dense) *dense.Dense {

	p := len(mvn.mean)

	chol, ok := dense.Chol(mvn.cov)
	assert(ok, "Cholesky failed")

	z := dense.DenseView(NewNormal(0., 1.).Random(p*n, &RNG{}, nil), n, p)

	out = dense.Mult(z, dense.T(chol.L(), nil), out)

	for row := 0; row < n; row++ {
		Add(out.RowView(row), mvn.mean, out.RowView(row))
	}

	// Alternative algorithm: see function 'mvrnom' in the R package
	// MASS.

	return out
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"testing"
	"time"

	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
	"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

func TestAccAWSSpotDatafeedSubscription_serial(t *testing.T) {
	cases := map[string]func(t *testing.T){
		"basic":      testAccAWSSpotDatafeedSubscription_basic,
		"disappears": testAccAWSSpotDatafeedSubscription_disappears,
		"import":     testAccAWSSpotDatafeedSubscription_importBasic,
	}

	for name, tc := range cases {
		t.Run(name, func(t *testing.T) {
			tc(t)
		})
	}
}

func testAccAWSSpotDatafeedSubscription_importBasic(t *testing.T) {
	resourceName := "aws_spot_datafeed_subscription.default"
	ri := acctest.RandInt()

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSSpotDatafeedSubscriptionDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSSpotDatafeedSubscription(ri),
			},

			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func testAccAWSSpotDatafeedSubscription_basic(t *testing.T) {
	var subscription ec2.SpotDatafeedSubscription
	ri := acctest.RandInt()

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSSpotDatafeedSubscriptionDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSSpotDatafeedSubscription(ri),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSpotDatafeedSubscriptionExists("aws_spot_datafeed_subscription.default", &subscription),
				),
			},
		},
	})
}

func testAccCheckAWSSpotDatafeedSubscriptionDisappears(subscription *ec2.SpotDatafeedSubscription) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		conn := testAccProvider.Meta().(*AWSClient).ec2conn

		_, err := conn.DeleteSpotDatafeedSubscription(&ec2.DeleteSpotDatafeedSubscriptionInput{})
		if err != nil {
			return err
		}

		return resource.Retry(40*time.Minute, func() *resource.RetryError {
			_, err := conn.DescribeSpotDatafeedSubscription(&ec2.DescribeSpotDatafeedSubscriptionInput{})
			if err != nil {
				cgw, ok := err.(awserr.Error)
				if ok && cgw.Code() == "InvalidSpotDatafeed.NotFound" {
					return nil
				}
				return resource.NonRetryableError(
					fmt.Errorf("Error retrieving Spot Datafeed Subscription: %s", err))
			}
			return resource.RetryableError(fmt.Errorf("Waiting for Spot Datafeed Subscription"))
		})
	}
}

func testAccAWSSpotDatafeedSubscription_disappears(t *testing.T) {
	var subscription ec2.SpotDatafeedSubscription
	ri := acctest.RandInt()

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSSpotDatafeedSubscriptionDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSSpotDatafeedSubscription(ri),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSpotDatafeedSubscriptionExists("aws_spot_datafeed_subscription.default", &subscription),
					testAccCheckAWSSpotDatafeedSubscriptionDisappears(&subscription),
				),
				ExpectNonEmptyPlan: true,
			},
		},
	})
}

func testAccCheckAWSSpotDatafeedSubscriptionExists(n string, subscription *ec2.SpotDatafeedSubscription) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No policy ID is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).ec2conn

		resp, err := conn.DescribeSpotDatafeedSubscription(&ec2.DescribeSpotDatafeedSubscriptionInput{})
		if err != nil {
			return err
		}

		*subscription = *resp.SpotDatafeedSubscription

		return nil
	}
}

func testAccCheckAWSSpotDatafeedSubscriptionDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).ec2conn

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_spot_datafeed_subscription" {
			continue
		}

		// Try to get subscription
		_, err := conn.DescribeSpotDatafeedSubscription(&ec2.DescribeSpotDatafeedSubscriptionInput{})
		if err == nil {
			return fmt.Errorf("still exist.")
		}

		awsErr, ok := err.(awserr.Error)
		if !ok {
			return err
		}
		if awsErr.Code() != "InvalidSpotDatafeed.NotFound" {
			return err
		}
	}

	return nil
}

func testAccAWSSpotDatafeedSubscription(randInt int) string {
	return fmt.Sprintf(`
resource "aws_s3_bucket" "default" {
  bucket = "tf-spot-datafeed-%d"
}

resource "aws_spot_datafeed_subscription" "default" {
  bucket = aws_s3_bucket.default.bucket
}
`, randInt)
}
<commit_msg>tests/resource/aws_spot_datafeed_subscription: Add missing S3 grants to configuration and minor refactoring (#15954)<commit_after>package aws

import (
	"fmt"
	"testing"
	"time"

	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/hashicorp/aws-sdk-go-base/tfawserr"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
	"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

func TestAccAWSSpotDatafeedSubscription_serial(t *testing.T) {
	cases := map[string]func(t *testing.T){
		"basic":      testAccAWSSpotDatafeedSubscription_basic,
		"disappears": testAccAWSSpotDatafeedSubscription_disappears,
	}

	for name, tc := range cases {
		t.Run(name, func(t *testing.T) {
			tc(t)
		})
	}
}

func testAccAWSSpotDatafeedSubscription_basic(t *testing.T) {
	var subscription ec2.SpotDatafeedSubscription
	resourceName := "aws_spot_datafeed_subscription.test"
	rName := acctest.RandomWithPrefix("tf-acc-test")

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t); testAccPreCheckAWSSpotDatafeedSubscription(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSSpotDatafeedSubscriptionDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSSpotDatafeedSubscription(rName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSpotDatafeedSubscriptionExists(resourceName, &subscription),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func testAccCheckAWSSpotDatafeedSubscriptionDisappears(subscription *ec2.SpotDatafeedSubscription) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		conn := testAccProvider.Meta().(*AWSClient).ec2conn

		_, err := conn.DeleteSpotDatafeedSubscription(&ec2.DeleteSpotDatafeedSubscriptionInput{})
		if err != nil {
			return err
		}

		return resource.Retry(40*time.Minute, func() *resource.RetryError {
			_, err := conn.DescribeSpotDatafeedSubscription(&ec2.DescribeSpotDatafeedSubscriptionInput{})
			if err != nil {
				cgw, ok := err.(awserr.Error)
				if ok && cgw.Code() == "InvalidSpotDatafeed.NotFound" {
					return nil
				}
				return resource.NonRetryableError(
					fmt.Errorf("Error retrieving Spot Datafeed Subscription: %s", err))
			}
			return resource.RetryableError(fmt.Errorf("Waiting for Spot Datafeed Subscription"))
		})
	}
}

func testAccAWSSpotDatafeedSubscription_disappears(t *testing.T) {
	var subscription ec2.SpotDatafeedSubscription
	resourceName := "aws_spot_datafeed_subscription.test"
	rName := acctest.RandomWithPrefix("tf-acc-test")

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t); testAccPreCheckAWSSpotDatafeedSubscription(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSSpotDatafeedSubscriptionDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSSpotDatafeedSubscription(rName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSpotDatafeedSubscriptionExists(resourceName, &subscription),
					testAccCheckAWSSpotDatafeedSubscriptionDisappears(&subscription),
				),
				ExpectNonEmptyPlan: true,
			},
		},
	})
}

func testAccCheckAWSSpotDatafeedSubscriptionExists(n string, subscription *ec2.SpotDatafeedSubscription) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No policy ID is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).ec2conn

		resp, err := conn.DescribeSpotDatafeedSubscription(&ec2.DescribeSpotDatafeedSubscriptionInput{})
		if err != nil {
			return err
		}

		*subscription = *resp.SpotDatafeedSubscription

		return nil
	}
}

func testAccCheckAWSSpotDatafeedSubscriptionDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).ec2conn

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_spot_datafeed_subscription" {
			continue
		}

		_, err := conn.DescribeSpotDatafeedSubscription(&ec2.DescribeSpotDatafeedSubscriptionInput{})

		if tfawserr.ErrCodeEquals(err, "InvalidSpotDatafeed.NotFound") {
			continue
		}

		if err != nil {
			return fmt.Errorf("error descripting EC2 Spot Datafeed Subscription: %w", err)
		}
	}

	return nil
}

func testAccPreCheckAWSSpotDatafeedSubscription(t *testing.T) {
	conn := testAccProvider.Meta().(*AWSClient).ec2conn

	input := &ec2.DescribeSpotDatafeedSubscriptionInput{}

	_, err := conn.DescribeSpotDatafeedSubscription(input)

	if testAccPreCheckSkipError(err) {
		t.Skipf("skipping acceptance testing: %s", err)
	}

	if tfawserr.ErrCodeEquals(err, "InvalidSpotDatafeed.NotFound") {
		return
	}

	if err != nil {
		t.Fatalf("unexpected PreCheck error: %s", err)
	}
}

func testAccAWSSpotDatafeedSubscription(rName string) string {
	return fmt.Sprintf(`
data "aws_canonical_user_id" "current" {}

resource "aws_s3_bucket" "test" {
  bucket = %[1]q

  grant {
    id          = data.aws_canonical_user_id.current.id
    permissions = ["FULL_CONTROL"]
    type        = "CanonicalUser"
  }

  grant {
    id          = "c4c1ede66af53448b93c283ce9448c4ba468c9432aa01d700d3878632f77d2d0" # EC2 Account
    permissions = ["FULL_CONTROL"]
    type        = "CanonicalUser"
  }
}

resource "aws_spot_datafeed_subscription" "test" {
  bucket = aws_s3_bucket.test.bucket
}
`, rName)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"math/rand"
	"sync/atomic"
	"time"

	"github.com/vbauerster/mpb/v7"
	"github.com/vbauerster/mpb/v7/decor"
)

var curTask uint32
var doneTasks uint32

type task struct {
	id    uint32
	total int64
	bar   *mpb.Bar
}

func main() {
	numTasks := 4

	var total int64
	var filler mpb.BarFiller
	tasks := make([]*task, numTasks)

	for i := 0; i < numTasks; i++ {
		task := &task{
			id:    uint32(i),
			total: rand.Int63n(666) + 100,
		}
		total += task.total
		filler = middleware(filler, task.id)
		tasks[i] = task
	}

	filler = newLineMiddleware(filler)

	p := mpb.New()

	for i := 0; i < numTasks; i++ {
		var waitBar *mpb.Bar
		if i != 0 {
			waitBar = tasks[i-1].bar
		}
		bar := p.AddBar(tasks[i].total,
			mpb.BarExtenderRev(filler),
			mpb.BarQueueAfter(waitBar, false),
			mpb.PrependDecorators(
				decor.Name("current:", decor.WCSyncWidthR),
			),
			mpb.AppendDecorators(
				decor.Percentage(decor.WCSyncWidth),
			),
		)
		tasks[i].bar = bar
	}

	tb := p.AddBar(0,
		mpb.PrependDecorators(
			decor.Any(func(st decor.Statistics) string {
				return fmt.Sprintf("TOTAL(%d/%d)", atomic.LoadUint32(&doneTasks), len(tasks))
			}, decor.WCSyncWidthR),
		),
		mpb.AppendDecorators(
			decor.Percentage(decor.WCSyncWidth),
		),
	)

	tb.SetTotal(int64(total), false)

	for _, t := range tasks {
		atomic.StoreUint32(&curTask, uint32(t.id))
		complete(tb, t)
		atomic.AddUint32(&doneTasks, 1)
	}

	tb.EnableTriggerComplete()

	p.Wait()
}

func middleware(base mpb.BarFiller, id uint32) mpb.BarFiller {
	var done bool
	fn := func(w io.Writer, _ int, st decor.Statistics) {
		if !done {
			cur := atomic.LoadUint32(&curTask) == id
			if !cur {
				fmt.Fprintf(w, "   Taksk %02d\n", id)
				return
			}
			if !st.Completed {
				fmt.Fprintf(w, "=> Taksk %02d\n", id)
				return
			}
			done = cur
		}
		fmt.Fprintf(w, "   Taksk %02d: Done!\n", id)
	}
	if base == nil {
		return mpb.BarFillerFunc(fn)
	}
	return mpb.BarFillerFunc(func(w io.Writer, reqWidth int, st decor.Statistics) {
		fn(w, reqWidth, st)
		base.Fill(w, reqWidth, st)
	})
}

func newLineMiddleware(base mpb.BarFiller) mpb.BarFiller {
	return mpb.BarFillerFunc(func(w io.Writer, reqWidth int, st decor.Statistics) {
		fmt.Fprintln(w)
		base.Fill(w, reqWidth, st)
	})
}

func complete(tb *mpb.Bar, t *task) {
	bar := t.bar
	max := 100 * time.Millisecond
	for !bar.Completed() {
		n := rand.Int63n(10) + 1
		bar.IncrInt64(n)
		tb.IncrInt64(n)
		time.Sleep(time.Duration(n) * max / 10)
	}
	bar.Wait()
}
<commit_msg>fixup! refactoring: specific types<commit_after>package main

import (
	"fmt"
	"io"
	"math/rand"
	"sync/atomic"
	"time"

	"github.com/vbauerster/mpb/v7"
	"github.com/vbauerster/mpb/v7/decor"
)

var curTask uint32
var doneTasks uint32

type task struct {
	id    uint32
	total int64
	bar   *mpb.Bar
}

func main() {
	numTasks := 4

	var total int64
	var filler mpb.BarFiller
	tasks := make([]*task, numTasks)

	for i := 0; i < numTasks; i++ {
		task := &task{
			id:    uint32(i),
			total: rand.Int63n(666) + 100,
		}
		total += task.total
		filler = middleware(filler, task.id)
		tasks[i] = task
	}

	filler = newLineMiddleware(filler)

	p := mpb.New()

	for i := 0; i < numTasks; i++ {
		var waitBar *mpb.Bar
		if i != 0 {
			waitBar = tasks[i-1].bar
		}
		bar := p.AddBar(tasks[i].total,
			mpb.BarExtenderRev(filler),
			mpb.BarQueueAfter(waitBar, false),
			mpb.PrependDecorators(
				decor.Name("current:", decor.WCSyncWidthR),
			),
			mpb.AppendDecorators(
				decor.Percentage(decor.WCSyncWidth),
			),
		)
		tasks[i].bar = bar
	}

	tb := p.AddBar(0,
		mpb.PrependDecorators(
			decor.Any(func(st decor.Statistics) string {
				return fmt.Sprintf("TOTAL(%d/%d)", atomic.LoadUint32(&doneTasks), len(tasks))
			}, decor.WCSyncWidthR),
		),
		mpb.AppendDecorators(
			decor.Percentage(decor.WCSyncWidth),
		),
	)

	tb.SetTotal(total, false)

	for _, t := range tasks {
		atomic.StoreUint32(&curTask, t.id)
		complete(tb, t)
		atomic.AddUint32(&doneTasks, 1)
	}

	tb.EnableTriggerComplete()

	p.Wait()
}

func middleware(base mpb.BarFiller, id uint32) mpb.BarFiller {
	var done bool
	fn := func(w io.Writer, _ int, st decor.Statistics) {
		if !done {
			cur := atomic.LoadUint32(&curTask) == id
			if !cur {
				fmt.Fprintf(w, "   Taksk %02d\n", id)
				return
			}
			if !st.Completed {
				fmt.Fprintf(w, "=> Taksk %02d\n", id)
				return
			}
			done = cur
		}
		fmt.Fprintf(w, "   Taksk %02d: Done!\n", id)
	}
	if base == nil {
		return mpb.BarFillerFunc(fn)
	}
	return mpb.BarFillerFunc(func(w io.Writer, reqWidth int, st decor.Statistics) {
		fn(w, reqWidth, st)
		base.Fill(w, reqWidth, st)
	})
}

func newLineMiddleware(base mpb.BarFiller) mpb.BarFiller {
	return mpb.BarFillerFunc(func(w io.Writer, reqWidth int, st decor.Statistics) {
		fmt.Fprintln(w)
		base.Fill(w, reqWidth, st)
	})
}

func complete(tb *mpb.Bar, t *task) {
	bar := t.bar
	max := 100 * time.Millisecond
	for !bar.Completed() {
		n := rand.Int63n(10) + 1
		bar.IncrInt64(n)
		tb.IncrInt64(n)
		time.Sleep(time.Duration(n) * max / 10)
	}
	bar.Wait()
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"log"
	"strings"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/iam"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsIamPolicyAttachment() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsIamPolicyAttachmentCreate,
		Read:   resourceAwsIamPolicyAttachmentRead,
		Update: resourceAwsIamPolicyAttachmentUpdate,
		Delete: resourceAwsIamPolicyAttachmentDelete,

		Schema: map[string]*schema.Schema{
			"name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"users": &schema.Schema{
				Type:     schema.TypeSet,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Set:      schema.HashString,
			},
			"roles": &schema.Schema{
				Type:     schema.TypeSet,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Set:      schema.HashString,
			},
			"groups": &schema.Schema{
				Type:     schema.TypeSet,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Set:      schema.HashString,
			},
			"policy_arn": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
		},
	}
}

func resourceAwsIamPolicyAttachmentCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).iamconn

	name := d.Get("name").(string)
	arn := d.Get("policy_arn").(string)
	users := expandStringList(d.Get("users").(*schema.Set).List())
	roles := expandStringList(d.Get("roles").(*schema.Set).List())
	groups := expandStringList(d.Get("groups").(*schema.Set).List())

	if len(users) == 0 && len(roles) == 0 && len(groups) == 0 {
		return fmt.Errorf("[WARN] No Users, Roles, or Groups specified for IAM Policy Attachment %s", name)
	} else {
		var userErr, roleErr, groupErr error
		if users != nil {
			userErr = attachPolicyToUsers(conn, users, arn)
		}
		if roles != nil {
			roleErr = attachPolicyToRoles(conn, roles, arn)
		}
		if groups != nil {
			groupErr = attachPolicyToGroups(conn, groups, arn)
		}
		if userErr != nil || roleErr != nil || groupErr != nil {
			return composeErrors(fmt.Sprint("[WARN] Error attaching policy with IAM Policy Attachment ", name, ":"), userErr, roleErr, groupErr)
		}
	}
	d.SetId(d.Get("name").(string))
	return resourceAwsIamPolicyAttachmentRead(d, meta)
}

func resourceAwsIamPolicyAttachmentRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).iamconn
	arn := d.Get("policy_arn").(string)
	name := d.Get("name").(string)

	_, err := conn.GetPolicy(&iam.GetPolicyInput{
		PolicyArn: aws.String(arn),
	})

	if err != nil {
		if awsErr, ok := err.(awserr.Error); ok {
			if awsErr.Code() == "NoSuchEntity" {
				log.Printf("[WARN] No such entity found for Policy Attachment (%s)", d.Id())
				d.SetId("")
				return nil
			}
		}
		return err
	}

	ul := make([]string, 0)
	rl := make([]string, 0)
	gl := make([]string, 0)

	args := iam.ListEntitiesForPolicyInput{
		PolicyArn: aws.String(arn),
	}
	err = conn.ListEntitiesForPolicyPages(&args, func(page *iam.ListEntitiesForPolicyOutput, lastPage bool) bool {
		for _, u := range page.PolicyUsers {
			ul = append(ul, *u.UserName)
		}

		for _, r := range page.PolicyRoles {
			rl = append(rl, *r.RoleName)
		}

		for _, g := range page.PolicyGroups {
			gl = append(gl, *g.GroupName)
		}
		return true
	})
	if err != nil {
		return err
	}

	userErr := d.Set("users", ul)
	roleErr := d.Set("roles", rl)
	groupErr := d.Set("groups", gl)

	if userErr != nil || roleErr != nil || groupErr != nil {
		return composeErrors(fmt.Sprint("[WARN} Error setting user, role, or group list from IAM Policy Attachment ", name, ":"), userErr, roleErr, groupErr)
	}

	return nil
}
func resourceAwsIamPolicyAttachmentUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).iamconn
	name := d.Get("name").(string)
	var userErr, roleErr, groupErr error

	if d.HasChange("users") {
		userErr = updateUsers(conn, d, meta)
	}
	if d.HasChange("roles") {
		roleErr = updateRoles(conn, d, meta)
	}
	if d.HasChange("groups") {
		groupErr = updateGroups(conn, d, meta)
	}
	if userErr != nil || roleErr != nil || groupErr != nil {
		return composeErrors(fmt.Sprint("[WARN] Error updating user, role, or group list from IAM Policy Attachment ", name, ":"), userErr, roleErr, groupErr)
	}
	return resourceAwsIamPolicyAttachmentRead(d, meta)
}

func resourceAwsIamPolicyAttachmentDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).iamconn
	name := d.Get("name").(string)
	arn := d.Get("policy_arn").(string)
	users := expandStringList(d.Get("users").(*schema.Set).List())
	roles := expandStringList(d.Get("roles").(*schema.Set).List())
	groups := expandStringList(d.Get("groups").(*schema.Set).List())

	var userErr, roleErr, groupErr error
	if len(users) != 0 {
		userErr = detachPolicyFromUsers(conn, users, arn)
	}
	if len(roles) != 0 {
		roleErr = detachPolicyFromRoles(conn, roles, arn)
	}
	if len(groups) != 0 {
		groupErr = detachPolicyFromGroups(conn, groups, arn)
	}
	if userErr != nil || roleErr != nil || groupErr != nil {
		return composeErrors(fmt.Sprint("[WARN] Error removing user, role, or group list from IAM Policy Detach ", name, ":"), userErr, roleErr, groupErr)
	}
	return nil
}

func composeErrors(desc string, uErr error, rErr error, gErr error) error {
	errMsg := fmt.Sprintf(desc)
	errs := []error{uErr, rErr, gErr}
	for _, e := range errs {
		if e != nil {
			errMsg = errMsg + "\n– " + e.Error()
		}
	}
	return fmt.Errorf(errMsg)
}

func attachPolicyToUsers(conn *iam.IAM, users []*string, arn string) error {
	for _, u := range users {
		_, err := conn.AttachUserPolicy(&iam.AttachUserPolicyInput{
			UserName:  u,
			PolicyArn: aws.String(arn),
		})
		if err != nil {
			return err
		}
	}
	return nil
}
func attachPolicyToRoles(conn *iam.IAM, roles []*string, arn string) error {
	for _, r := range roles {
		_, err := conn.AttachRolePolicy(&iam.AttachRolePolicyInput{
			RoleName:  r,
			PolicyArn: aws.String(arn),
		})
		if err != nil {
			return err
		}

		var attachmentErr error
		attachmentErr = resource.Retry(2*time.Minute, func() *resource.RetryError {

			input := iam.ListRolePoliciesInput{
				RoleName: r,
			}

			attachedPolicies, err := conn.ListRolePolicies(&input)
			if err != nil {
				return resource.NonRetryableError(err)
			}

			if len(attachedPolicies.PolicyNames) > 0 {
				var foundPolicy bool
				for _, policyName := range attachedPolicies.PolicyNames {
					if strings.HasSuffix(arn, *policyName) {
						foundPolicy = true
						break
					}
				}

				if !foundPolicy {
					return resource.NonRetryableError(err)
				}
			}

			return nil
		})

		if attachmentErr != nil {
			return attachmentErr
		}
	}
	return nil
}
func attachPolicyToGroups(conn *iam.IAM, groups []*string, arn string) error {
	for _, g := range groups {
		_, err := conn.AttachGroupPolicy(&iam.AttachGroupPolicyInput{
			GroupName: g,
			PolicyArn: aws.String(arn),
		})
		if err != nil {
			return err
		}
	}
	return nil
}
func updateUsers(conn *iam.IAM, d *schema.ResourceData, meta interface{}) error {
	arn := d.Get("policy_arn").(string)
	o, n := d.GetChange("users")
	if o == nil {
		o = new(schema.Set)
	}
	if n == nil {
		n = new(schema.Set)
	}
	os := o.(*schema.Set)
	ns := n.(*schema.Set)
	remove := expandStringList(os.Difference(ns).List())
	add := expandStringList(ns.Difference(os).List())

	if rErr := detachPolicyFromUsers(conn, remove, arn); rErr != nil {
		return rErr
	}
	if aErr := attachPolicyToUsers(conn, add, arn); aErr != nil {
		return aErr
	}
	return nil
}
func updateRoles(conn *iam.IAM, d *schema.ResourceData, meta interface{}) error {
	arn := d.Get("policy_arn").(string)
	o, n := d.GetChange("roles")
	if o == nil {
		o = new(schema.Set)
	}
	if n == nil {
		n = new(schema.Set)
	}
	os := o.(*schema.Set)
	ns := n.(*schema.Set)
	remove := expandStringList(os.Difference(ns).List())
	add := expandStringList(ns.Difference(os).List())

	if rErr := detachPolicyFromRoles(conn, remove, arn); rErr != nil {
		return rErr
	}
	if aErr := attachPolicyToRoles(conn, add, arn); aErr != nil {
		return aErr
	}
	return nil
}
func updateGroups(conn *iam.IAM, d *schema.ResourceData, meta interface{}) error {
	arn := d.Get("policy_arn").(string)
	o, n := d.GetChange("groups")
	if o == nil {
		o = new(schema.Set)
	}
	if n == nil {
		n = new(schema.Set)
	}
	os := o.(*schema.Set)
	ns := n.(*schema.Set)
	remove := expandStringList(os.Difference(ns).List())
	add := expandStringList(ns.Difference(os).List())

	if rErr := detachPolicyFromGroups(conn, remove, arn); rErr != nil {
		return rErr
	}
	if aErr := attachPolicyToGroups(conn, add, arn); aErr != nil {
		return aErr
	}
	return nil

}
func detachPolicyFromUsers(conn *iam.IAM, users []*string, arn string) error {
	for _, u := range users {
		_, err := conn.DetachUserPolicy(&iam.DetachUserPolicyInput{
			UserName:  u,
			PolicyArn: aws.String(arn),
		})
		if err != nil {
			return err
		}
	}
	return nil
}
func detachPolicyFromRoles(conn *iam.IAM, roles []*string, arn string) error {
	for _, r := range roles {
		_, err := conn.DetachRolePolicy(&iam.DetachRolePolicyInput{
			RoleName:  r,
			PolicyArn: aws.String(arn),
		})
		if err != nil {
			return err
		}
	}
	return nil
}
func detachPolicyFromGroups(conn *iam.IAM, groups []*string, arn string) error {
	for _, g := range groups {
		_, err := conn.DetachGroupPolicy(&iam.DetachGroupPolicyInput{
			GroupName: g,
			PolicyArn: aws.String(arn),
		})
		if err != nil {
			return err
		}
	}
	return nil
}
<commit_msg>provider/aws: Validate `aws_iam_policy_attachment` Name parameter to stop being empty (#8441)<commit_after>package aws

import (
	"fmt"
	"log"
	"strings"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/iam"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsIamPolicyAttachment() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsIamPolicyAttachmentCreate,
		Read:   resourceAwsIamPolicyAttachmentRead,
		Update: resourceAwsIamPolicyAttachmentUpdate,
		Delete: resourceAwsIamPolicyAttachmentDelete,

		Schema: map[string]*schema.Schema{
			"name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
				ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
					if v.(string) == "" {
						errors = append(errors, fmt.Errorf(
							"%q cannot be an empty string", k))
					}
					return
				},
			},
			"users": &schema.Schema{
				Type:     schema.TypeSet,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Set:      schema.HashString,
			},
			"roles": &schema.Schema{
				Type:     schema.TypeSet,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Set:      schema.HashString,
			},
			"groups": &schema.Schema{
				Type:     schema.TypeSet,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Set:      schema.HashString,
			},
			"policy_arn": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
		},
	}
}

func resourceAwsIamPolicyAttachmentCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).iamconn

	name := d.Get("name").(string)
	arn := d.Get("policy_arn").(string)
	users := expandStringList(d.Get("users").(*schema.Set).List())
	roles := expandStringList(d.Get("roles").(*schema.Set).List())
	groups := expandStringList(d.Get("groups").(*schema.Set).List())

	if len(users) == 0 && len(roles) == 0 && len(groups) == 0 {
		return fmt.Errorf("[WARN] No Users, Roles, or Groups specified for IAM Policy Attachment %s", name)
	} else {
		var userErr, roleErr, groupErr error
		if users != nil {
			userErr = attachPolicyToUsers(conn, users, arn)
		}
		if roles != nil {
			roleErr = attachPolicyToRoles(conn, roles, arn)
		}
		if groups != nil {
			groupErr = attachPolicyToGroups(conn, groups, arn)
		}
		if userErr != nil || roleErr != nil || groupErr != nil {
			return composeErrors(fmt.Sprint("[WARN] Error attaching policy with IAM Policy Attachment ", name, ":"), userErr, roleErr, groupErr)
		}
	}
	d.SetId(d.Get("name").(string))
	return resourceAwsIamPolicyAttachmentRead(d, meta)
}

func resourceAwsIamPolicyAttachmentRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).iamconn
	arn := d.Get("policy_arn").(string)
	name := d.Get("name").(string)

	_, err := conn.GetPolicy(&iam.GetPolicyInput{
		PolicyArn: aws.String(arn),
	})

	if err != nil {
		if awsErr, ok := err.(awserr.Error); ok {
			if awsErr.Code() == "NoSuchEntity" {
				log.Printf("[WARN] No such entity found for Policy Attachment (%s)", d.Id())
				d.SetId("")
				return nil
			}
		}
		return err
	}

	ul := make([]string, 0)
	rl := make([]string, 0)
	gl := make([]string, 0)

	args := iam.ListEntitiesForPolicyInput{
		PolicyArn: aws.String(arn),
	}
	err = conn.ListEntitiesForPolicyPages(&args, func(page *iam.ListEntitiesForPolicyOutput, lastPage bool) bool {
		for _, u := range page.PolicyUsers {
			ul = append(ul, *u.UserName)
		}

		for _, r := range page.PolicyRoles {
			rl = append(rl, *r.RoleName)
		}

		for _, g := range page.PolicyGroups {
			gl = append(gl, *g.GroupName)
		}
		return true
	})
	if err != nil {
		return err
	}

	userErr := d.Set("users", ul)
	roleErr := d.Set("roles", rl)
	groupErr := d.Set("groups", gl)

	if userErr != nil || roleErr != nil || groupErr != nil {
		return composeErrors(fmt.Sprint("[WARN} Error setting user, role, or group list from IAM Policy Attachment ", name, ":"), userErr, roleErr, groupErr)
	}

	return nil
}
func resourceAwsIamPolicyAttachmentUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).iamconn
	name := d.Get("name").(string)
	var userErr, roleErr, groupErr error

	if d.HasChange("users") {
		userErr = updateUsers(conn, d, meta)
	}
	if d.HasChange("roles") {
		roleErr = updateRoles(conn, d, meta)
	}
	if d.HasChange("groups") {
		groupErr = updateGroups(conn, d, meta)
	}
	if userErr != nil || roleErr != nil || groupErr != nil {
		return composeErrors(fmt.Sprint("[WARN] Error updating user, role, or group list from IAM Policy Attachment ", name, ":"), userErr, roleErr, groupErr)
	}
	return resourceAwsIamPolicyAttachmentRead(d, meta)
}

func resourceAwsIamPolicyAttachmentDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).iamconn
	name := d.Get("name").(string)
	arn := d.Get("policy_arn").(string)
	users := expandStringList(d.Get("users").(*schema.Set).List())
	roles := expandStringList(d.Get("roles").(*schema.Set).List())
	groups := expandStringList(d.Get("groups").(*schema.Set).List())

	var userErr, roleErr, groupErr error
	if len(users) != 0 {
		userErr = detachPolicyFromUsers(conn, users, arn)
	}
	if len(roles) != 0 {
		roleErr = detachPolicyFromRoles(conn, roles, arn)
	}
	if len(groups) != 0 {
		groupErr = detachPolicyFromGroups(conn, groups, arn)
	}
	if userErr != nil || roleErr != nil || groupErr != nil {
		return composeErrors(fmt.Sprint("[WARN] Error removing user, role, or group list from IAM Policy Detach ", name, ":"), userErr, roleErr, groupErr)
	}
	return nil
}

func composeErrors(desc string, uErr error, rErr error, gErr error) error {
	errMsg := fmt.Sprintf(desc)
	errs := []error{uErr, rErr, gErr}
	for _, e := range errs {
		if e != nil {
			errMsg = errMsg + "\n– " + e.Error()
		}
	}
	return fmt.Errorf(errMsg)
}

func attachPolicyToUsers(conn *iam.IAM, users []*string, arn string) error {
	for _, u := range users {
		_, err := conn.AttachUserPolicy(&iam.AttachUserPolicyInput{
			UserName:  u,
			PolicyArn: aws.String(arn),
		})
		if err != nil {
			return err
		}
	}
	return nil
}
func attachPolicyToRoles(conn *iam.IAM, roles []*string, arn string) error {
	for _, r := range roles {
		_, err := conn.AttachRolePolicy(&iam.AttachRolePolicyInput{
			RoleName:  r,
			PolicyArn: aws.String(arn),
		})
		if err != nil {
			return err
		}

		var attachmentErr error
		attachmentErr = resource.Retry(2*time.Minute, func() *resource.RetryError {

			input := iam.ListRolePoliciesInput{
				RoleName: r,
			}

			attachedPolicies, err := conn.ListRolePolicies(&input)
			if err != nil {
				return resource.NonRetryableError(err)
			}

			if len(attachedPolicies.PolicyNames) > 0 {
				var foundPolicy bool
				for _, policyName := range attachedPolicies.PolicyNames {
					if strings.HasSuffix(arn, *policyName) {
						foundPolicy = true
						break
					}
				}

				if !foundPolicy {
					return resource.NonRetryableError(err)
				}
			}

			return nil
		})

		if attachmentErr != nil {
			return attachmentErr
		}
	}
	return nil
}
func attachPolicyToGroups(conn *iam.IAM, groups []*string, arn string) error {
	for _, g := range groups {
		_, err := conn.AttachGroupPolicy(&iam.AttachGroupPolicyInput{
			GroupName: g,
			PolicyArn: aws.String(arn),
		})
		if err != nil {
			return err
		}
	}
	return nil
}
func updateUsers(conn *iam.IAM, d *schema.ResourceData, meta interface{}) error {
	arn := d.Get("policy_arn").(string)
	o, n := d.GetChange("users")
	if o == nil {
		o = new(schema.Set)
	}
	if n == nil {
		n = new(schema.Set)
	}
	os := o.(*schema.Set)
	ns := n.(*schema.Set)
	remove := expandStringList(os.Difference(ns).List())
	add := expandStringList(ns.Difference(os).List())

	if rErr := detachPolicyFromUsers(conn, remove, arn); rErr != nil {
		return rErr
	}
	if aErr := attachPolicyToUsers(conn, add, arn); aErr != nil {
		return aErr
	}
	return nil
}
func updateRoles(conn *iam.IAM, d *schema.ResourceData, meta interface{}) error {
	arn := d.Get("policy_arn").(string)
	o, n := d.GetChange("roles")
	if o == nil {
		o = new(schema.Set)
	}
	if n == nil {
		n = new(schema.Set)
	}
	os := o.(*schema.Set)
	ns := n.(*schema.Set)
	remove := expandStringList(os.Difference(ns).List())
	add := expandStringList(ns.Difference(os).List())

	if rErr := detachPolicyFromRoles(conn, remove, arn); rErr != nil {
		return rErr
	}
	if aErr := attachPolicyToRoles(conn, add, arn); aErr != nil {
		return aErr
	}
	return nil
}
func updateGroups(conn *iam.IAM, d *schema.ResourceData, meta interface{}) error {
	arn := d.Get("policy_arn").(string)
	o, n := d.GetChange("groups")
	if o == nil {
		o = new(schema.Set)
	}
	if n == nil {
		n = new(schema.Set)
	}
	os := o.(*schema.Set)
	ns := n.(*schema.Set)
	remove := expandStringList(os.Difference(ns).List())
	add := expandStringList(ns.Difference(os).List())

	if rErr := detachPolicyFromGroups(conn, remove, arn); rErr != nil {
		return rErr
	}
	if aErr := attachPolicyToGroups(conn, add, arn); aErr != nil {
		return aErr
	}
	return nil

}
func detachPolicyFromUsers(conn *iam.IAM, users []*string, arn string) error {
	for _, u := range users {
		_, err := conn.DetachUserPolicy(&iam.DetachUserPolicyInput{
			UserName:  u,
			PolicyArn: aws.String(arn),
		})
		if err != nil {
			return err
		}
	}
	return nil
}
func detachPolicyFromRoles(conn *iam.IAM, roles []*string, arn string) error {
	for _, r := range roles {
		_, err := conn.DetachRolePolicy(&iam.DetachRolePolicyInput{
			RoleName:  r,
			PolicyArn: aws.String(arn),
		})
		if err != nil {
			return err
		}
	}
	return nil
}
func detachPolicyFromGroups(conn *iam.IAM, groups []*string, arn string) error {
	for _, g := range groups {
		_, err := conn.DetachGroupPolicy(&iam.DetachGroupPolicyInput{
			GroupName: g,
			PolicyArn: aws.String(arn),
		})
		if err != nil {
			return err
		}
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bytes"
	"flag"
	"fmt"
	"go/ast"
	"go/parser"
	"go/printer"
	"go/scanner"
	"go/token"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime/pprof"
	"strings"
)

var (
	// main operation modes
	list        = flag.Bool("l", false, "list files whose formatting differs from gofmt's")
	write       = flag.Bool("w", false, "write result to (source) file instead of stdout")
	rewriteRule = flag.String("r", "", "rewrite rule (e.g., 'α[β:len(α)] -> α[β:]')")
	simplifyAST = flag.Bool("s", false, "simplify code")

	// layout control
	comments  = flag.Bool("comments", true, "print comments")
	tabWidth  = flag.Int("tabwidth", 8, "tab width")
	tabIndent = flag.Bool("tabindent", true, "indent with tabs independent of -spaces")
	useSpaces = flag.Bool("spaces", true, "align with spaces instead of tabs")

	// debugging
	cpuprofile = flag.String("cpuprofile", "", "write cpu profile to this file")
)

var (
	fset        = token.NewFileSet()
	exitCode    = 0
	rewrite     func(*ast.File) *ast.File
	parserMode  uint
	printerMode uint
)

func report(err os.Error) {
	scanner.PrintError(os.Stderr, err)
	exitCode = 2
}

func usage() {
	fmt.Fprintf(os.Stderr, "usage: gofmt [flags] [path ...]\n")
	flag.PrintDefaults()
	os.Exit(2)
}

func initParserMode() {
	parserMode = uint(0)
	if *comments {
		parserMode |= parser.ParseComments
	}
}

func initPrinterMode() {
	printerMode = uint(0)
	if *tabIndent {
		printerMode |= printer.TabIndent
	}
	if *useSpaces {
		printerMode |= printer.UseSpaces
	}
}

func isGoFile(f *os.FileInfo) bool {
	// ignore non-Go files
	return f.IsRegular() && !strings.HasPrefix(f.Name, ".") && strings.HasSuffix(f.Name, ".go")
}

// If in == nil, the source is the contents of the file with the given filename.
func processFile(filename string, in io.Reader, out io.Writer) os.Error {
	if in == nil {
		f, err := os.Open(filename)
		if err != nil {
			return err
		}
		defer f.Close()
		in = f
	}

	src, err := ioutil.ReadAll(in)
	if err != nil {
		return err
	}

	file, err := parser.ParseFile(fset, filename, src, parserMode)
	if err != nil {
		return err
	}

	if rewrite != nil {
		file = rewrite(file)
	}

	if *simplifyAST {
		simplify(file)
	}

	var buf bytes.Buffer
	_, err = (&printer.Config{printerMode, *tabWidth}).Fprint(&buf, fset, file)
	if err != nil {
		return err
	}
	res := buf.Bytes()

	if !bytes.Equal(src, res) {
		// formatting has changed
		if *list {
			fmt.Fprintln(out, filename)
		}
		if *write {
			err = ioutil.WriteFile(filename, res, 0)
			if err != nil {
				return err
			}
		}
	}

	if !*list && !*write {
		_, err = out.Write(res)
	}

	return err
}

type fileVisitor chan os.Error

func (v fileVisitor) VisitDir(path string, f *os.FileInfo) bool {
	return true
}

func (v fileVisitor) VisitFile(path string, f *os.FileInfo) {
	if isGoFile(f) {
		v <- nil // synchronize error handler
		if err := processFile(path, nil, os.Stdout); err != nil {
			v <- err
		}
	}
}

func walkDir(path string) {
	v := make(fileVisitor)
	go func() {
		filepath.Walk(path, v, v)
		close(v)
	}()
	for err := range v {
		if err != nil {
			report(err)
		}
	}
}

func main() {
	// call gofmtMain in a separate function
	// so that it can use defer and have them
	// run before the exit.
	gofmtMain()
	os.Exit(exitCode)
}

func gofmtMain() {
	flag.Usage = usage
	flag.Parse()
	if *tabWidth < 0 {
		fmt.Fprintf(os.Stderr, "negative tabwidth %d\n", *tabWidth)
		exitCode = 2
		return
	}

	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			fmt.Fprintf(os.Stderr, "creating cpu profile: %s\n", err)
			exitCode = 2
			return
		}
		defer f.Close()
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	initParserMode()
	initPrinterMode()
	initRewrite()

	if flag.NArg() == 0 {
		if err := processFile("<standard input>", os.Stdin, os.Stdout); err != nil {
			report(err)
		}
		return
	}

	for i := 0; i < flag.NArg(); i++ {
		path := flag.Arg(i)
		switch dir, err := os.Stat(path); {
		case err != nil:
			report(err)
		case dir.IsRegular():
			if err := processFile(path, nil, os.Stdout); err != nil {
				report(err)
			}
		case dir.IsDirectory():
			walkDir(path)
		}
	}
}
<commit_msg>gofmt: add -diff<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bytes"
	"exec"
	"flag"
	"fmt"
	"go/ast"
	"go/parser"
	"go/printer"
	"go/scanner"
	"go/token"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime/pprof"
	"strings"
)

var (
	// main operation modes
	list        = flag.Bool("l", false, "list files whose formatting differs from gofmt's")
	write       = flag.Bool("w", false, "write result to (source) file instead of stdout")
	rewriteRule = flag.String("r", "", "rewrite rule (e.g., 'α[β:len(α)] -> α[β:]')")
	simplifyAST = flag.Bool("s", false, "simplify code")
	doDiff      = flag.Bool("d", false, "display diffs instead of rewriting files")

	// layout control
	comments  = flag.Bool("comments", true, "print comments")
	tabWidth  = flag.Int("tabwidth", 8, "tab width")
	tabIndent = flag.Bool("tabindent", true, "indent with tabs independent of -spaces")
	useSpaces = flag.Bool("spaces", true, "align with spaces instead of tabs")

	// debugging
	cpuprofile = flag.String("cpuprofile", "", "write cpu profile to this file")
)

var (
	fset        = token.NewFileSet()
	exitCode    = 0
	rewrite     func(*ast.File) *ast.File
	parserMode  uint
	printerMode uint
)

func report(err os.Error) {
	scanner.PrintError(os.Stderr, err)
	exitCode = 2
}

func usage() {
	fmt.Fprintf(os.Stderr, "usage: gofmt [flags] [path ...]\n")
	flag.PrintDefaults()
	os.Exit(2)
}

func initParserMode() {
	parserMode = uint(0)
	if *comments {
		parserMode |= parser.ParseComments
	}
}

func initPrinterMode() {
	printerMode = uint(0)
	if *tabIndent {
		printerMode |= printer.TabIndent
	}
	if *useSpaces {
		printerMode |= printer.UseSpaces
	}
}

func isGoFile(f *os.FileInfo) bool {
	// ignore non-Go files
	return f.IsRegular() && !strings.HasPrefix(f.Name, ".") && strings.HasSuffix(f.Name, ".go")
}

// If in == nil, the source is the contents of the file with the given filename.
func processFile(filename string, in io.Reader, out io.Writer) os.Error {
	if in == nil {
		f, err := os.Open(filename)
		if err != nil {
			return err
		}
		defer f.Close()
		in = f
	}

	src, err := ioutil.ReadAll(in)
	if err != nil {
		return err
	}

	file, err := parser.ParseFile(fset, filename, src, parserMode)
	if err != nil {
		return err
	}

	if rewrite != nil {
		file = rewrite(file)
	}

	if *simplifyAST {
		simplify(file)
	}

	var buf bytes.Buffer
	_, err = (&printer.Config{printerMode, *tabWidth}).Fprint(&buf, fset, file)
	if err != nil {
		return err
	}
	res := buf.Bytes()

	if !bytes.Equal(src, res) {
		// formatting has changed
		if *list {
			fmt.Fprintln(out, filename)
		}
		if *write {
			err = ioutil.WriteFile(filename, res, 0)
			if err != nil {
				return err
			}
		}
		if *doDiff {
			data, err := diff(src, res)
			if err != nil {
				return fmt.Errorf("computing diff: %s", err)
			}
			fmt.Printf("diff %s fixed/%s\n", filename, filename)
			out.Write(data)
		}
	}

	if !*list && !*write && !*doDiff {
		_, err = out.Write(res)
	}

	return err
}

type fileVisitor chan os.Error

func (v fileVisitor) VisitDir(path string, f *os.FileInfo) bool {
	return true
}

func (v fileVisitor) VisitFile(path string, f *os.FileInfo) {
	if isGoFile(f) {
		v <- nil // synchronize error handler
		if err := processFile(path, nil, os.Stdout); err != nil {
			v <- err
		}
	}
}

func walkDir(path string) {
	v := make(fileVisitor)
	go func() {
		filepath.Walk(path, v, v)
		close(v)
	}()
	for err := range v {
		if err != nil {
			report(err)
		}
	}
}

func main() {
	// call gofmtMain in a separate function
	// so that it can use defer and have them
	// run before the exit.
	gofmtMain()
	os.Exit(exitCode)
}

func gofmtMain() {
	flag.Usage = usage
	flag.Parse()
	if *tabWidth < 0 {
		fmt.Fprintf(os.Stderr, "negative tabwidth %d\n", *tabWidth)
		exitCode = 2
		return
	}

	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			fmt.Fprintf(os.Stderr, "creating cpu profile: %s\n", err)
			exitCode = 2
			return
		}
		defer f.Close()
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	initParserMode()
	initPrinterMode()
	initRewrite()

	if flag.NArg() == 0 {
		if err := processFile("<standard input>", os.Stdin, os.Stdout); err != nil {
			report(err)
		}
		return
	}

	for i := 0; i < flag.NArg(); i++ {
		path := flag.Arg(i)
		switch dir, err := os.Stat(path); {
		case err != nil:
			report(err)
		case dir.IsRegular():
			if err := processFile(path, nil, os.Stdout); err != nil {
				report(err)
			}
		case dir.IsDirectory():
			walkDir(path)
		}
	}
}

func diff(b1, b2 []byte) (data []byte, err os.Error) {
	f1, err := ioutil.TempFile("", "gofmt")
	if err != nil {
		return nil, err
	}
	defer os.Remove(f1.Name())
	defer f1.Close()

	f2, err := ioutil.TempFile("", "gofmt")
	if err != nil {
		return nil, err
	}
	defer os.Remove(f2.Name())
	defer f2.Close()

	f1.Write(b1)
	f2.Write(b2)

	diffcmd, err := exec.LookPath("diff")
	if err != nil {
		return nil, err
	}

	c, err := exec.Run(diffcmd, []string{"diff", "-u", f1.Name(), f2.Name()},
		nil, "", exec.DevNull, exec.Pipe, exec.MergeWithStdout)
	if err != nil {
		return nil, err
	}
	defer c.Close()

	return ioutil.ReadAll(c.Stdout)
}
<|endoftext|>