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

package fs

import (
	"errors"
	"fmt"
	"reflect"

	"github.com/jacobsa/fuse"
	"github.com/jacobsa/fuse/fuseutil"
	"github.com/jacobsa/gcloud/gcs"
	"github.com/jacobsa/gcloud/syncutil"
	"github.com/jacobsa/gcsfuse/fs/inode"
	"github.com/jacobsa/gcsfuse/timeutil"
	"golang.org/x/net/context"
	"google.golang.org/cloud/storage"
)

type fileSystem struct {
	fuseutil.NotImplementedFileSystem

	/////////////////////////
	// Dependencies
	/////////////////////////

	clock  timeutil.Clock
	bucket gcs.Bucket

	/////////////////////////
	// Mutable state
	/////////////////////////

	// When acquiring this lock, the caller must hold no inode or dir handle
	// locks.
	mu syncutil.InvariantMutex

	// The user and group owning everything in the file system.
	//
	// GUARDED_BY(Mu)
	uid uint32
	gid uint32

	// The collection of live inodes, keyed by inode ID. No ID less than
	// fuse.RootInodeID is ever used.
	//
	// INVARIANT: All values are of type *inode.DirInode or *inode.FileInode
	// INVARIANT: For all keys k, k >= fuse.RootInodeID
	// INVARIANT: inodes[fuse.RootInodeID] is of type *inode.DirInode
	//
	// GUARDED_BY(mu)
	inodes map[fuse.InodeID]inode.Inode

	// The next inode ID to hand out. We assume that this will never overflow,
	// since even if we were handing out inode IDs at 4 GHz, it would still take
	// over a century to do so.
	//
	// INVARIANT: For all keys k in inodes, k < nextInodeID
	//
	// GUARDED_BY(mu)
	nextInodeID fuse.InodeID

	// An index of all directory inodes by Name().
	//
	// INVARIANT: For each key k, isDirName(k)
	//
	// INVARIANT: For each key k, dirNameIndex[k].Name() == k
	//
	// INVARIANT: The values are all and only the values of the inodes map of
	// type *inode.DirHandle.
	//
	// GUARDED_BY(mu)
	dirNameIndex map[string]*inode.DirInode

	// The collection of live handles, keyed by handle ID.
	//
	// INVARIANT: All values are of type *dirHandle
	//
	// GUARDED_BY(mu)
	handles map[fuse.HandleID]interface{}

	// The next handle ID to hand out. We assume that this will never overflow.
	//
	// INVARIANT: For all keys k in handles, k < nextHandleID
	//
	// GUARDED_BY(mu)
	nextHandleID fuse.HandleID
}

// Create a fuse file system whose root directory is the root of the supplied
// bucket. The supplied clock will be used for cache invalidation, modification
// times, etc.
func NewFileSystem(
	clock timeutil.Clock,
	bucket gcs.Bucket) (ffs fuse.FileSystem, err error) {
	// Set up the basic struct.
	fs := &fileSystem{
		clock:        clock,
		bucket:       bucket,
		inodes:       make(map[fuse.InodeID]interface{}),
		nextInodeID:  fuse.RootInodeID + 1,
		dirNameIndex: make(map[string]*inode.DirInode),
		handles:      make(map[fuse.HandleID]interface{}),
	}

	// Set up the root inode.
	root := inode.NewDirInode(bucket, "")
	fs.inodes[fuse.RootInodeID] = root
	fs.dirNameIndex[""] = root

	// Set up invariant checking.
	fs.mu = syncutil.NewInvariantMutex(fs.checkInvariants)

	ffs = fs
	return
}

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

func isDirName(name string) bool {
	return name == "" || name[len(name)-1] == '/'
}

func (fs *fileSystem) checkInvariants() {
	// Check inode keys.
	for id, _ := range fs.inodes {
		if id < fuse.RootInodeID || id >= fs.nextInodeID {
			panic(fmt.Sprintf("Illegal inode ID: %v", id))
		}
	}

	// Check the root inode.
	_ = fs.inodes[fuse.RootInodeID].(*inode.DirInode)

	// Check each inode, and the indexes over them. Keep a count of each type
	// seen.
	dirsSeen := 0
	filesSeen := 0
	for _, in := range fs.inodes {
		switch typed := in.(type) {
		case *inode.DirInode:
			if !isDirName(typed.Name()) {
				panic(fmt.Sprintf("Unexpected directory name: %s", typed.Name()))
			}

			dirsSeen++
			if fs.dirNameIndex[typed.Name()] != typed {
				panic(fmt.Sprintf("dirNameIndex mismatch: %s", typed.Name()))
			}

		case *inode.FileInode:
			filesSeen++

		default:
			panic(fmt.Sprintf("Unexpected inode type: %v", reflect.TypeOf(in)))
		}
	}

	// Make sure that the indexes are exhaustive.
	if len(fs.dirNameIndex) != dirsSeen {
		panic(
			fmt.Sprintf(
				"dirNameIndex length mismatch: %v vs. %v",
				len(fs.dirNameIndex),
				dirsSeen))
	}

	// Check handles.
	for id, h := range fs.handles {
		if id >= fs.nextHandleID {
			panic(fmt.Sprintf("Illegal handle ID: %v", id))
		}

		_ = h.(*dirHandle)
	}
}

// Find the given inode and return it with its lock held for reading. Panic if
// it doesn't exist or is the wrong type.
//
// SHARED_LOCKS_REQUIRED(fs.mu)
// SHARED_LOCK_FUNCTION(in.mu)
func (fs *fileSystem) getDirForReadingOrDie(
	id fuse.InodeID) (in *inode.DirInode) {
	in = fs.inodes[id].(*inode.DirInode)
	in.Mu.RLock()
	return
}

// Get attributes for the given directory inode, fixing up ownership information.
//
// SHARED_LOCKS_REQUIRED(fs.mu)
// SHARED_LOCK_FUNCTION(d.mu)
func (fs *fileSystem) getAttributes(
	ctx context.Context,
	d *inode.DirInode) (attrs fuse.InodeAttributes, err error) {
	attrs, err = d.Attributes(ctx)
	if err != nil {
		return
	}

	attrs.Uid = fs.uid
	attrs.Gid = fs.gid

	return
}

// Find a directory inode for the given object record. Create one if there
// isn't already one available.
//
// EXCLUSIVE_LOCKS_REQUIRED(fs.mu)
func (fs *fileSystem) lookUpOrCreateDirInode(
	ctx context.Context,
	o *storage.Object) (in *inode.DirInode, err error) {
	// Do we already have an inode for this name?
	if in = fs.dirNameIndex[o.Name]; in != nil {
		return
	}

	err = errors.New("TODO(jacobsa): Mint an inode.")
	return
}

////////////////////////////////////////////////////////////////////////
// fuse.FileSystem methods
////////////////////////////////////////////////////////////////////////

func (fs *fileSystem) Init(
	ctx context.Context,
	req *fuse.InitRequest) (resp *fuse.InitResponse, err error) {
	resp = &fuse.InitResponse{}

	fs.mu.Lock()
	defer fs.mu.Unlock()

	// Store the mounting user's info for later.
	fs.uid = req.Header.Uid
	fs.gid = req.Header.Gid

	return
}

func (fs *fileSystem) LookUpInode(
	ctx context.Context,
	req *fuse.LookUpInodeRequest) (resp *fuse.LookUpInodeResponse, err error) {
	fs.mu.Lock()
	defer fs.mu.Unlock()

	// Find the parent directory in question.
	parent := fs.inodes[req.Parent].(*inode.DirInode)

	// Find a record for the child with the given name.
	o, err := parent.LookUpChild(ctx, req.Name)
	if err != nil {
		err = fmt.Errorf("LookUpChild: %v", err)
		return
	}

	// Is the child a directory or a file?
	var in inode.Inode
	if isDirName(o.Name) {
		in, err = fs.lookUpOrCreateDirInode(ctx, o)
	} else {
		err = errors.New("TODO(jacobsa): Handle files in the same way.")
	}

	if err != nil {
		return
	}

	// Fill out the response.
	resp.Entry.Child = in.ID()
	if resp.Entry.Attributes, err = in.Attributes(ctx); err != nil {
		return
	}

	return
}

func (fs *fileSystem) GetInodeAttributes(
	ctx context.Context,
	req *fuse.GetInodeAttributesRequest) (
	resp *fuse.GetInodeAttributesResponse, err error) {
	resp = &fuse.GetInodeAttributesResponse{}

	fs.mu.RLock()
	defer fs.mu.RUnlock()

	// Find the inode.
	in := fs.inodes[req.Inode]

	// Grab its attributes.
	switch typed := in.(type) {
	case *inode.DirInode:
		resp.Attributes, err = fs.getAttributes(ctx, typed)
		if err != nil {
			err = fmt.Errorf("DirInode.Attributes: %v", err)
			return
		}

	default:
		panic(
			fmt.Sprintf(
				"Unknown inode type for ID %v: %v",
				req.Inode,
				reflect.TypeOf(in)))
	}

	return
}

func (fs *fileSystem) OpenDir(
	ctx context.Context,
	req *fuse.OpenDirRequest) (resp *fuse.OpenDirResponse, err error) {
	resp = &fuse.OpenDirResponse{}

	fs.mu.Lock()
	defer fs.mu.Unlock()

	// Make sure the inode still exists and is a directory. If not, something has
	// screwed up because the VFS layer shouldn't have let us forget the inode
	// before opening it.
	in := fs.getDirForReadingOrDie(req.Inode)
	defer in.Mu.RUnlock()

	// Allocate a handle.
	handleID := fs.nextHandleID
	fs.nextHandleID++

	fs.handles[handleID] = newDirHandle(in)
	resp.Handle = handleID

	return
}

func (fs *fileSystem) ReadDir(
	ctx context.Context,
	req *fuse.ReadDirRequest) (resp *fuse.ReadDirResponse, err error) {
	fs.mu.RLock()
	defer fs.mu.RUnlock()

	// Find the handle.
	dh := fs.handles[req.Handle].(*dirHandle)
	dh.Mu.Lock()
	defer dh.Mu.Unlock()

	// Serve the request.
	resp, err = dh.ReadDir(ctx, req)

	return
}

func (fs *fileSystem) ReleaseDirHandle(
	ctx context.Context,
	req *fuse.ReleaseDirHandleRequest) (
	resp *fuse.ReleaseDirHandleResponse, err error) {
	resp = &fuse.ReleaseDirHandleResponse{}

	fs.mu.Lock()
	defer fs.mu.Unlock()

	// Sanity check that this handle exists and is of the correct type.
	_ = fs.handles[req.Handle].(*dirHandle)

	// Clear the entry from the map.
	delete(fs.handles, req.Handle)

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

package fs

import (
	"errors"
	"fmt"
	"reflect"

	"github.com/jacobsa/fuse"
	"github.com/jacobsa/fuse/fuseutil"
	"github.com/jacobsa/gcloud/gcs"
	"github.com/jacobsa/gcloud/syncutil"
	"github.com/jacobsa/gcsfuse/fs/inode"
	"github.com/jacobsa/gcsfuse/timeutil"
	"golang.org/x/net/context"
	"google.golang.org/cloud/storage"
)

type fileSystem struct {
	fuseutil.NotImplementedFileSystem

	/////////////////////////
	// Dependencies
	/////////////////////////

	clock  timeutil.Clock
	bucket gcs.Bucket

	/////////////////////////
	// Mutable state
	/////////////////////////

	// When acquiring this lock, the caller must hold no inode or dir handle
	// locks.
	mu syncutil.InvariantMutex

	// The user and group owning everything in the file system.
	//
	// GUARDED_BY(Mu)
	uid uint32
	gid uint32

	// The collection of live inodes, keyed by inode ID. No ID less than
	// fuse.RootInodeID is ever used.
	//
	// INVARIANT: All values are of type *inode.DirInode or *inode.FileInode
	// INVARIANT: For all keys k, k >= fuse.RootInodeID
	// INVARIANT: inodes[fuse.RootInodeID] is of type *inode.DirInode
	//
	// GUARDED_BY(mu)
	inodes map[fuse.InodeID]inode.Inode

	// The next inode ID to hand out. We assume that this will never overflow,
	// since even if we were handing out inode IDs at 4 GHz, it would still take
	// over a century to do so.
	//
	// INVARIANT: For all keys k in inodes, k < nextInodeID
	//
	// GUARDED_BY(mu)
	nextInodeID fuse.InodeID

	// An index of all directory inodes by Name().
	//
	// INVARIANT: For each key k, isDirName(k)
	//
	// INVARIANT: For each key k, dirNameIndex[k].Name() == k
	//
	// INVARIANT: The values are all and only the values of the inodes map of
	// type *inode.DirHandle.
	//
	// GUARDED_BY(mu)
	dirNameIndex map[string]*inode.DirInode

	// The collection of live handles, keyed by handle ID.
	//
	// INVARIANT: All values are of type *dirHandle
	//
	// GUARDED_BY(mu)
	handles map[fuse.HandleID]interface{}

	// The next handle ID to hand out. We assume that this will never overflow.
	//
	// INVARIANT: For all keys k in handles, k < nextHandleID
	//
	// GUARDED_BY(mu)
	nextHandleID fuse.HandleID
}

// Create a fuse file system whose root directory is the root of the supplied
// bucket. The supplied clock will be used for cache invalidation, modification
// times, etc.
func NewFileSystem(
	clock timeutil.Clock,
	bucket gcs.Bucket) (ffs fuse.FileSystem, err error) {
	// Set up the basic struct.
	fs := &fileSystem{
		clock:        clock,
		bucket:       bucket,
		inodes:       make(map[fuse.InodeID]inode.Inode),
		nextInodeID:  fuse.RootInodeID + 1,
		dirNameIndex: make(map[string]*inode.DirInode),
		handles:      make(map[fuse.HandleID]interface{}),
	}

	// Set up the root inode.
	root := inode.NewDirInode(bucket, fuse.RootInodeID, "")
	fs.inodes[fuse.RootInodeID] = root
	fs.dirNameIndex[""] = root

	// Set up invariant checking.
	fs.mu = syncutil.NewInvariantMutex(fs.checkInvariants)

	ffs = fs
	return
}

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

func isDirName(name string) bool {
	return name == "" || name[len(name)-1] == '/'
}

func (fs *fileSystem) checkInvariants() {
	// Check inode keys.
	for id, _ := range fs.inodes {
		if id < fuse.RootInodeID || id >= fs.nextInodeID {
			panic(fmt.Sprintf("Illegal inode ID: %v", id))
		}
	}

	// Check the root inode.
	_ = fs.inodes[fuse.RootInodeID].(*inode.DirInode)

	// Check each inode, and the indexes over them. Keep a count of each type
	// seen.
	dirsSeen := 0
	filesSeen := 0
	for _, in := range fs.inodes {
		switch typed := in.(type) {
		case *inode.DirInode:
			if !isDirName(typed.Name()) {
				panic(fmt.Sprintf("Unexpected directory name: %s", typed.Name()))
			}

			dirsSeen++
			if fs.dirNameIndex[typed.Name()] != typed {
				panic(fmt.Sprintf("dirNameIndex mismatch: %s", typed.Name()))
			}

		case *inode.FileInode:
			filesSeen++

		default:
			panic(fmt.Sprintf("Unexpected inode type: %v", reflect.TypeOf(in)))
		}
	}

	// Make sure that the indexes are exhaustive.
	if len(fs.dirNameIndex) != dirsSeen {
		panic(
			fmt.Sprintf(
				"dirNameIndex length mismatch: %v vs. %v",
				len(fs.dirNameIndex),
				dirsSeen))
	}

	// Check handles.
	for id, h := range fs.handles {
		if id >= fs.nextHandleID {
			panic(fmt.Sprintf("Illegal handle ID: %v", id))
		}

		_ = h.(*dirHandle)
	}
}

// Find the given inode and return it with its lock held for reading. Panic if
// it doesn't exist or is the wrong type.
//
// SHARED_LOCKS_REQUIRED(fs.mu)
// SHARED_LOCK_FUNCTION(in.mu)
func (fs *fileSystem) getDirForReadingOrDie(
	id fuse.InodeID) (in *inode.DirInode) {
	in = fs.inodes[id].(*inode.DirInode)
	in.Mu.RLock()
	return
}

// Get attributes for the given directory inode, fixing up ownership information.
//
// SHARED_LOCKS_REQUIRED(fs.mu)
// SHARED_LOCK_FUNCTION(d.mu)
func (fs *fileSystem) getAttributes(
	ctx context.Context,
	d *inode.DirInode) (attrs fuse.InodeAttributes, err error) {
	attrs, err = d.Attributes(ctx)
	if err != nil {
		return
	}

	attrs.Uid = fs.uid
	attrs.Gid = fs.gid

	return
}

// Find a directory inode for the given object record. Create one if there
// isn't already one available.
//
// EXCLUSIVE_LOCKS_REQUIRED(fs.mu)
func (fs *fileSystem) lookUpOrCreateDirInode(
	ctx context.Context,
	o *storage.Object) (in *inode.DirInode, err error) {
	// Do we already have an inode for this name?
	if in = fs.dirNameIndex[o.Name]; in != nil {
		return
	}

	err = errors.New("TODO(jacobsa): Mint an inode.")
	return
}

////////////////////////////////////////////////////////////////////////
// fuse.FileSystem methods
////////////////////////////////////////////////////////////////////////

func (fs *fileSystem) Init(
	ctx context.Context,
	req *fuse.InitRequest) (resp *fuse.InitResponse, err error) {
	resp = &fuse.InitResponse{}

	fs.mu.Lock()
	defer fs.mu.Unlock()

	// Store the mounting user's info for later.
	fs.uid = req.Header.Uid
	fs.gid = req.Header.Gid

	return
}

func (fs *fileSystem) LookUpInode(
	ctx context.Context,
	req *fuse.LookUpInodeRequest) (resp *fuse.LookUpInodeResponse, err error) {
	fs.mu.Lock()
	defer fs.mu.Unlock()

	// Find the parent directory in question.
	parent := fs.inodes[req.Parent].(*inode.DirInode)

	// Find a record for the child with the given name.
	o, err := parent.LookUpChild(ctx, req.Name)
	if err != nil {
		err = fmt.Errorf("LookUpChild: %v", err)
		return
	}

	// Is the child a directory or a file?
	var in inode.Inode
	if isDirName(o.Name) {
		in, err = fs.lookUpOrCreateDirInode(ctx, o)
	} else {
		err = errors.New("TODO(jacobsa): Handle files in the same way.")
	}

	if err != nil {
		return
	}

	// Fill out the response.
	resp.Entry.Child = in.ID()
	if resp.Entry.Attributes, err = in.Attributes(ctx); err != nil {
		return
	}

	return
}

func (fs *fileSystem) GetInodeAttributes(
	ctx context.Context,
	req *fuse.GetInodeAttributesRequest) (
	resp *fuse.GetInodeAttributesResponse, err error) {
	resp = &fuse.GetInodeAttributesResponse{}

	fs.mu.RLock()
	defer fs.mu.RUnlock()

	// Find the inode.
	in := fs.inodes[req.Inode]

	// Grab its attributes.
	switch typed := in.(type) {
	case *inode.DirInode:
		resp.Attributes, err = fs.getAttributes(ctx, typed)
		if err != nil {
			err = fmt.Errorf("DirInode.Attributes: %v", err)
			return
		}

	default:
		panic(
			fmt.Sprintf(
				"Unknown inode type for ID %v: %v",
				req.Inode,
				reflect.TypeOf(in)))
	}

	return
}

func (fs *fileSystem) OpenDir(
	ctx context.Context,
	req *fuse.OpenDirRequest) (resp *fuse.OpenDirResponse, err error) {
	resp = &fuse.OpenDirResponse{}

	fs.mu.Lock()
	defer fs.mu.Unlock()

	// Make sure the inode still exists and is a directory. If not, something has
	// screwed up because the VFS layer shouldn't have let us forget the inode
	// before opening it.
	in := fs.getDirForReadingOrDie(req.Inode)
	defer in.Mu.RUnlock()

	// Allocate a handle.
	handleID := fs.nextHandleID
	fs.nextHandleID++

	fs.handles[handleID] = newDirHandle(in)
	resp.Handle = handleID

	return
}

func (fs *fileSystem) ReadDir(
	ctx context.Context,
	req *fuse.ReadDirRequest) (resp *fuse.ReadDirResponse, err error) {
	fs.mu.RLock()
	defer fs.mu.RUnlock()

	// Find the handle.
	dh := fs.handles[req.Handle].(*dirHandle)
	dh.Mu.Lock()
	defer dh.Mu.Unlock()

	// Serve the request.
	resp, err = dh.ReadDir(ctx, req)

	return
}

func (fs *fileSystem) ReleaseDirHandle(
	ctx context.Context,
	req *fuse.ReleaseDirHandleRequest) (
	resp *fuse.ReleaseDirHandleResponse, err error) {
	resp = &fuse.ReleaseDirHandleResponse{}

	fs.mu.Lock()
	defer fs.mu.Unlock()

	// Sanity check that this handle exists and is of the correct type.
	_ = fs.handles[req.Handle].(*dirHandle)

	// Clear the entry from the map.
	delete(fs.handles, req.Handle)

	return
}
<|endoftext|>


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

package openweathermap

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"strings"
)

// CurrentWeatherData struct contains an aggregate view of the structs
// defined above for JSON to be unmarshaled into.
type CurrentWeatherData struct {
	GeoPos  Coordinates        `json:"coord"`
	Sys     Sys                `json:"sys"`
	Base    string             `json:"base"`
	Weather []Weather          `json:"weather"`
	Main    Main               `json:"main"`
	Wind    Wind               `json:"wind"`
	Clouds  Clouds             `json:"clouds"`
	Rain    map[string]float64 `json:"rain"`
	Snow    map[string]float64 `json:"snow"`
	Dt      int                `json:"dt"`
	ID      int                `json:"id"`
	Name    string             `json:"name"`
	Cod     int                `json:"cod"`
	Unit    string
	Lang    string
	Key     string
}

// NewCurrent returns a new CurrentWeatherData pointer with the supplied parameters
func NewCurrent(unit, lang string) (*CurrentWeatherData, error) {
	unitChoice := strings.ToUpper(unit)
	langChoice := strings.ToUpper(lang)

	c := &CurrentWeatherData{}

	if ValidDataUnit(unitChoice) {
		c.Unit = DataUnits[unitChoice]
	} else {
		return nil, errUnitUnavailable
	}

	if ValidLangCode(langChoice) {
		c.Lang = langChoice
	} else {
		return nil, errLangUnavailable
	}

	c.Key = getKey()

	return c, nil
}

// SetLang allows you to set the language responses will be displayed as.  This isn't part of the
// NewCurrent call because it'd keep it easier to go with API defaults and
// adjust if explicitly called.
func (w *CurrentWeatherData) SetLang(lang string) error {
	if !ValidLangCode(lang) {
		return errLangUnavailable
	}
	w.Lang = lang

	return nil
}

// CurrentByName will provide the current weather with the provided
// location name.
func (w *CurrentWeatherData) CurrentByName(location string) error {
	var err error
	var response *http.Response

	response, err = http.Get(fmt.Sprintf(fmt.Sprintf(baseURL, "appid=%s&q=%s&units=%s&lang=%s"), w.Key, url.QueryEscape(location), w.Unit, w.Lang))
	if err != nil {
		return err
	}
	defer response.Body.Close()

	if err := json.NewDecoder(response.Body).Decode(&w); err != nil {
		return err
	}

	return nil
}

// CurrentByCoordinates will provide the current weather with the
// provided location coordinates.
func (w *CurrentWeatherData) CurrentByCoordinates(location *Coordinates) error {
	response, err := http.Get(fmt.Sprintf(fmt.Sprintf(baseURL, "appid=%s&lat=%f&lon=%f&units=%s&lang=%s"), w.Key, location.Latitude, location.Longitude, w.Unit, w.Lang))
	if err != nil {
		return err
	}
	defer response.Body.Close()

	if err = json.NewDecoder(response.Body).Decode(&w); err != nil {
		return err
	}

	return nil
}

// CurrentByID will provide the current weather with the
// provided location ID.
func (w *CurrentWeatherData) CurrentByID(id int) error {
	response, err := http.Get(fmt.Sprintf(fmt.Sprintf(baseURL, "appid=%s&id=%d&units=%s&lang=%s"), w.Key, id, w.Unit, w.Lang))
	if err != nil {
		return err
	}
	defer response.Body.Close()

	if err = json.NewDecoder(response.Body).Decode(&w); err != nil {
		return err
	}

	return nil
}

// CurrentByZip will provide the current weather for the
// provided zip code.
func (w *CurrentWeatherData) CurrentByZip(zip int, countryCode string) error {
	response, err := http.Get(fmt.Sprintf(fmt.Sprintf(baseURL, "appid=%s&zip=%d,%s&units=%s&lang=%s"), w.Key, zip, countryCode, w.Unit, w.Lang))
	if err != nil {
		return err
	}
	defer response.Body.Close()

	if err = json.NewDecoder(response.Body).Decode(&w); err != nil {
		return err
	}

	return nil
}

// CurrentByArea will provide the current weather for the
// provided area.
func (w *CurrentWeatherData) CurrentByArea() {}
<commit_msg>removed unused function<commit_after>// Copyright 2015 Brian J. Downs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package openweathermap

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"strings"
)

// CurrentWeatherData struct contains an aggregate view of the structs
// defined above for JSON to be unmarshaled into.
type CurrentWeatherData struct {
	GeoPos  Coordinates        `json:"coord"`
	Sys     Sys                `json:"sys"`
	Base    string             `json:"base"`
	Weather []Weather          `json:"weather"`
	Main    Main               `json:"main"`
	Wind    Wind               `json:"wind"`
	Clouds  Clouds             `json:"clouds"`
	Rain    map[string]float64 `json:"rain"`
	Snow    map[string]float64 `json:"snow"`
	Dt      int                `json:"dt"`
	ID      int                `json:"id"`
	Name    string             `json:"name"`
	Cod     int                `json:"cod"`
	Unit    string
	Lang    string
	Key     string
}

// NewCurrent returns a new CurrentWeatherData pointer with the supplied parameters
func NewCurrent(unit, lang string) (*CurrentWeatherData, error) {
	unitChoice := strings.ToUpper(unit)
	langChoice := strings.ToUpper(lang)

	c := &CurrentWeatherData{}

	if ValidDataUnit(unitChoice) {
		c.Unit = DataUnits[unitChoice]
	} else {
		return nil, errUnitUnavailable
	}

	if ValidLangCode(langChoice) {
		c.Lang = langChoice
	} else {
		return nil, errLangUnavailable
	}

	c.Key = getKey()

	return c, nil
}

// CurrentByName will provide the current weather with the provided
// location name.
func (w *CurrentWeatherData) CurrentByName(location string) error {
	var err error
	var response *http.Response

	response, err = http.Get(fmt.Sprintf(fmt.Sprintf(baseURL, "appid=%s&q=%s&units=%s&lang=%s"), w.Key, url.QueryEscape(location), w.Unit, w.Lang))
	if err != nil {
		return err
	}
	defer response.Body.Close()

	if err := json.NewDecoder(response.Body).Decode(&w); err != nil {
		return err
	}

	return nil
}

// CurrentByCoordinates will provide the current weather with the
// provided location coordinates.
func (w *CurrentWeatherData) CurrentByCoordinates(location *Coordinates) error {
	response, err := http.Get(fmt.Sprintf(fmt.Sprintf(baseURL, "appid=%s&lat=%f&lon=%f&units=%s&lang=%s"), w.Key, location.Latitude, location.Longitude, w.Unit, w.Lang))
	if err != nil {
		return err
	}
	defer response.Body.Close()

	if err = json.NewDecoder(response.Body).Decode(&w); err != nil {
		return err
	}

	return nil
}

// CurrentByID will provide the current weather with the
// provided location ID.
func (w *CurrentWeatherData) CurrentByID(id int) error {
	response, err := http.Get(fmt.Sprintf(fmt.Sprintf(baseURL, "appid=%s&id=%d&units=%s&lang=%s"), w.Key, id, w.Unit, w.Lang))
	if err != nil {
		return err
	}
	defer response.Body.Close()

	if err = json.NewDecoder(response.Body).Decode(&w); err != nil {
		return err
	}

	return nil
}

// CurrentByZip will provide the current weather for the
// provided zip code.
func (w *CurrentWeatherData) CurrentByZip(zip int, countryCode string) error {
	response, err := http.Get(fmt.Sprintf(fmt.Sprintf(baseURL, "appid=%s&zip=%d,%s&units=%s&lang=%s"), w.Key, zip, countryCode, w.Unit, w.Lang))
	if err != nil {
		return err
	}
	defer response.Body.Close()

	if err = json.NewDecoder(response.Body).Decode(&w); err != nil {
		return err
	}

	return nil
}

// CurrentByArea will provide the current weather for the
// provided area.
func (w *CurrentWeatherData) CurrentByArea() {}
<|endoftext|>


<commit_before>package webserver

// Copyright (c) 2020, Mitchell Cooper

import (
	"encoding/json"
	"fmt"
	"html"
	"html/template"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"github.com/cooper/quiki/wikifier"
)

var templateDirs string
var templates = make(map[string]wikiTemplate)

var templateFuncs = map[string]interface{}{
	"even": func(i int) bool {
		return i%2 == 0
	},
	"odd": func(i int) bool {
		return i%2 != 0
	},
}

type wikiTemplate struct {
	path       string             // template directory path
	template   *template.Template // master HTML template
	staticPath string             // static file directory path, if any
	staticRoot string             // static file directory HTTP root, if any
	manifest   struct {

		// human-readable template name
		// Name   string

		// template author's name
		// Author string

		// URL to template code on the web, such as GitHub repository
		// Code   string

		// wiki logo info
		Logo struct {

			// ideally one of these dimensions will be specified and the other
			// not. used for the logo specified by the wiki 'logo' directive.
			// usually the height is specified. if both are present, the
			// logo will be generated in those exact dimensions.
			Height int
			Width  int
		}
	}
}

// search all template directories for a template by its name
func findTemplate(name string) (wikiTemplate, error) {

	// template is already cached
	if t, ok := templates[name]; ok {
		return t, nil
	}

	for _, templateDir := range strings.Split(templateDirs, ",") {
		templatePath := filepath.Join(templateDir, name)
		t, err := loadTemplate(name, templatePath)

		// an error occurred in loading the template
		if err != nil {
			return t, err
		}

		// no template but no error means try the next directory
		if t.template == nil {
			continue
		}

		return t, nil
	}

	// never found a template
	return wikiTemplate{}, fmt.Errorf("unable to find template '%s' in any of %v", name, templateDirs)
}

// load a template from its known path
func loadTemplate(name, templatePath string) (wikiTemplate, error) {
	var t wikiTemplate
	var tryNextDirectory bool

	// template is already cached
	if t, ok := templates[name]; ok {
		return t, nil
	}

	// parse HTML templates
	tmpl := template.New("")
	err := filepath.Walk(templatePath, func(filePath string, info os.FileInfo, err error) error {

		// walk error, probably missing template
		if err != nil {
			tryNextDirectory = true
			return err
		}

		// found template file
		if strings.HasSuffix(filePath, ".tpl") {

			// error in parsing
			subTmpl, err := tmpl.ParseFiles(filePath)
			if err != nil {
				return err
			}

			// add funcs
			subTmpl.Funcs(templateFuncs)
		}

		// found static content directory
		if info.IsDir() && info.Name() == "static" {
			t.staticPath = filePath
			t.staticRoot = "/tmpl/" + name
			fileServer := http.FileServer(http.Dir(filePath))
			pfx := t.staticRoot + "/"
			Mux.Handle(pfx, http.StripPrefix(pfx, fileServer))
			log.Printf("[%s] template registered: %s", name, pfx)
		}

		// found manifest
		if info.Name() == "manifest.json" {

			// couldn't read manifest
			contents, err := ioutil.ReadFile(filePath)
			if err != nil {
				return err
			}

			// couldn't parse manifest
			if err := json.Unmarshal(contents, &t.manifest); err != nil {
				return err
			}
		}

		return err
	})

	// not found
	if tryNextDirectory {
		return t, nil
	}

	// other error
	if err != nil {
		return t, err
	}

	// cache the template
	t.path = templatePath
	t.template = tmpl
	templates[name] = t

	return t, nil
}

type wikiPage struct {
	File        string                       // page name, with extension
	Name        string                       // page name, without extension
	WholeTitle  string                       // optional, shown in <title> as-is
	Title       string                       // page title
	Description string                       // page description
	Keywords    []string                     // page keywords
	WikiTitle   string                       // wiki titled
	WikiLogo    string                       // path to wiki logo image (deprecated, use Logo)
	WikiRoot    string                       // wiki HTTP root (deprecated, use Root.Wiki)
	Root        wikifier.PageOptRoot         // all roots
	StaticRoot  string                       // path to static resources
	Pages       []wikiPage                   // more pages for category posts
	Message     string                       // message for error page
	Navigation  []wikifier.PageOptNavigation // slice of nav items
	PageN       int                          // for category posts, the page number (first page = 1)
	NumPages    int                          // for category posts, the number of pages
	PageCSS     template.CSS                 // css
	HTMLContent template.HTML                // html
	retina      []int                        // retina scales for logo
}

func (p wikiPage) VisibleTitle() string {
	if p.WholeTitle != "" {
		return p.WholeTitle
	}
	if p.Title == p.WikiTitle || p.Title == "" {
		return p.WikiTitle
	}
	return p.Title + " - " + p.WikiTitle
}

func (p wikiPage) Scripts() []string {
	return []string{
		"/static/mootools.min.js",
		"/static/quiki.js",
		"https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js",
	}
}

// for category posts, the page numbers available.
// if there is only one page, this is nothing
func (p wikiPage) PageNumbers() []int {
	if p.NumPages == 1 {
		return nil
	}
	numbers := make([]int, p.NumPages)
	for i := 1; i <= p.NumPages; i++ {
		numbers[i-1] = i
	}
	return numbers
}

func (p wikiPage) Logo() template.HTML {
	if p.WikiLogo == "" {
		return template.HTML("")
	}
	h := `<img alt="` + html.EscapeString(p.WikiTitle) + `" src="` + p.WikiLogo + `"`

	// retina
	if len(p.retina) != 0 {
		h += ` srcset="` + wikifier.ScaleString(p.WikiLogo, p.retina) + `"`
	}

	h += ` />`
	return template.HTML(h)
}
<commit_msg>wikiPage KeywordString<commit_after>package webserver

// Copyright (c) 2020, Mitchell Cooper

import (
	"encoding/json"
	"fmt"
	"html"
	"html/template"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"github.com/cooper/quiki/wikifier"
)

var templateDirs string
var templates = make(map[string]wikiTemplate)

var templateFuncs = map[string]interface{}{
	"even": func(i int) bool {
		return i%2 == 0
	},
	"odd": func(i int) bool {
		return i%2 != 0
	},
}

type wikiTemplate struct {
	path       string             // template directory path
	template   *template.Template // master HTML template
	staticPath string             // static file directory path, if any
	staticRoot string             // static file directory HTTP root, if any
	manifest   struct {

		// human-readable template name
		// Name   string

		// template author's name
		// Author string

		// URL to template code on the web, such as GitHub repository
		// Code   string

		// wiki logo info
		Logo struct {

			// ideally one of these dimensions will be specified and the other
			// not. used for the logo specified by the wiki 'logo' directive.
			// usually the height is specified. if both are present, the
			// logo will be generated in those exact dimensions.
			Height int
			Width  int
		}
	}
}

// search all template directories for a template by its name
func findTemplate(name string) (wikiTemplate, error) {

	// template is already cached
	if t, ok := templates[name]; ok {
		return t, nil
	}

	for _, templateDir := range strings.Split(templateDirs, ",") {
		templatePath := filepath.Join(templateDir, name)
		t, err := loadTemplate(name, templatePath)

		// an error occurred in loading the template
		if err != nil {
			return t, err
		}

		// no template but no error means try the next directory
		if t.template == nil {
			continue
		}

		return t, nil
	}

	// never found a template
	return wikiTemplate{}, fmt.Errorf("unable to find template '%s' in any of %v", name, templateDirs)
}

// load a template from its known path
func loadTemplate(name, templatePath string) (wikiTemplate, error) {
	var t wikiTemplate
	var tryNextDirectory bool

	// template is already cached
	if t, ok := templates[name]; ok {
		return t, nil
	}

	// parse HTML templates
	tmpl := template.New("")
	err := filepath.Walk(templatePath, func(filePath string, info os.FileInfo, err error) error {

		// walk error, probably missing template
		if err != nil {
			tryNextDirectory = true
			return err
		}

		// found template file
		if strings.HasSuffix(filePath, ".tpl") {

			// error in parsing
			subTmpl, err := tmpl.ParseFiles(filePath)
			if err != nil {
				return err
			}

			// add funcs
			subTmpl.Funcs(templateFuncs)
		}

		// found static content directory
		if info.IsDir() && info.Name() == "static" {
			t.staticPath = filePath
			t.staticRoot = "/tmpl/" + name
			fileServer := http.FileServer(http.Dir(filePath))
			pfx := t.staticRoot + "/"
			Mux.Handle(pfx, http.StripPrefix(pfx, fileServer))
			log.Printf("[%s] template registered: %s", name, pfx)
		}

		// found manifest
		if info.Name() == "manifest.json" {

			// couldn't read manifest
			contents, err := ioutil.ReadFile(filePath)
			if err != nil {
				return err
			}

			// couldn't parse manifest
			if err := json.Unmarshal(contents, &t.manifest); err != nil {
				return err
			}
		}

		return err
	})

	// not found
	if tryNextDirectory {
		return t, nil
	}

	// other error
	if err != nil {
		return t, err
	}

	// cache the template
	t.path = templatePath
	t.template = tmpl
	templates[name] = t

	return t, nil
}

type wikiPage struct {
	File        string                       // page name, with extension
	Name        string                       // page name, without extension
	WholeTitle  string                       // optional, shown in <title> as-is
	Title       string                       // page title
	Description string                       // page description
	Keywords    []string                     // page keywords
	WikiTitle   string                       // wiki titled
	WikiLogo    string                       // path to wiki logo image (deprecated, use Logo)
	WikiRoot    string                       // wiki HTTP root (deprecated, use Root.Wiki)
	Root        wikifier.PageOptRoot         // all roots
	StaticRoot  string                       // path to static resources
	Pages       []wikiPage                   // more pages for category posts
	Message     string                       // message for error page
	Navigation  []wikifier.PageOptNavigation // slice of nav items
	PageN       int                          // for category posts, the page number (first page = 1)
	NumPages    int                          // for category posts, the number of pages
	PageCSS     template.CSS                 // css
	HTMLContent template.HTML                // html
	retina      []int                        // retina scales for logo
}

func (p wikiPage) VisibleTitle() string {
	if p.WholeTitle != "" {
		return p.WholeTitle
	}
	if p.Title == p.WikiTitle || p.Title == "" {
		return p.WikiTitle
	}
	return p.Title + " - " + p.WikiTitle
}

func (p wikiPage) Scripts() []string {
	return []string{
		"/static/mootools.min.js",
		"/static/quiki.js",
		"https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js",
	}
}

// for category posts, the page numbers available.
// if there is only one page, this is nothing
func (p wikiPage) PageNumbers() []int {
	if p.NumPages == 1 {
		return nil
	}
	numbers := make([]int, p.NumPages)
	for i := 1; i <= p.NumPages; i++ {
		numbers[i-1] = i
	}
	return numbers
}

func (p wikiPage) Logo() template.HTML {
	if p.WikiLogo == "" {
		return template.HTML("")
	}
	h := `<img alt="` + html.EscapeString(p.WikiTitle) + `" src="` + p.WikiLogo + `"`

	// retina
	if len(p.retina) != 0 {
		h += ` srcset="` + wikifier.ScaleString(p.WikiLogo, p.retina) + `"`
	}

	h += ` />`
	return template.HTML(h)
}

func (p wikiPage) KeywordString() string {
	return strings.Join(p.Keywords, " ,")
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/Masterminds/glide/cmd"

	"github.com/Masterminds/cookoo"
	"github.com/Masterminds/cookoo/cli"

	"flag"
	"fmt"
	"os"
)

var version string = "DEV"

const Summary = "Manage Go projects with ease."
const Usage = `Manage dependencies, naming, and GOPATH for your Go projects.

Examples:
	$ glide create
	$ glide in
	$ glide install
	$ glide update
	$ glide rebuild

COMMANDS
========

Utilities:

- help: Show this help message (alias of -h)
- status: Print a status report.
- version: Print the version and exit.

Dependency management:

- create: Initialize a new project, creating a template glide.yaml.
- install: Install all packages in the glide.yaml.
- update: Update existing packages (alias: 'up').
- rebuild: Rebuild ('go build') the dependencies.

Project tools:

- in: Glide into a commandline shell preconfigured for your project (with
  GOPATH set).
- into: "glide into /my/project" is the same as running "cd /my/project && glide in"
- gopath: Emits the GOPATH for the current project. Useful for things like
  manually setting GOPATH: GOPATH=$(glide gopath)

Importing:

- godeps: Import Godeps and Godeps-Git files and display the would-be yaml file.

FILES
=====

Each project should have a 'glide.yaml' file in the project directory. Files
look something like this:

	package: github.com/Masterminds/glide
	imports:
		- package: github.com/Masterminds/cookoo
		  vcs: git
		  ref: 1.1.0
		  subpackages: **
  		- package: github.com/kylelemons/go-gypsy
		  subpackages: yaml
`

func main() {
	reg, router, cxt := cookoo.Cookoo()

	routes(reg, cxt)

	if err := router.HandleRequest("@startup", cxt, false); err != nil {
		fmt.Printf("Oops! %s\n", err)
		os.Exit(1)
	}

}

func routes(reg *cookoo.Registry, cxt cookoo.Context) {

	flags := flag.NewFlagSet("global", flag.PanicOnError)
	flags.Bool("h", false, "Print help text.")
	flags.Bool("q", false, "Quiet (no info or debug messages)")
	flags.String("yaml", "glide.yaml", "Set a YAML configuration file.")

	cxt.Put("os.Args", os.Args)

	reg.Route("@startup", "Parse args and send to the right subcommand.").
		Does(cli.ShiftArgs, "_").Using("n").WithDefault(1).
		Does(cli.ParseArgs, "remainingArgs").
		Using("flagset").WithDefault(flags).
		Using("args").From("cxt:os.Args").
		Does(cli.ShowHelp, "help").
		Using("show").From("cxt:h cxt:help").
		Using("summary").WithDefault(Summary).
		Using("usage").WithDefault(Usage).
		Using("flags").WithDefault(flags).
		Does(cmd.BeQuiet, "quiet").
		Using("quiet").From("cxt:q").
		Does(cli.RunSubcommand, "subcommand").
		Using("default").WithDefault("help").
		Using("offset").WithDefault(0).
		Using("args").From("cxt:remainingArgs")

	reg.Route("@ready", "Prepare for glide commands.").
		Does(cmd.ReadyToGlide, "ready").
		Does(cmd.ParseYaml, "cfg").Using("filename").From("cxt:yaml")

	reg.Route("help", "Print help.").
		Does(cli.ShowHelp, "help").
		Using("show").WithDefault(true).
		Using("summary").WithDefault(Summary).
		Using("usage").WithDefault(Usage).
		Using("flags").WithDefault(flags)

	reg.Route("version", "Print the version and exit.").Does(showVersion, "_")

	reg.Route("into", "Creates a new Glide shell.").
		Does(cmd.AlreadyGliding, "isGliding").
		Does(cli.ShiftArgs, "toPath").Using("n").WithDefault(2).
		Does(cmd.Into, "in").Using("into").From("cxt:toPath").
		Using("into").WithDefault("").From("cxt:toPath").
		Includes("@ready")

	reg.Route("in", "Set GOPATH and supporting env vars.").
		Does(cmd.AlreadyGliding, "isGliding").
		Includes("@ready").
		//Does(cli.ShiftArgs, "toPath").Using("n").WithDefault(1).
		Does(cmd.Into, "in").
		Using("into").WithDefault("").From("cxt:toPath").
		Using("conf").From("cxt:cfg")

	reg.Route("gopath", "Return the GOPATH for the present project.").
		Does(cmd.In, "gopath")

	reg.Route("out", "Set GOPATH back to former val.").
		Does(cmd.Out, "gopath")

	reg.Route("install", "Install dependencies.").
		Includes("@ready").
		Does(cmd.Mkdir, "dir").Using("dir").WithDefault("_vendor").
		Does(cmd.LinkPackage, "alias").
		Does(cmd.GetImports, "dependencies").Using("conf").From("cxt:cfg").
		Does(cmd.SetReference, "version").Using("conf").From("cxt:cfg").
		Does(cmd.Rebuild, "rebuild").Using("conf").From("cxt:cfg")

	reg.Route("up", "Update dependencies (alias of 'update')").
		Does(cookoo.ForwardTo, "fwd").Using("route").WithDefault("update")

	reg.Route("update", "Update dependencies.").
		Includes("@ready").
		Does(cmd.CowardMode, "_").
		Does(cmd.UpdateImports, "dependencies").Using("conf").From("cxt:cfg").
		Does(cmd.SetReference, "version").Using("conf").From("cxt:cfg").
		Does(cmd.Rebuild, "rebuild").Using("conf").From("cxt:cfg")

	reg.Route("rebuild", "Rebuild dependencies").
		Includes("@ready").
		Does(cmd.CowardMode, "_").
		Does(cmd.Rebuild, "rebuild").Using("conf").From("cxt:cfg")

	reg.Route("pin", "Print a YAML file with all of the packages pinned to the current version.").
		Includes("@ready").
		Does(cmd.UpdateReferences, "refs").Using("conf").From("cxt:cfg").
		Does(cmd.MergeToYaml, "merged").Using("conf").From("cxt:cfg").
		Does(cmd.WriteYaml, "out").Using("yaml.Node").From("cxt:merged")

	reg.Route("godeps", "Read a Godeps file").
		Includes("@ready").
		Does(cmd.Godeps, "godeps").
		Does(cmd.AddDependencies, "addGodeps").
		Using("dependencies").From("cxt:godeps").
		Using("conf").From("cxt:cfg").
		Does(cmd.GodepsGit, "godepsGit").
		Does(cmd.AddDependencies, "addGodepsGit").
		Using("dependencies").From("cxt:godepsGit").
		Using("conf").From("cxt:cfg").
		// Does(cmd.UpdateReferences, "refs").Using("conf").From("cxt:cfg").
		Does(cmd.MergeToYaml, "merged").Using("conf").From("cxt:cfg").
		Does(cmd.WriteYaml, "out").Using("yaml.Node").From("cxt:merged")

	reg.Route("init", "Initialize Glide (deprecated; use 'create'").
		Does(cookoo.ForwardTo, "fwd").Using("route").WithDefault("create")

	reg.Route("create", "Initialize Glide").
		Does(cmd.InitGlide, "init")

	reg.Route("status", "Status").
		Does(cmd.Status, "status")

	reg.Route("@plugin", "Try to send to a plugin.").
		Includes("@ready").
		Does(cmd.DropToShell, "plugin")
}

func showVersion(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
	fmt.Println(version)
	return version, nil
}
<commit_msg>Added a package comment so that details show up in godoc.<commit_after>// Glide is a command line utility that manages Go project dependencies and
// your GOPATH.
//
// Dependencies are managed via a glide.yaml in the root of a project. The yaml
// file lets you specify projects, versions (tags, branches, or references),
// and even alias one location in as other one. Aliasing is useful when supporting
// forks without needing to rewrite the imports in a codebase.
//
// A glide.yaml file looks like:
//
//   	package: github.com/Masterminds/glide
// 		imports:
//	 		- package: github.com/Masterminds/cookoo
//			  vcs: git
//			  ref: 1.1.0
// 	  		  subpackages: **
//  		- package: github.com/kylelemons/go-gypsy
// 	  		  subpackages: yaml
//
// Glide puts dependencies in a _vendor directory. Go utilities require this to
// be in your GOPATH. Glide makes this easy. Use the `glide in` command to enter
// a shell (your default) with the GOPATH set to the projects _vendor directory.
// To leave this shell simply exit it.
//
// If your .bashrc, .zshrc, or other startup shell sets your GOPATH you many need
// to optionally set it using something like:
//
//		if [ "" = "${GOPATH}" ]; then
//		  export GOPATH="/some/dir"
//		fi
//
// For more information use the `glide help` command or see https://github.com/Masterminds/glide
package main

import (
	"github.com/Masterminds/glide/cmd"

	"github.com/Masterminds/cookoo"
	"github.com/Masterminds/cookoo/cli"

	"flag"
	"fmt"
	"os"
)

var version string = "DEV"

const Summary = "Manage Go projects with ease."
const Usage = `Manage dependencies, naming, and GOPATH for your Go projects.

Examples:
	$ glide create
	$ glide in
	$ glide install
	$ glide update
	$ glide rebuild

COMMANDS
========

Utilities:

- help: Show this help message (alias of -h)
- status: Print a status report.
- version: Print the version and exit.

Dependency management:

- create: Initialize a new project, creating a template glide.yaml.
- install: Install all packages in the glide.yaml.
- update: Update existing packages (alias: 'up').
- rebuild: Rebuild ('go build') the dependencies.

Project tools:

- in: Glide into a commandline shell preconfigured for your project (with
  GOPATH set).
- into: "glide into /my/project" is the same as running "cd /my/project && glide in"
- gopath: Emits the GOPATH for the current project. Useful for things like
  manually setting GOPATH: GOPATH=$(glide gopath)

Importing:

- godeps: Import Godeps and Godeps-Git files and display the would-be yaml file.

FILES
=====

Each project should have a 'glide.yaml' file in the project directory. Files
look something like this:

	package: github.com/Masterminds/glide
	imports:
		- package: github.com/Masterminds/cookoo
		  vcs: git
		  ref: 1.1.0
		  subpackages: **
  		- package: github.com/kylelemons/go-gypsy
		  subpackages: yaml
`

func main() {
	reg, router, cxt := cookoo.Cookoo()

	routes(reg, cxt)

	if err := router.HandleRequest("@startup", cxt, false); err != nil {
		fmt.Printf("Oops! %s\n", err)
		os.Exit(1)
	}

}

func routes(reg *cookoo.Registry, cxt cookoo.Context) {

	flags := flag.NewFlagSet("global", flag.PanicOnError)
	flags.Bool("h", false, "Print help text.")
	flags.Bool("q", false, "Quiet (no info or debug messages)")
	flags.String("yaml", "glide.yaml", "Set a YAML configuration file.")

	cxt.Put("os.Args", os.Args)

	reg.Route("@startup", "Parse args and send to the right subcommand.").
		Does(cli.ShiftArgs, "_").Using("n").WithDefault(1).
		Does(cli.ParseArgs, "remainingArgs").
		Using("flagset").WithDefault(flags).
		Using("args").From("cxt:os.Args").
		Does(cli.ShowHelp, "help").
		Using("show").From("cxt:h cxt:help").
		Using("summary").WithDefault(Summary).
		Using("usage").WithDefault(Usage).
		Using("flags").WithDefault(flags).
		Does(cmd.BeQuiet, "quiet").
		Using("quiet").From("cxt:q").
		Does(cli.RunSubcommand, "subcommand").
		Using("default").WithDefault("help").
		Using("offset").WithDefault(0).
		Using("args").From("cxt:remainingArgs")

	reg.Route("@ready", "Prepare for glide commands.").
		Does(cmd.ReadyToGlide, "ready").
		Does(cmd.ParseYaml, "cfg").Using("filename").From("cxt:yaml")

	reg.Route("help", "Print help.").
		Does(cli.ShowHelp, "help").
		Using("show").WithDefault(true).
		Using("summary").WithDefault(Summary).
		Using("usage").WithDefault(Usage).
		Using("flags").WithDefault(flags)

	reg.Route("version", "Print the version and exit.").Does(showVersion, "_")

	reg.Route("into", "Creates a new Glide shell.").
		Does(cmd.AlreadyGliding, "isGliding").
		Does(cli.ShiftArgs, "toPath").Using("n").WithDefault(2).
		Does(cmd.Into, "in").Using("into").From("cxt:toPath").
		Using("into").WithDefault("").From("cxt:toPath").
		Includes("@ready")

	reg.Route("in", "Set GOPATH and supporting env vars.").
		Does(cmd.AlreadyGliding, "isGliding").
		Includes("@ready").
		//Does(cli.ShiftArgs, "toPath").Using("n").WithDefault(1).
		Does(cmd.Into, "in").
		Using("into").WithDefault("").From("cxt:toPath").
		Using("conf").From("cxt:cfg")

	reg.Route("gopath", "Return the GOPATH for the present project.").
		Does(cmd.In, "gopath")

	reg.Route("out", "Set GOPATH back to former val.").
		Does(cmd.Out, "gopath")

	reg.Route("install", "Install dependencies.").
		Includes("@ready").
		Does(cmd.Mkdir, "dir").Using("dir").WithDefault("_vendor").
		Does(cmd.LinkPackage, "alias").
		Does(cmd.GetImports, "dependencies").Using("conf").From("cxt:cfg").
		Does(cmd.SetReference, "version").Using("conf").From("cxt:cfg").
		Does(cmd.Rebuild, "rebuild").Using("conf").From("cxt:cfg")

	reg.Route("up", "Update dependencies (alias of 'update')").
		Does(cookoo.ForwardTo, "fwd").Using("route").WithDefault("update")

	reg.Route("update", "Update dependencies.").
		Includes("@ready").
		Does(cmd.CowardMode, "_").
		Does(cmd.UpdateImports, "dependencies").Using("conf").From("cxt:cfg").
		Does(cmd.SetReference, "version").Using("conf").From("cxt:cfg").
		Does(cmd.Rebuild, "rebuild").Using("conf").From("cxt:cfg")

	reg.Route("rebuild", "Rebuild dependencies").
		Includes("@ready").
		Does(cmd.CowardMode, "_").
		Does(cmd.Rebuild, "rebuild").Using("conf").From("cxt:cfg")

	reg.Route("pin", "Print a YAML file with all of the packages pinned to the current version.").
		Includes("@ready").
		Does(cmd.UpdateReferences, "refs").Using("conf").From("cxt:cfg").
		Does(cmd.MergeToYaml, "merged").Using("conf").From("cxt:cfg").
		Does(cmd.WriteYaml, "out").Using("yaml.Node").From("cxt:merged")

	reg.Route("godeps", "Read a Godeps file").
		Includes("@ready").
		Does(cmd.Godeps, "godeps").
		Does(cmd.AddDependencies, "addGodeps").
		Using("dependencies").From("cxt:godeps").
		Using("conf").From("cxt:cfg").
		Does(cmd.GodepsGit, "godepsGit").
		Does(cmd.AddDependencies, "addGodepsGit").
		Using("dependencies").From("cxt:godepsGit").
		Using("conf").From("cxt:cfg").
		// Does(cmd.UpdateReferences, "refs").Using("conf").From("cxt:cfg").
		Does(cmd.MergeToYaml, "merged").Using("conf").From("cxt:cfg").
		Does(cmd.WriteYaml, "out").Using("yaml.Node").From("cxt:merged")

	reg.Route("init", "Initialize Glide (deprecated; use 'create'").
		Does(cookoo.ForwardTo, "fwd").Using("route").WithDefault("create")

	reg.Route("create", "Initialize Glide").
		Does(cmd.InitGlide, "init")

	reg.Route("status", "Status").
		Does(cmd.Status, "status")

	reg.Route("@plugin", "Try to send to a plugin.").
		Includes("@ready").
		Does(cmd.DropToShell, "plugin")
}

func showVersion(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
	fmt.Println(version)
	return version, nil
}
<|endoftext|>


<commit_before>package apps

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gexec"

	"github.com/cloudfoundry-incubator/cf-test-helpers/cf"

	"strings"
)

var _ = Describe("Cloud Controller UAA connectivity", func() {
	It("User added to organization by username", func() {
		cf.AsUser(context.AdminUserContext(), DEFAULT_TIMEOUT, func() {
			orgGuid := cf.Cf("org", context.RegularUserContext().Org, "--guid").Wait(DEFAULT_TIMEOUT).Out.Contents()
			jsonBody := "{\"username\": \"" + strings.TrimSpace(context.RegularUserContext().Username) + "\"}"
			Expect(cf.Cf("curl", "/v2/organizations/"+strings.TrimSpace(string(orgGuid))+"/managers", "-X", "PUT", "-d", jsonBody).Wait(CF_PUSH_TIMEOUT)).To(Exit(0))
			Expect(cf.Cf("org-users", context.RegularUserContext().Org).Wait(DEFAULT_TIMEOUT).Out.Contents()).To(ContainSubstring(context.RegularUserContext().Username))
		})
	})
})
<commit_msg>Remove cc uaa connectivity test<commit_after><|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"time"
)

var Char struct {
	class, name, race, acct string
	lvl                     int
	seen                    time.Time
}

func ChkErr(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func main() {
	f, err := os.OpenFile("logs/bot.log", os.O_RDWR|os.O_APPEND|os.O_CREATE, 0640)
	defer f.Close()
	ChkErr(err)
	log.SetOutput(f)

	// for who.go WhoChar(char string, lvl int,
	// class string, race string, acct string)
	var char = flag.String("char", "",
		"Character name for update or import. Ex: Rynshana")
	var lvl = flag.Int("lvl", 0,
		"Character level for update or import. Ex: 50")
	var class = flag.String("class", "",
		"Character class for initial import. Ex: \"Cleric\"")
	var race = flag.String("race", "",
		"Character race for initial import. Ex: \"Moon Elf\"")
	var acct = flag.String("acct", "",
		"Character account for initial import. Ex: Krimic")
	// for who.go WhoBatch(ppl string)
	var who = flag.String("who", "",
		"Batched who output. "+
			"Ex: \"[10 Ctr] Rarac  (Orc)|[ 2 War] Xatus  (Troll)\"")
	// for identify.go Identify(filename string)
	var file = flag.String("import", "",
		"Parse file for identify stats, import to DB. Ex: newstats.txt")
	// for time.go Uptime(curup string)
	var time = flag.String("time", "",
		"Parse uptime for boot tracking. Ex: 58:10:26")
	// for local.go glstat
	var glist = flag.String("glist", "",
		"Provide stats for multiple items at once. Ex: \"a longsword|a dagger\"")
	var item = flag.String("item", "",
		"Provide stats for a single item. Ex: \"a longsword\"")
	// for tell.go ReplyTo(char string, tell string)
	var tell = flag.String("tell", "",
		"Tell with command and maybe operant. Ex: \"stat a longsword\"")
	// run database backup, restore, and parsing
	var backup = flag.Bool("bak", false,
		"Backup the toril.db database.")
	var restore = flag.String("res", "",
		"Restore the toril.db database from backup file. Ex: toril.db.gz")
	var stats = flag.Bool("s", false,
		"Run FormatStats() creation for item DB.")

	flag.Parse()

	var cmds []string
	// only run one command at a time
	switch {
	case *time != "":
		Uptime(*time)
	case *who != "":
		cmds = WhoBatch(*who)
	case *char != "" && *tell != "":
		cmds = ReplyTo(*char, *tell)
	case *char != "" && 50 >= *lvl && *lvl > 0 &&
		*class != "" && *race != "" && *acct != "":
		WhoChar(*char, *lvl, *class, *race, *acct)
	case *stats:
		FormatStats()
	case *item != "":
		fmt.Println(FindItem(*item, "short_stats"))
	case *glist != "":
		GlistStats(*glist)
	case *file != "":
		Identify(*file)
	case *backup:
		BackupDB()
	case *restore != "": // this doesn't work on Mac OS X
		RestoreDB(*restore)
	}
	for _, cmd := range cmds {
		fmt.Printf(cmd)
	}
}
<commit_msg>Bug fix on printing cmds with percent signs<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"time"
)

var Char struct {
	class, name, race, acct string
	lvl                     int
	seen                    time.Time
}

func ChkErr(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func main() {
	f, err := os.OpenFile("logs/bot.log", os.O_RDWR|os.O_APPEND|os.O_CREATE, 0640)
	defer f.Close()
	ChkErr(err)
	log.SetOutput(f)

	// for who.go WhoChar(char string, lvl int,
	// class string, race string, acct string)
	var char = flag.String("char", "",
		"Character name for update or import. Ex: Rynshana")
	var lvl = flag.Int("lvl", 0,
		"Character level for update or import. Ex: 50")
	var class = flag.String("class", "",
		"Character class for initial import. Ex: \"Cleric\"")
	var race = flag.String("race", "",
		"Character race for initial import. Ex: \"Moon Elf\"")
	var acct = flag.String("acct", "",
		"Character account for initial import. Ex: Krimic")
	// for who.go WhoBatch(ppl string)
	var who = flag.String("who", "",
		"Batched who output. "+
			"Ex: \"[10 Ctr] Rarac  (Orc)|[ 2 War] Xatus  (Troll)\"")
	// for identify.go Identify(filename string)
	var file = flag.String("import", "",
		"Parse file for identify stats, import to DB. Ex: newstats.txt")
	// for time.go Uptime(curup string)
	var time = flag.String("time", "",
		"Parse uptime for boot tracking. Ex: 58:10:26")
	// for local.go glstat
	var glist = flag.String("glist", "",
		"Provide stats for multiple items at once. Ex: \"a longsword|a dagger\"")
	var item = flag.String("item", "",
		"Provide stats for a single item. Ex: \"a longsword\"")
	// for tell.go ReplyTo(char string, tell string)
	var tell = flag.String("tell", "",
		"Tell with command and maybe operant. Ex: \"stat a longsword\"")
	// run database backup, restore, and parsing
	var backup = flag.Bool("bak", false,
		"Backup the toril.db database.")
	var restore = flag.String("res", "",
		"Restore the toril.db database from backup file. Ex: toril.db.gz")
	var stats = flag.Bool("s", false,
		"Run FormatStats() creation for item DB.")

	flag.Parse()

	var cmds []string
	// only run one command at a time
	switch {
	case *time != "":
		Uptime(*time)
	case *who != "":
		cmds = WhoBatch(*who)
	case *char != "" && *tell != "":
		cmds = ReplyTo(*char, *tell)
	case *char != "" && 50 >= *lvl && *lvl > 0 &&
		*class != "" && *race != "" && *acct != "":
		WhoChar(*char, *lvl, *class, *race, *acct)
	case *stats:
		FormatStats()
	case *item != "":
		fmt.Println(FindItem(*item, "short_stats"))
	case *glist != "":
		GlistStats(*glist)
	case *file != "":
		Identify(*file)
	case *backup:
		BackupDB()
	case *restore != "": // this doesn't work on Mac OS X
		RestoreDB(*restore)
	}
	for _, cmd := range cmds {
		fmt.Print(cmd)
	}
}
<|endoftext|>


<commit_before>package gohex

import (
	"bufio"
	"encoding/hex"
	"strings"
)

type DataSegment struct {
	data    []byte
	address int
}

type Memory struct {
	dataSegments   []DataSegment
	startAddress   int
	currentAddress int
}

func NewMemory() *Memory {
	m := new(Memory)
	return m
}

func (m *Memory) GetStartAddress() int {
	return m.startAddress
}

func (m *Memory) GetDataSegments() []DataSegment {
	return m.dataSegments
}

func (m *Memory) Clear() {
	m.startAddress = 0
	m.currentAddress = 0
	m.dataSegments = []DataSegment{}
}

func (m *Memory) ParseIntelHex(str string) error {
	scanner := bufio.NewScanner(strings.NewReader(str))
	lineNum := 0
	eof := false
	start := false
	for scanner.Scan() {
		lineNum++
		line := scanner.Text()
		if len(line) == 0 {
			continue
		}
		if line[0] != ':' {
			return newParseError(SYNTAX_ERROR, "no colon char on the first line character", lineNum)
		}
		bytes, err := hex.DecodeString(line[1:])
		if err != nil {
			return newParseError(SYNTAX_ERROR, err.Error(), lineNum)
		}
		if len(bytes) < 5 {
			return newParseError(DATA_ERROR, "not enought data bytes", lineNum)
		}

		err = checkSum(bytes)
		if err != nil {
			return newParseError(CHECKSUM_ERROR, err.Error(), lineNum)
		}

		err = checkRecordSize(bytes)
		if err != nil {
			return newParseError(DATA_ERROR, err.Error(), lineNum)
		}

		switch record_type := bytes[3]; record_type {
		case 0:
			//data
			// jesli nie ma segmentu z aktualnym ciągłym adresem to:
			// utworz segment
			// wpisuj dane
			// zwieksz aktualny adres
		case 1:
			//eof
			err = checkEOF(bytes)
			if err != nil {
				return newParseError(RECORD_ERROR, err.Error(), lineNum)
			}
			eof = true
			break
		case 4:
			//extended address
			m.currentAddress, err = getExtendedAddress(bytes)
			if err != nil {
				return newParseError(RECORD_ERROR, err.Error(), lineNum)
			}
		case 5:
			//run address
			if start == true {
				return newParseError(DATA_ERROR, "multiple start address lines", lineNum)
			}
			m.startAddress, err = getStartAddress(bytes)
			if err != nil {
				return newParseError(RECORD_ERROR, err.Error(), lineNum)
			}
			start = true
		}
	}
	if err := scanner.Err(); err != nil {
		return newParseError(SYNTAX_ERROR, err.Error(), lineNum)
	}
	if eof == false {
		return newParseError(DATA_ERROR, "no end of file line", lineNum)
	}

	return nil
}

func (m *Memory) DumpIntelHex() error {
	return nil
}
<commit_msg>refactoring<commit_after>package gohex

import (
	"bufio"
	"encoding/hex"
	"strings"
)

type DataSegment struct {
	data    []byte
	address int
}

type Memory struct {
	dataSegments   []DataSegment
	startAddress   int
	currentAddress int
	eofFlag		   bool
	startFlag	   bool
	lineNum		   int
}

func NewMemory() *Memory {
	m := new(Memory)
	return m
}

func (m *Memory) GetStartAddress() int {
	return m.startAddress
}

func (m *Memory) GetDataSegments() []DataSegment {
	return m.dataSegments
}

func (m *Memory) Clear() {
	m.startAddress = 0
	m.currentAddress = 0
	m.lineNum = 0
	m.dataSegments = []DataSegment{}
	m.startFlag = false
	m.eofFlag = false
}

func (m *Memory) parseIntelHexRecord(bytes []byte) error {
	if len(bytes) < 5 {
		return newParseError(DATA_ERROR, "not enought data bytes", m.lineNum)
	}
	err := checkSum(bytes)
	if err != nil {
		return newParseError(CHECKSUM_ERROR, err.Error(), m.lineNum)
	}
	err = checkRecordSize(bytes)
	if err != nil {
		return newParseError(DATA_ERROR, err.Error(), m.lineNum)
	}
	switch record_type := bytes[3]; record_type {
	case 0:
		//data
		// jesli nie ma segmentu z aktualnym ciągłym adresem to:
		// utworz segment
		// wpisuj dane
		// zwieksz aktualny adres
	case 1:
		//eof
		err = checkEOF(bytes)
		if err != nil {
			return newParseError(RECORD_ERROR, err.Error(), m.lineNum)
		}
		m.eofFlag = true
		break
	case 4:
		//extended address
		m.currentAddress, err = getExtendedAddress(bytes)
		if err != nil {
			return newParseError(RECORD_ERROR, err.Error(), m.lineNum)
		}
	case 5:
		//run address
		if m.startFlag == true {
			return newParseError(DATA_ERROR, "multiple start address lines", m.lineNum)
		}
		m.startAddress, err = getStartAddress(bytes)
		if err != nil {
			return newParseError(RECORD_ERROR, err.Error(), m.lineNum)
		}
		m.startFlag = true
	}
	return nil
}

func (m *Memory) parseIntelHexLine(line string) error {
	if len(line) == 0 {
		return nil
	}
	if line[0] != ':' {
		return newParseError(SYNTAX_ERROR, "no colon char on the first line character", m.lineNum)
	}
	bytes, err := hex.DecodeString(line[1:])
	if err != nil {
		return newParseError(SYNTAX_ERROR, err.Error(), m.lineNum)
	}
	return m.parseIntelHexRecord(bytes)
}

func (m *Memory) ParseIntelHex(str string) error {
	scanner := bufio.NewScanner(strings.NewReader(str))
	m.Clear()
	for scanner.Scan() {
		m.lineNum++
		line := scanner.Text()
		err := m.parseIntelHexLine(line)
		if err != nil {
			return err
		}
	}
	if err := scanner.Err(); err != nil {
		return newParseError(SYNTAX_ERROR, err.Error(), m.lineNum)
	}
	if m.eofFlag == false {
		return newParseError(DATA_ERROR, "no end of file line", m.lineNum)
	}

	return nil
}

func (m *Memory) DumpIntelHex() error {
	return nil
}
<|endoftext|>


<commit_before>package gobot

import (
	"fmt"
	log "github.com/Sirupsen/logrus"
	"github.com/eternnoir/gobot/payload"
	"net/http"
	_ "net/http/pprof"
	"sync"
)

var (
	workerMu  sync.RWMutex
	adapterMu sync.RWMutex
	workers   = make(map[string]Worker)
	adapters  = make(map[string]Adapter)
)

func RegisterWorker(name string, worker Worker) {
	workerMu.Lock()
	defer workerMu.Unlock()

	if worker == nil {
		panic("gotbot: Worker cannot be nil.")
	}
	if _, exist := workers[name]; exist {
		panic("gobot: Worker exist : " + name)
	}
	log.Debugf("Add Worker %s", name)
	workers[name] = worker
}

type Gobot struct {
	Name       string
	workers    map[string]Worker
	adapters   map[string]Adapter
	ConfigPath string
}

func NewDefaultGobot(botname string) *Gobot {
	ret := &Gobot{}
	ret.Name = botname
	ret.workers = workers
	ret.adapters = adapters
	ret.ConfigPath = "./"
	return ret
}

func RegisterAdapter(name string, newadapter Adapter) {
	adapterMu.Lock()
	defer adapterMu.Unlock()
	if newadapter == nil {
		panic("gobot: Adapter cannot be nil.")
	}
	if _, exist := adapters[name]; exist {
		panic("gobot: " + name + " exist.")
	}
	log.Debugf("Add adapter %s", name)
	adapters[name] = newadapter
}

func (bot *Gobot) StartGoBot() error {
	err := bot.initAdapter()
	if err != nil {
		log.Error(err)
		return err
	}

	err = bot.initWorkers()
	if err != nil {
		log.Error(err)
		return err
	}
	go bot.startAdaperts()
	return http.ListenAndServe("localhost:6060", nil)
}

func (bot *Gobot) Receive(message *payload.Message) {
	log.Infof("Receive new message. %#v", message)
	if message.SourceAdapter == "" {
		panic("Message's SourceAdapter Id must be seted.")
	}
	for name, worker := range bot.workers {
		// Call workers process
		log.Debugf("Call worker %s process message %#v", name, message)
		go func() {
			err := worker.Process(bot, message)
			if err != nil {
				log.Error(err)
			}
		}()
	}
}

func (bot *Gobot) Send(text string) {
	for an, adapter := range bot.adapters {
		log.Debugf("Use adapter %s, Send message %s", an, text)
		go adapter.Send(text)
	}
}

func (bot *Gobot) SendToChat(text, chatroom string) {
	for an, adapter := range bot.adapters {
		log.Debugf("Use adapter %s, Send message %s to ChatRoom %s", an, text, chatroom)
		go adapter.SendToChat(text, chatroom)
	}
}

func (bot *Gobot) Reply(orimessage *payload.Message, text string) error {
	adapter := bot.adapters[orimessage.SourceAdapter]
	return adapter.Reply(orimessage, text)
}

func (bot *Gobot) startAdaperts() {
	for name, adapter := range bot.adapters {
		log.Infof("Start Adapter %s", name)
		go adapter.Start()
	}
}

func (bot *Gobot) initAdapter() error {
	for name, adapter := range bot.adapters {
		err := adapter.Init(bot)
		if err != nil {
			return fmt.Errorf("Init Adapter %s Fail. %s", name, err.Error())
		}
	}
	return nil
}

func (bot *Gobot) initWorkers() error {
	for name, worker := range bot.workers {
		err := worker.Init(bot)
		if err != nil {
			return fmt.Errorf("Init worker %s Fail. %s", name, err.Error())
		}
	}
	return nil
}
<commit_msg>Fix two worker not working.<commit_after>package gobot

import (
	"fmt"
	log "github.com/Sirupsen/logrus"
	"github.com/eternnoir/gobot/payload"
	"net/http"
	_ "net/http/pprof"
	"sync"
)

var (
	workerMu  sync.RWMutex
	adapterMu sync.RWMutex
	workers   = make(map[string]Worker)
	adapters  = make(map[string]Adapter)
)

func RegisterWorker(name string, worker Worker) {
	workerMu.Lock()
	defer workerMu.Unlock()

	if worker == nil {
		panic("gotbot: Worker cannot be nil.")
	}
	if _, exist := workers[name]; exist {
		panic("gobot: Worker exist : " + name)
	}
	log.Debugf("Add Worker %s", name)
	workers[name] = worker
}

type Gobot struct {
	Name       string
	workers    map[string]Worker
	adapters   map[string]Adapter
	ConfigPath string
}

func NewDefaultGobot(botname string) *Gobot {
	ret := &Gobot{}
	ret.Name = botname
	ret.workers = workers
	ret.adapters = adapters
	ret.ConfigPath = "./"
	return ret
}

func RegisterAdapter(name string, newadapter Adapter) {
	adapterMu.Lock()
	defer adapterMu.Unlock()
	if newadapter == nil {
		panic("gobot: Adapter cannot be nil.")
	}
	if _, exist := adapters[name]; exist {
		panic("gobot: " + name + " exist.")
	}
	log.Debugf("Add adapter %s", name)
	adapters[name] = newadapter
}

func (bot *Gobot) StartGoBot() error {
	err := bot.initAdapter()
	if err != nil {
		log.Error(err)
		return err
	}

	err = bot.initWorkers()
	if err != nil {
		log.Error(err)
		return err
	}
	go bot.startAdaperts()
	return http.ListenAndServe("localhost:6060", nil)
}

func (bot *Gobot) Receive(message *payload.Message) {
	log.Infof("Receive new message. %#v", message)
	if message.SourceAdapter == "" {
		panic("Message's SourceAdapter Id must be seted.")
	}
	for name, worker := range bot.workers {
		// Call workers process
		log.Debugf("Call worker %s process message %#v", name, message)
		err := worker.Process(bot, message)
		if err != nil {
			log.Error(err)
		}
	}
}

func (bot *Gobot) Send(text string) {
	for an, adapter := range bot.adapters {
		log.Debugf("Use adapter %s, Send message %s", an, text)
		go adapter.Send(text)
	}
}

func (bot *Gobot) SendToChat(text, chatroom string) {
	for an, adapter := range bot.adapters {
		log.Debugf("Use adapter %s, Send message %s to ChatRoom %s", an, text, chatroom)
		go adapter.SendToChat(text, chatroom)
	}
}

func (bot *Gobot) Reply(orimessage *payload.Message, text string) error {
	adapter := bot.adapters[orimessage.SourceAdapter]
	return adapter.Reply(orimessage, text)
}

func (bot *Gobot) startAdaperts() {
	for name, adapter := range bot.adapters {
		log.Infof("Start Adapter %s", name)
		go adapter.Start()
	}
}

func (bot *Gobot) initAdapter() error {
	for name, adapter := range bot.adapters {
		err := adapter.Init(bot)
		if err != nil {
			return fmt.Errorf("Init Adapter %s Fail. %s", name, err.Error())
		}
	}
	return nil
}

func (bot *Gobot) initWorkers() error {
	for name, worker := range bot.workers {
		err := worker.Init(bot)
		if err != nil {
			return fmt.Errorf("Init worker %s Fail. %s", name, err.Error())
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package gotak

import (
	"crypto/x509"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/http/httputil"
	"strings"
)

type Diagnostics struct {
	Version      TlsVersion
	CipherSuite  string
	Certificates []*x509.Certificate
	NPN          bool
	NpnStrings   []string
}

func Diagnose(addr string, config *Config) (*Diagnostics, error) {
	if config == nil {
		config = new(Config)
		config.NextProtos = []string{"http/1.1"}
	}

	if !strings.Contains(addr, ":") {
		addr = addr + ":443"
	}

	conn, diag, err := Dial("tcp", addr, config)
	if err != nil {
		return nil, err
	}
	defer conn.Close()

	clientConn := httputil.NewClientConn(conn, nil)

	req, err := http.NewRequest("GET", "/favicon.ico", nil)
	if err != nil {
		return nil, err
	}

	_, err = clientConn.Do(req)
	if err != nil {
		return nil, err
	}

	if diag.NpnStrings != nil {
		diag.NPN = true
	}

	return diag, nil
}

func DiagnoseRequest(r *http.Request, config *Config) (*Diagnostics, error) {
	if config == nil {
		config = new(Config)
		config.NextProtos = []string{"http/1.1"}
	}

	addr := r.URL.Host

	if !strings.Contains(addr, ":") {
		addr = addr + ":443"
	}

	conn, diag, err := Dial("tcp", addr, config)
	if err != nil {
		return nil, err
	}
	defer conn.Close()

	clientConn := httputil.NewClientConn(conn, nil)

	_, err = clientConn.Do(r)
	if err != nil {
		return nil, err
	}

	if diag.NpnStrings != nil {
		diag.NPN = true
	}

	return diag, nil
}

func (d *Diagnostics) JSON() ([]byte, error) {
	jd := new(jsonDiagnostics)
	jd.Version = d.Version.String()
	jd.CipherSuite = d.CipherSuite
	jd.NPN = d.NpnStrings

	return json.Marshal(jd)
}

func (d *Diagnostics) EncodeJSON(w io.Writer) error {
	jd := new(jsonDiagnostics)
	jd.Version = d.Version.String()
	jd.CipherSuite = d.CipherSuite
	jd.NPN = d.NpnStrings

	return json.NewEncoder(w).Encode(jd)
}

type jsonDiagnostics struct {
	Version     string   `json:"version"`
	CipherSuite string   `json:"cipher_suite"`
	NPN         []string `json:"next_protocol_negotiation,omitempty"`
}

type TlsVersion uint16

const (
	TLS_1_0 TlsVersion = 10
	TLS_1_1            = 11
	TLS_1_2            = 12
)

func (t TlsVersion) String() string {
	switch t {
	case TLS_1_0:
		return "1.0"
	case TLS_1_1:
		return "1.1"
	case TLS_1_2:
		return "1.2"
	default:
		return ""
	}
}

func cryptVersTlsToGotak(vers uint16) (TlsVersion, error) {
	switch vers {
	case VersionSSL30, VersionTLS10:
		return TLS_1_0, nil
	case VersionTLS11:
		return TLS_1_1, nil
	case VersionTLS12:
		return TLS_1_2, nil
	default:
		return 0, fmt.Errorf("Error: Could not parse version %d.", vers)
	}
}
<commit_msg>Minor reliability improvement<commit_after>package gotak

import (
	"crypto/x509"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/http/httputil"
	"strings"
)

type Diagnostics struct {
	Version      TlsVersion
	CipherSuite  string
	Certificates []*x509.Certificate
	NPN          bool
	NpnStrings   []string
}

func Diagnose(addr string, config *Config) (*Diagnostics, error) {
	if config == nil {
		config = new(Config)
		config.NextProtos = []string{"http/1.1"}
	}

	if !strings.Contains(addr, ":") {
		addr = addr + ":443"
	}

	conn, diag, err := Dial("tcp", addr, config)
	if err != nil {
		return nil, err
	}
	defer conn.Close()

	clientConn := httputil.NewClientConn(conn, nil)

	req, err := http.NewRequest("GET", "/favicon.ico", nil)
	if err != nil {
		return nil, err
	}

	clientConn.Do(req)

	if diag.NpnStrings != nil {
		diag.NPN = true
	}

	return diag, nil
}

func DiagnoseRequest(r *http.Request, config *Config) (*Diagnostics, error) {
	if config == nil {
		config = new(Config)
		config.NextProtos = []string{"http/1.1"}
	}

	addr := r.URL.Host

	if !strings.Contains(addr, ":") {
		addr = addr + ":443"
	}

	conn, diag, err := Dial("tcp", addr, config)
	if err != nil {
		return nil, err
	}
	defer conn.Close()

	clientConn := httputil.NewClientConn(conn, nil)

	clientConn.Do(r)

	if diag.NpnStrings != nil {
		diag.NPN = true
	}

	return diag, nil
}

func (d *Diagnostics) JSON() ([]byte, error) {
	jd := new(jsonDiagnostics)
	jd.Version = d.Version.String()
	jd.CipherSuite = d.CipherSuite
	jd.NPN = d.NpnStrings

	return json.Marshal(jd)
}

func (d *Diagnostics) EncodeJSON(w io.Writer) error {
	jd := new(jsonDiagnostics)
	jd.Version = d.Version.String()
	jd.CipherSuite = d.CipherSuite
	jd.NPN = d.NpnStrings

	return json.NewEncoder(w).Encode(jd)
}

type jsonDiagnostics struct {
	Version     string   `json:"version"`
	CipherSuite string   `json:"cipher_suite"`
	NPN         []string `json:"next_protocol_negotiation,omitempty"`
}

type TlsVersion uint16

const (
	TLS_1_0 TlsVersion = 10
	TLS_1_1            = 11
	TLS_1_2            = 12
)

func (t TlsVersion) String() string {
	switch t {
	case TLS_1_0:
		return "1.0"
	case TLS_1_1:
		return "1.1"
	case TLS_1_2:
		return "1.2"
	default:
		return ""
	}
}

func cryptVersTlsToGotak(vers uint16) (TlsVersion, error) {
	switch vers {
	case VersionSSL30, VersionTLS10:
		return TLS_1_0, nil
	case VersionTLS11:
		return TLS_1_1, nil
	case VersionTLS12:
		return TLS_1_2, nil
	default:
		return 0, fmt.Errorf("Error: Could not parse version %d.", vers)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
)

func main() {
	// for who.go Who(char, lvl)
	var char = flag.String("char", "", "Character name for update or import. Ex: Rynshana")
	var lvl = flag.Int("lvl", 0, "Character level for update or import. Ex: 50")
	// for who.go WhoChar(char, lvl, class, race, acct)
	var class = flag.String("class", "", "Character class for initial import. Ex: \"Cleric\"")
	var race = flag.String("race", "", "Character race for initial import. Ex: \"Moon Elf\"")
	var acct = flag.String("acct", "", "Character account for initial import. Ex: Krimic")
	// for identify.go Identify(filename)
	var file = flag.String("import", "", "Parse file for identify stats, import to DB. Ex: newstats.txt")
	// for time.go Uptime(curup)
	var time = flag.String("time", "", "Parse uptime for boot tracking. Ex: 58:10:26")
	// for tell.go ReplyTo(char, tell)
	var tell = flag.String("tell", "", "Tell with command and maybe operant. Ex: \"stat a longsword\"")

	flag.Parse()

	// only run one command at a time
	switch {
	case *char != "" && 50 >= *lvl && *lvl > 0 && *class != "" && *race != "" && *acct != "":
		WhoChar(*char, *lvl, *class, *race, *acct)
	case *char != "" && 50 >= *lvl && *lvl > 0:
		Who(*char, *lvl)
	case *file != "":
		Identify(*file)
	case *time != "":
		Uptime(*time)
	case *char != "" && *tell != "":
		ReplyTo(*char, *tell)
	}
}
<commit_msg>Added flag for who batch mode<commit_after>package main

import (
	"flag"
)

func main() {
	// for who.go Who(char, lvl)
	var char = flag.String("char", "", "Character name for update or import. Ex: Rynshana")
	var lvl = flag.Int("lvl", 0, "Character level for update or import. Ex: 50")
	// for who.go WhoChar(char, lvl, class, race, acct)
	var class = flag.String("class", "", "Character class for initial import. Ex: \"Cleric\"")
	var race = flag.String("race", "", "Character race for initial import. Ex: \"Moon Elf\"")
	var acct = flag.String("acct", "", "Character account for initial import. Ex: Krimic")
	// for identify.go Identify(filename)
	var file = flag.String("import", "", "Parse file for identify stats, import to DB. Ex: newstats.txt")
	// for time.go Uptime(curup)
	var time = flag.String("time", "", "Parse uptime for boot tracking. Ex: 58:10:26")
	// for tell.go ReplyTo(char, tell)
	var tell = flag.String("tell", "", "Tell with command and maybe operant. Ex: \"stat a longsword\"")
	// for who.go WhoBatch(ppl)
	var who = flag.String("who", "", "Batched who output. Ex: [ 1 Ctr] Rarac  (Orc)|[ 2 War] Xatus  (Troll)")

	flag.Parse()

	// only run one command at a time
	switch {
	case *char != "" && 50 >= *lvl && *lvl > 0 && *class != "" && *race != "" && *acct != "":
		WhoChar(*char, *lvl, *class, *race, *acct)
	case *char != "" && 50 >= *lvl && *lvl > 0:
		Who(*char, *lvl)
	case *file != "":
		Identify(*file)
	case *time != "":
		Uptime(*time)
	case *char != "" && *tell != "":
		ReplyTo(*char, *tell)
	case *who != "":
		WhoBatch(*who)
	}
}
<|endoftext|>


<commit_before>package allocdir

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

	"github.com/hashicorp/nomad/nomad/structs"
)

var (
	// The name of the directory that is shared across tasks in a task group.
	SharedAllocName = "alloc"

	// The set of directories that exist inside eache shared alloc directory.
	SharedAllocDirs = []string{"logs", "tmp", "data"}

	// The name of the directory that exists inside each task directory
	// regardless of driver.
	TaskLocal = "local"
)

type AllocDir struct {
	// AllocDir is the directory used for storing any state
	// of this allocation. It will be purged on alloc destroy.
	AllocDir string

	// The shared directory is available to all tasks within the same task
	// group.
	SharedDir string

	// TaskDirs is a mapping of task names to their non-shared directory.
	TaskDirs map[string]string

	// A list of locations the shared alloc has been mounted to.
	mounted []string
}

type AllocFile struct {
	Name  string
	IsDir bool
	Size  int64
}

func NewAllocDir(allocDir string) *AllocDir {
	d := &AllocDir{AllocDir: allocDir, TaskDirs: make(map[string]string)}
	d.SharedDir = filepath.Join(d.AllocDir, SharedAllocName)
	return d
}

// Tears down previously build directory structure.
func (d *AllocDir) Destroy() error {
	// Unmount all mounted shared alloc dirs.
	for _, m := range d.mounted {
		if err := d.unmountSharedDir(m); err != nil {
			return fmt.Errorf("Failed to unmount shared directory: %v", err)
		}
	}

	return os.RemoveAll(d.AllocDir)
}

// Given a list of a task build the correct alloc structure.
func (d *AllocDir) Build(tasks []*structs.Task) error {
	// Make the alloc directory, owned by the nomad process.
	if err := os.MkdirAll(d.AllocDir, 0700); err != nil {
		return fmt.Errorf("Failed to make the alloc directory %v: %v", d.AllocDir, err)
	}

	// Make the shared directory and make it availabe to all user/groups.
	if err := os.Mkdir(d.SharedDir, 0777); err != nil {
		return err
	}

	// Make the shared directory have non-root permissions.
	if err := d.dropDirPermissions(d.SharedDir); err != nil {
		return err
	}

	for _, dir := range SharedAllocDirs {
		p := filepath.Join(d.SharedDir, dir)
		if err := os.Mkdir(p, 0777); err != nil {
			return err
		}
	}

	// Make the task directories.
	for _, t := range tasks {
		taskDir := filepath.Join(d.AllocDir, t.Name)
		if err := os.Mkdir(taskDir, 0777); err != nil {
			return err
		}

		// Make the task directory have non-root permissions.
		if err := d.dropDirPermissions(taskDir); err != nil {
			return err
		}

		// Create a local directory that each task can use.
		local := filepath.Join(taskDir, TaskLocal)
		if err := os.Mkdir(local, 0777); err != nil {
			return err
		}

		if err := d.dropDirPermissions(local); err != nil {
			return err
		}

		d.TaskDirs[t.Name] = taskDir
	}

	return nil
}

// Embed takes a mapping of absolute directory or file paths on the host to
// their intended, relative location within the task directory. Embed attempts
// hardlink and then defaults to copying. If the path exists on the host and
// can't be embeded an error is returned.
func (d *AllocDir) Embed(task string, entries map[string]string) error {
	taskdir, ok := d.TaskDirs[task]
	if !ok {
		return fmt.Errorf("Task directory doesn't exist for task %v", task)
	}

	subdirs := make(map[string]string)
	for source, dest := range entries {
		// Check to see if directory exists on host.
		s, err := os.Stat(source)
		if os.IsNotExist(err) {
			continue
		}

		// Embedding a single file
		if !s.IsDir() {
			destDir := filepath.Join(taskdir, filepath.Dir(dest))
			if err := os.MkdirAll(destDir, s.Mode().Perm()); err != nil {
				return fmt.Errorf("Couldn't create destination directory %v: %v", destDir, err)
			}

			// Copy the file.
			taskEntry := filepath.Join(destDir, filepath.Base(dest))
			if err := d.linkOrCopy(source, taskEntry, s.Mode().Perm()); err != nil {
				return err
			}

			continue
		}

		// Create destination directory.
		destDir := filepath.Join(taskdir, dest)
		if err := os.MkdirAll(destDir, s.Mode().Perm()); err != nil {
			return fmt.Errorf("Couldn't create destination directory %v: %v", destDir, err)
		}

		// Enumerate the files in source.
		dirEntries, err := ioutil.ReadDir(source)
		if err != nil {
			return fmt.Errorf("Couldn't read directory %v: %v", source, err)
		}

		for _, entry := range dirEntries {
			hostEntry := filepath.Join(source, entry.Name())
			taskEntry := filepath.Join(destDir, filepath.Base(hostEntry))
			if entry.IsDir() {
				subdirs[hostEntry] = filepath.Join(dest, filepath.Base(hostEntry))
				continue
			}

			// Check if entry exists. This can happen if restarting a failed
			// task.
			if _, err := os.Lstat(taskEntry); err == nil {
				continue
			}

			if !entry.Mode().IsRegular() {
				// If it is a symlink we can create it, otherwise we skip it.
				if entry.Mode()&os.ModeSymlink == 0 {
					continue
				}

				link, err := os.Readlink(hostEntry)
				if err != nil {
					return fmt.Errorf("Couldn't resolve symlink for %v: %v", source, err)
				}

				if err := os.Symlink(link, taskEntry); err != nil {
					return fmt.Errorf("Couldn't create symlink: %v", err)
				}
				continue
			}

			if err := d.linkOrCopy(hostEntry, taskEntry, entry.Mode().Perm()); err != nil {
				return err
			}
		}
	}

	// Recurse on self to copy subdirectories.
	if len(subdirs) != 0 {
		return d.Embed(task, subdirs)
	}

	return nil
}

// MountSharedDir mounts the shared directory into the specified task's
// directory. Mount is documented at an OS level in their respective
// implementation files.
func (d *AllocDir) MountSharedDir(task string) error {
	taskDir, ok := d.TaskDirs[task]
	if !ok {
		return fmt.Errorf("No task directory exists for %v", task)
	}

	taskLoc := filepath.Join(taskDir, SharedAllocName)
	if err := d.mountSharedDir(taskLoc); err != nil {
		return fmt.Errorf("Failed to mount shared directory for task %v: %v", task, err)
	}

	d.mounted = append(d.mounted, taskLoc)
	return nil
}

func (d *AllocDir) FSList(path string) ([]*AllocFile, error) {
	p := filepath.Join(d.AllocDir, path)
	finfos, err := ioutil.ReadDir(p)
	if err != nil {
		return []*AllocFile{}, nil
	}
	files := make([]*AllocFile, len(finfos))
	for idx, info := range finfos {
		files[idx] = &AllocFile{
			Name:  info.Name(),
			IsDir: info.IsDir(),
			Size:  info.Size(),
		}
	}
	return files, err
}

func (d *AllocDir) FSStat(path string) (*AllocFile, error) {
	p := filepath.Join(d.AllocDir, path)
	info, err := os.Stat(p)
	if err != nil {
		return nil, err
	}

	return &AllocFile{
		Size:  info.Size(),
		Name:  info.Name(),
		IsDir: info.IsDir(),
	}, nil
}

func (d *AllocDir) FSReadAt(allocID string, path string, offset int64, limit int64, w io.Writer) error {
	buf := make([]byte, limit)
	p := filepath.Join(d.AllocDir, path)
	f, err := os.Open(p)
	if err != nil {
		return err
	}
	n, err := f.ReadAt(buf, offset)
	if err != nil {
		return err
	}
	w.Write(buf[:n])
	return nil
}

func fileCopy(src, dst string, perm os.FileMode) error {
	// Do a simple copy.
	srcFile, err := os.Open(src)
	if err != nil {
		return fmt.Errorf("Couldn't open src file %v: %v", src, err)
	}

	dstFile, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE, perm)
	if err != nil {
		return fmt.Errorf("Couldn't create destination file %v: %v", dst, err)
	}

	if _, err := io.Copy(dstFile, srcFile); err != nil {
		return fmt.Errorf("Couldn't copy %v to %v: %v", src, dst, err)
	}

	return nil
}
<commit_msg>Writing contents of buffer to writer even if there was an error<commit_after>package allocdir

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

	"github.com/hashicorp/nomad/nomad/structs"
)

var (
	// The name of the directory that is shared across tasks in a task group.
	SharedAllocName = "alloc"

	// The set of directories that exist inside eache shared alloc directory.
	SharedAllocDirs = []string{"logs", "tmp", "data"}

	// The name of the directory that exists inside each task directory
	// regardless of driver.
	TaskLocal = "local"
)

type AllocDir struct {
	// AllocDir is the directory used for storing any state
	// of this allocation. It will be purged on alloc destroy.
	AllocDir string

	// The shared directory is available to all tasks within the same task
	// group.
	SharedDir string

	// TaskDirs is a mapping of task names to their non-shared directory.
	TaskDirs map[string]string

	// A list of locations the shared alloc has been mounted to.
	mounted []string
}

type AllocFile struct {
	Name  string
	IsDir bool
	Size  int64
}

func NewAllocDir(allocDir string) *AllocDir {
	d := &AllocDir{AllocDir: allocDir, TaskDirs: make(map[string]string)}
	d.SharedDir = filepath.Join(d.AllocDir, SharedAllocName)
	return d
}

// Tears down previously build directory structure.
func (d *AllocDir) Destroy() error {
	// Unmount all mounted shared alloc dirs.
	for _, m := range d.mounted {
		if err := d.unmountSharedDir(m); err != nil {
			return fmt.Errorf("Failed to unmount shared directory: %v", err)
		}
	}

	return os.RemoveAll(d.AllocDir)
}

// Given a list of a task build the correct alloc structure.
func (d *AllocDir) Build(tasks []*structs.Task) error {
	// Make the alloc directory, owned by the nomad process.
	if err := os.MkdirAll(d.AllocDir, 0700); err != nil {
		return fmt.Errorf("Failed to make the alloc directory %v: %v", d.AllocDir, err)
	}

	// Make the shared directory and make it availabe to all user/groups.
	if err := os.Mkdir(d.SharedDir, 0777); err != nil {
		return err
	}

	// Make the shared directory have non-root permissions.
	if err := d.dropDirPermissions(d.SharedDir); err != nil {
		return err
	}

	for _, dir := range SharedAllocDirs {
		p := filepath.Join(d.SharedDir, dir)
		if err := os.Mkdir(p, 0777); err != nil {
			return err
		}
	}

	// Make the task directories.
	for _, t := range tasks {
		taskDir := filepath.Join(d.AllocDir, t.Name)
		if err := os.Mkdir(taskDir, 0777); err != nil {
			return err
		}

		// Make the task directory have non-root permissions.
		if err := d.dropDirPermissions(taskDir); err != nil {
			return err
		}

		// Create a local directory that each task can use.
		local := filepath.Join(taskDir, TaskLocal)
		if err := os.Mkdir(local, 0777); err != nil {
			return err
		}

		if err := d.dropDirPermissions(local); err != nil {
			return err
		}

		d.TaskDirs[t.Name] = taskDir
	}

	return nil
}

// Embed takes a mapping of absolute directory or file paths on the host to
// their intended, relative location within the task directory. Embed attempts
// hardlink and then defaults to copying. If the path exists on the host and
// can't be embeded an error is returned.
func (d *AllocDir) Embed(task string, entries map[string]string) error {
	taskdir, ok := d.TaskDirs[task]
	if !ok {
		return fmt.Errorf("Task directory doesn't exist for task %v", task)
	}

	subdirs := make(map[string]string)
	for source, dest := range entries {
		// Check to see if directory exists on host.
		s, err := os.Stat(source)
		if os.IsNotExist(err) {
			continue
		}

		// Embedding a single file
		if !s.IsDir() {
			destDir := filepath.Join(taskdir, filepath.Dir(dest))
			if err := os.MkdirAll(destDir, s.Mode().Perm()); err != nil {
				return fmt.Errorf("Couldn't create destination directory %v: %v", destDir, err)
			}

			// Copy the file.
			taskEntry := filepath.Join(destDir, filepath.Base(dest))
			if err := d.linkOrCopy(source, taskEntry, s.Mode().Perm()); err != nil {
				return err
			}

			continue
		}

		// Create destination directory.
		destDir := filepath.Join(taskdir, dest)
		if err := os.MkdirAll(destDir, s.Mode().Perm()); err != nil {
			return fmt.Errorf("Couldn't create destination directory %v: %v", destDir, err)
		}

		// Enumerate the files in source.
		dirEntries, err := ioutil.ReadDir(source)
		if err != nil {
			return fmt.Errorf("Couldn't read directory %v: %v", source, err)
		}

		for _, entry := range dirEntries {
			hostEntry := filepath.Join(source, entry.Name())
			taskEntry := filepath.Join(destDir, filepath.Base(hostEntry))
			if entry.IsDir() {
				subdirs[hostEntry] = filepath.Join(dest, filepath.Base(hostEntry))
				continue
			}

			// Check if entry exists. This can happen if restarting a failed
			// task.
			if _, err := os.Lstat(taskEntry); err == nil {
				continue
			}

			if !entry.Mode().IsRegular() {
				// If it is a symlink we can create it, otherwise we skip it.
				if entry.Mode()&os.ModeSymlink == 0 {
					continue
				}

				link, err := os.Readlink(hostEntry)
				if err != nil {
					return fmt.Errorf("Couldn't resolve symlink for %v: %v", source, err)
				}

				if err := os.Symlink(link, taskEntry); err != nil {
					return fmt.Errorf("Couldn't create symlink: %v", err)
				}
				continue
			}

			if err := d.linkOrCopy(hostEntry, taskEntry, entry.Mode().Perm()); err != nil {
				return err
			}
		}
	}

	// Recurse on self to copy subdirectories.
	if len(subdirs) != 0 {
		return d.Embed(task, subdirs)
	}

	return nil
}

// MountSharedDir mounts the shared directory into the specified task's
// directory. Mount is documented at an OS level in their respective
// implementation files.
func (d *AllocDir) MountSharedDir(task string) error {
	taskDir, ok := d.TaskDirs[task]
	if !ok {
		return fmt.Errorf("No task directory exists for %v", task)
	}

	taskLoc := filepath.Join(taskDir, SharedAllocName)
	if err := d.mountSharedDir(taskLoc); err != nil {
		return fmt.Errorf("Failed to mount shared directory for task %v: %v", task, err)
	}

	d.mounted = append(d.mounted, taskLoc)
	return nil
}

func (d *AllocDir) FSList(path string) ([]*AllocFile, error) {
	p := filepath.Join(d.AllocDir, path)
	finfos, err := ioutil.ReadDir(p)
	if err != nil {
		return []*AllocFile{}, nil
	}
	files := make([]*AllocFile, len(finfos))
	for idx, info := range finfos {
		files[idx] = &AllocFile{
			Name:  info.Name(),
			IsDir: info.IsDir(),
			Size:  info.Size(),
		}
	}
	return files, err
}

func (d *AllocDir) FSStat(path string) (*AllocFile, error) {
	p := filepath.Join(d.AllocDir, path)
	info, err := os.Stat(p)
	if err != nil {
		return nil, err
	}

	return &AllocFile{
		Size:  info.Size(),
		Name:  info.Name(),
		IsDir: info.IsDir(),
	}, nil
}

func (d *AllocDir) FSReadAt(allocID string, path string, offset int64, limit int64, w io.Writer) error {
	buf := make([]byte, limit)
	p := filepath.Join(d.AllocDir, path)
	f, err := os.Open(p)
	if err != nil {
		return err
	}
	n, err := f.ReadAt(buf, offset)
	w.Write(buf[:n])
	return err
}

func fileCopy(src, dst string, perm os.FileMode) error {
	// Do a simple copy.
	srcFile, err := os.Open(src)
	if err != nil {
		return fmt.Errorf("Couldn't open src file %v: %v", src, err)
	}

	dstFile, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE, perm)
	if err != nil {
		return fmt.Errorf("Couldn't create destination file %v: %v", dst, err)
	}

	if _, err := io.Copy(dstFile, srcFile); err != nil {
		return fmt.Errorf("Couldn't copy %v to %v: %v", src, dst, err)
	}

	return nil
}
<|endoftext|>