<commit_before>package contractmanager

import (
	"encoding/json"
	"path/filepath"
	"reflect"
	"sync"
	"sync/atomic"
	"time"

	"github.com/NebulousLabs/Sia/build"
)

// syncResources will call Sync on all resources that the WAL has open. The
// storage folder files will be left open, as they are not updated atomically.
// The settings file and WAL tmp files will be synced and closed, to perform an
// atomic update to the files.
func (wal *writeAheadLog) syncResources() {
	// Syncing occurs over multiple files and disks, and is done in parallel to
	// minimize the amount of time that a lock is held over the contract
	// manager.
	var wg sync.WaitGroup

	// Sync the settings file.
	wg.Add(1)
	go func() {
		defer wg.Done()

		if wal.fileSettingsTmp == nil {
			// nothing to sync
			return
		}

		tmpFilename := filepath.Join(wal.cm.persistDir, settingsFileTmp)
		filename := filepath.Join(wal.cm.persistDir, settingsFile)
		err := wal.fileSettingsTmp.Sync()
		if err != nil {
			wal.cm.log.Severe("ERROR: unable to sync the contract manager settings:", err)
		}
		err = wal.fileSettingsTmp.Close()
		if err != nil {
			wal.cm.log.Println("unable to close the temporary contract manager settings file:", err)
		}

		// For testing, provide a place to interrupt the saving of the sync
		// file. This makes it easy to simulate certain types of unclean
		// shutdown.
		if wal.cm.dependencies.disrupt("settingsSyncRename") {
			// The current settings file that is being re-written will not be
			// saved.
			return
		}

		err = wal.cm.dependencies.renameFile(tmpFilename, filename)
		if err != nil {
			wal.cm.log.Severe("ERROR: unable to atomically copy the contract manager settings:", err)
		}
	}()

	// Sync all of the storage folders.
	for _, sf := range wal.cm.storageFolders {
		// Skip operation on unavailable storage folders.
		if atomic.LoadUint64(&sf.atomicUnavailable) == 1 {
			continue
		}

		wg.Add(2)
		go func(sf *storageFolder) {
			defer wg.Done()
			err := sf.metadataFile.Sync()
			if err != nil {
				wal.cm.log.Severe("ERROR: unable to sync a storage folder:", err)
			}
		}(sf)
		go func(sf *storageFolder) {
			defer wg.Done()
			err := sf.sectorFile.Sync()
			if err != nil {
				wal.cm.log.Severe("ERROR: unable to sync a storage folder:", err)
			}
		}(sf)
	}

	// Sync the temp WAL file, but do not perform the atmoic rename - the
	// atomic rename must be guaranteed to happen after all of the other files
	// have been synced.
	wg.Add(1)
	go func() {
		defer wg.Done()

		err := wal.fileWALTmp.Sync()
		if err != nil {
			wal.cm.log.Severe("Unable to sync the write-ahead-log:", err)
		}
		err = wal.fileWALTmp.Close()
		if err != nil {
			// Log that the host is having trouble saving the uncommitted changes.
			// Crash if the list of uncommitted changes has grown very large.
			wal.cm.log.Println("ERROR: could not close temporary write-ahead-log in contract manager:", err)
			return
		}
	}()

	// Wait for all of the sync calls to finish.
	wg.Wait()

	// Now that all the Sync calls have completed, rename the WAL tmp file to
	// update the WAL.
	if !wal.cm.dependencies.disrupt("walRename") {
		walTmpName := filepath.Join(wal.cm.persistDir, walFileTmp)
		walFileName := filepath.Join(wal.cm.persistDir, walFile)
		err := wal.cm.dependencies.renameFile(walTmpName, walFileName)
		if err != nil {
			// Log that the host is having trouble saving the uncommitted changes.
			// Crash if the list of uncommitted changes has grown very large.
			wal.cm.log.Severe("ERROR: could not rename temporary write-ahead-log in contract manager:", err)
		}
	}

	// Perform any cleanup actions on the updates.
	for _, sc := range wal.uncommittedChanges {
		for _, sfe := range sc.StorageFolderExtensions {
			wal.commitStorageFolderExtension(sfe)
		}
		for _, sfr := range sc.StorageFolderReductions {
			wal.commitStorageFolderReduction(sfr)
		}
		for _, sfr := range sc.StorageFolderRemovals {
			wal.commitStorageFolderRemoval(sfr)
		}

		// TODO: Virtual sector handling here.
	}

	// Now that the WAL is sync'd and updated, any calls waiting on ACID
	// guarantees can safely return.
	close(wal.syncChan)
	wal.syncChan = make(chan struct{})
}

// commit will take all of the changes that have been added to the WAL and
// atomically commit the WAL to disk, then apply the actions in the WAL to the
// state. commit will do lots of syncing disk I/O, and so can take a while,
// especially if there are a large number of actions queued up.
//
// A bool is returned indicating whether or not the commit was successful.
// False does not indiciate an error, it can also indicate that there was
// nothing to do.
//
// commit should only be called from threadedSyncLoop.
func (wal *writeAheadLog) commit() {
	// Sync all open, non-WAL files on the host.
	wal.syncResources()

	// Extract any unfinished long-running jobs from the list of WAL items.
	unfinishedAdditions := findUnfinishedStorageFolderAdditions(wal.uncommittedChanges)
	unfinishedExtensions := findUnfinishedStorageFolderExtensions(wal.uncommittedChanges)

	// Clear the set of uncommitted changes.
	wal.uncommittedChanges = nil

	// Begin writing to the settings file.
	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		defer wg.Done()

		newSettings := wal.cm.savedSettings()
		if reflect.DeepEqual(newSettings, wal.committedSettings) {
			// no need to write the settings file
			wal.fileSettingsTmp = nil
			return
		}
		wal.committedSettings = newSettings

		// Begin writing to the settings file, which will be synced during the
		// next iteration of the sync loop.
		var err error
		wal.fileSettingsTmp, err = wal.cm.dependencies.createFile(filepath.Join(wal.cm.persistDir, settingsFileTmp))
		if err != nil {
			wal.cm.log.Severe("Unable to open temporary settings file for writing:", err)
		}
		b, err := json.MarshalIndent(newSettings, "", "\t")
		if err != nil {
			build.ExtendErr("unable to marshal settings data", err)
		}
		enc := json.NewEncoder(wal.fileSettingsTmp)
		if err := enc.Encode(settingsMetadata.Header); err != nil {
			build.ExtendErr("unable to write header to settings temp file", err)
		}
		if err := enc.Encode(settingsMetadata.Version); err != nil {
			build.ExtendErr("unable to write version to settings temp file", err)
		}
		if _, err = wal.fileSettingsTmp.Write(b); err != nil {
			build.ExtendErr("unable to write data settings temp file", err)
		}
	}()

	// Begin writing new changes to the WAL.
	wg.Add(1)
	go func() {
		defer wg.Done()

		// Recreate the wal file so that it can receive new updates.
		var err error
		walTmpName := filepath.Join(wal.cm.persistDir, walFileTmp)
		wal.fileWALTmp, err = wal.cm.dependencies.createFile(walTmpName)
		if err != nil {
			wal.cm.log.Severe("ERROR: unable to create write-ahead-log:", err)
		}
		// Write the metadata into the WAL.
		err = writeWALMetadata(wal.fileWALTmp)
		if err != nil {
			wal.cm.log.Severe("Unable to properly initialize WAL file, crashing to prevent corruption:", err)
		}

		// Append all of the remaining long running uncommitted changes to the WAL.
		if len(unfinishedAdditions)+len(unfinishedExtensions) > 0 {
			wal.appendChange(stateChange{
				UnfinishedStorageFolderAdditions:  unfinishedAdditions,
				UnfinishedStorageFolderExtensions: unfinishedExtensions,
			})
		}
	}()
	wg.Wait()
}

// spawnSyncLoop prepares and establishes the loop which will be running in the
// background to coordinate disk syncronizations. Disk syncing is done in a
// background loop to help with performance, and to allow multiple things to
// modify the WAL simultaneously.
func (wal *writeAheadLog) spawnSyncLoop() (err error) {
	// Create a signal so we know when the sync loop has stopped, which means
	// there will be no more open commits.
	threadsStopped := make(chan struct{})
	syncLoopStopped := make(chan struct{})
	wal.syncChan = make(chan struct{})
	go wal.threadedSyncLoop(threadsStopped, syncLoopStopped)
	wal.cm.tg.AfterStop(func() {
		// Wait for another iteration of the sync loop, so that the in-progress
		// settings can be saved atomically to disk.
		wal.mu.Lock()
		syncChan := wal.syncChan
		wal.mu.Unlock()
		<-syncChan

		// Close the threadsStopped channel to let the sync loop know that all
		// calls to tg.Add() in the contract manager have cleaned up.
		close(threadsStopped)

		// Because this is being called in an 'AfterStop' routine, all open
		// calls to the contract manager should have completed, and all open
		// threads should have closed. The last call to change the contract
		// manager should have completed, so the number of uncommitted changes
		// should be zero.
		<-syncLoopStopped // Wait for the sync loop to signal proper termination.

		// Allow unclean shutdown to be simulated by disrupting the removal of
		// the WAL file.
		if !wal.cm.dependencies.disrupt("cleanWALFile") {
			err = wal.cm.dependencies.removeFile(filepath.Join(wal.cm.persistDir, walFile))
			if err != nil {
				wal.cm.log.Println("Error removing WAL during contract manager shutdown:", err)
			}
		}
	})
	return nil
}

// threadedSyncLoop is a background thread that occasionally commits the WAL to
// the state as an ACID transaction. This process can be very slow, so
// transactions to the contract manager are batched automatically and
// occasionally committed together.
func (wal *writeAheadLog) threadedSyncLoop(threadsStopped chan struct{}, syncLoopStopped chan struct{}) {
	// Provide a place for the testing to disable the sync loop.
	if wal.cm.dependencies.disrupt("threadedSyncLoopStart") {
		close(syncLoopStopped)
		return
	}

	syncInterval := 500 * time.Millisecond
	for {
		select {
		case <-threadsStopped:
			close(syncLoopStopped)
			return
		case <-time.After(syncInterval):
			// Commit all of the changes in the WAL to disk, and then apply the
			// changes.
			wal.mu.Lock()
			wal.commit()
			wal.mu.Unlock()
		}
	}
}
<commit_msg>only commit host WAL if it has changes<commit_after>package contractmanager

import (
	"encoding/json"
	"path/filepath"
	"reflect"
	"sync"
	"sync/atomic"
	"time"

	"github.com/NebulousLabs/Sia/build"
)

// syncResources will call Sync on all resources that the WAL has open. The
// storage folder files will be left open, as they are not updated atomically.
// The settings file and WAL tmp files will be synced and closed, to perform an
// atomic update to the files.
func (wal *writeAheadLog) syncResources() {
	// Syncing occurs over multiple files and disks, and is done in parallel to
	// minimize the amount of time that a lock is held over the contract
	// manager.
	var wg sync.WaitGroup

	// Sync the settings file.
	wg.Add(1)
	go func() {
		defer wg.Done()

		if wal.fileSettingsTmp == nil {
			// nothing to sync
			return
		}

		tmpFilename := filepath.Join(wal.cm.persistDir, settingsFileTmp)
		filename := filepath.Join(wal.cm.persistDir, settingsFile)
		err := wal.fileSettingsTmp.Sync()
		if err != nil {
			wal.cm.log.Severe("ERROR: unable to sync the contract manager settings:", err)
		}
		err = wal.fileSettingsTmp.Close()
		if err != nil {
			wal.cm.log.Println("unable to close the temporary contract manager settings file:", err)
		}

		// For testing, provide a place to interrupt the saving of the sync
		// file. This makes it easy to simulate certain types of unclean
		// shutdown.
		if wal.cm.dependencies.disrupt("settingsSyncRename") {
			// The current settings file that is being re-written will not be
			// saved.
			return
		}

		err = wal.cm.dependencies.renameFile(tmpFilename, filename)
		if err != nil {
			wal.cm.log.Severe("ERROR: unable to atomically copy the contract manager settings:", err)
		}
	}()

	// Sync all of the storage folders.
	for _, sf := range wal.cm.storageFolders {
		// Skip operation on unavailable storage folders.
		if atomic.LoadUint64(&sf.atomicUnavailable) == 1 {
			continue
		}

		wg.Add(2)
		go func(sf *storageFolder) {
			defer wg.Done()
			err := sf.metadataFile.Sync()
			if err != nil {
				wal.cm.log.Severe("ERROR: unable to sync a storage folder:", err)
			}
		}(sf)
		go func(sf *storageFolder) {
			defer wg.Done()
			err := sf.sectorFile.Sync()
			if err != nil {
				wal.cm.log.Severe("ERROR: unable to sync a storage folder:", err)
			}
		}(sf)
	}

	// Sync the temp WAL file, but do not perform the atmoic rename - the
	// atomic rename must be guaranteed to happen after all of the other files
	// have been synced.
	wg.Add(1)
	go func() {
		defer wg.Done()
		if len(wal.uncommittedChanges) == 0 {
			// nothing to sync
			return
		}

		err := wal.fileWALTmp.Sync()
		if err != nil {
			wal.cm.log.Severe("Unable to sync the write-ahead-log:", err)
		}
		err = wal.fileWALTmp.Close()
		if err != nil {
			// Log that the host is having trouble saving the uncommitted changes.
			// Crash if the list of uncommitted changes has grown very large.
			wal.cm.log.Println("ERROR: could not close temporary write-ahead-log in contract manager:", err)
			return
		}
	}()

	// Wait for all of the sync calls to finish.
	wg.Wait()

	// Now that all the Sync calls have completed, rename the WAL tmp file to
	// update the WAL.
	if len(wal.uncommittedChanges) != 0 && !wal.cm.dependencies.disrupt("walRename") {
		walTmpName := filepath.Join(wal.cm.persistDir, walFileTmp)
		walFileName := filepath.Join(wal.cm.persistDir, walFile)
		err := wal.cm.dependencies.renameFile(walTmpName, walFileName)
		if err != nil {
			// Log that the host is having trouble saving the uncommitted changes.
			// Crash if the list of uncommitted changes has grown very large.
			wal.cm.log.Severe("ERROR: could not rename temporary write-ahead-log in contract manager:", err)
		}
	}

	// Perform any cleanup actions on the updates.
	for _, sc := range wal.uncommittedChanges {
		for _, sfe := range sc.StorageFolderExtensions {
			wal.commitStorageFolderExtension(sfe)
		}
		for _, sfr := range sc.StorageFolderReductions {
			wal.commitStorageFolderReduction(sfr)
		}
		for _, sfr := range sc.StorageFolderRemovals {
			wal.commitStorageFolderRemoval(sfr)
		}

		// TODO: Virtual sector handling here.
	}

	// Now that the WAL is sync'd and updated, any calls waiting on ACID
	// guarantees can safely return.
	close(wal.syncChan)
	wal.syncChan = make(chan struct{})
}

// commit will take all of the changes that have been added to the WAL and
// atomically commit the WAL to disk, then apply the actions in the WAL to the
// state. commit will do lots of syncing disk I/O, and so can take a while,
// especially if there are a large number of actions queued up.
//
// A bool is returned indicating whether or not the commit was successful.
// False does not indiciate an error, it can also indicate that there was
// nothing to do.
//
// commit should only be called from threadedSyncLoop.
func (wal *writeAheadLog) commit() {
	// Sync all open, non-WAL files on the host.
	wal.syncResources()

	// Begin writing to the settings file.
	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		defer wg.Done()

		newSettings := wal.cm.savedSettings()
		if reflect.DeepEqual(newSettings, wal.committedSettings) {
			// no need to write the settings file
			wal.fileSettingsTmp = nil
			return
		}
		wal.committedSettings = newSettings

		// Begin writing to the settings file, which will be synced during the
		// next iteration of the sync loop.
		var err error
		wal.fileSettingsTmp, err = wal.cm.dependencies.createFile(filepath.Join(wal.cm.persistDir, settingsFileTmp))
		if err != nil {
			wal.cm.log.Severe("Unable to open temporary settings file for writing:", err)
		}
		b, err := json.MarshalIndent(newSettings, "", "\t")
		if err != nil {
			build.ExtendErr("unable to marshal settings data", err)
		}
		enc := json.NewEncoder(wal.fileSettingsTmp)
		if err := enc.Encode(settingsMetadata.Header); err != nil {
			build.ExtendErr("unable to write header to settings temp file", err)
		}
		if err := enc.Encode(settingsMetadata.Version); err != nil {
			build.ExtendErr("unable to write version to settings temp file", err)
		}
		if _, err = wal.fileSettingsTmp.Write(b); err != nil {
			build.ExtendErr("unable to write data settings temp file", err)
		}
	}()

	// Begin writing new changes to the WAL.
	wg.Add(1)
	go func() {
		defer wg.Done()

		if len(wal.uncommittedChanges) == 0 {
			// no need to recreate wal
			return
		}

		// Extract any unfinished long-running jobs from the list of WAL items.
		unfinishedAdditions := findUnfinishedStorageFolderAdditions(wal.uncommittedChanges)
		unfinishedExtensions := findUnfinishedStorageFolderExtensions(wal.uncommittedChanges)

		// Recreate the wal file so that it can receive new updates.
		var err error
		walTmpName := filepath.Join(wal.cm.persistDir, walFileTmp)
		wal.fileWALTmp, err = wal.cm.dependencies.createFile(walTmpName)
		if err != nil {
			wal.cm.log.Severe("ERROR: unable to create write-ahead-log:", err)
		}
		// Write the metadata into the WAL.
		err = writeWALMetadata(wal.fileWALTmp)
		if err != nil {
			wal.cm.log.Severe("Unable to properly initialize WAL file, crashing to prevent corruption:", err)
		}

		// Append all of the remaining long running uncommitted changes to the WAL.
		wal.appendChange(stateChange{
			UnfinishedStorageFolderAdditions:  unfinishedAdditions,
			UnfinishedStorageFolderExtensions: unfinishedExtensions,
		})

		// Clear the set of uncommitted changes.
		wal.uncommittedChanges = nil
	}()
	wg.Wait()
}

// spawnSyncLoop prepares and establishes the loop which will be running in the
// background to coordinate disk syncronizations. Disk syncing is done in a
// background loop to help with performance, and to allow multiple things to
// modify the WAL simultaneously.
func (wal *writeAheadLog) spawnSyncLoop() (err error) {
	// Create a signal so we know when the sync loop has stopped, which means
	// there will be no more open commits.
	threadsStopped := make(chan struct{})
	syncLoopStopped := make(chan struct{})
	wal.syncChan = make(chan struct{})
	go wal.threadedSyncLoop(threadsStopped, syncLoopStopped)
	wal.cm.tg.AfterStop(func() {
		// Wait for another iteration of the sync loop, so that the in-progress
		// settings can be saved atomically to disk.
		wal.mu.Lock()
		syncChan := wal.syncChan
		wal.mu.Unlock()
		<-syncChan

		// Close the threadsStopped channel to let the sync loop know that all
		// calls to tg.Add() in the contract manager have cleaned up.
		close(threadsStopped)

		// Because this is being called in an 'AfterStop' routine, all open
		// calls to the contract manager should have completed, and all open
		// threads should have closed. The last call to change the contract
		// manager should have completed, so the number of uncommitted changes
		// should be zero.
		<-syncLoopStopped // Wait for the sync loop to signal proper termination.

		// Allow unclean shutdown to be simulated by disrupting the removal of
		// the WAL file.
		if !wal.cm.dependencies.disrupt("cleanWALFile") {
			err = wal.cm.dependencies.removeFile(filepath.Join(wal.cm.persistDir, walFile))
			if err != nil {
				wal.cm.log.Println("Error removing WAL during contract manager shutdown:", err)
			}
		}
	})
	return nil
}

// threadedSyncLoop is a background thread that occasionally commits the WAL to
// the state as an ACID transaction. This process can be very slow, so
// transactions to the contract manager are batched automatically and
// occasionally committed together.
func (wal *writeAheadLog) threadedSyncLoop(threadsStopped chan struct{}, syncLoopStopped chan struct{}) {
	// Provide a place for the testing to disable the sync loop.
	if wal.cm.dependencies.disrupt("threadedSyncLoopStart") {
		close(syncLoopStopped)
		return
	}

	syncInterval := 500 * time.Millisecond
	for {
		select {
		case <-threadsStopped:
			close(syncLoopStopped)
			return
		case <-time.After(syncInterval):
			// Commit all of the changes in the WAL to disk, and then apply the
			// changes.
			wal.mu.Lock()
			wal.commit()
			wal.mu.Unlock()
		}
	}
}
<|endoftext|>


<commit_before>package color

import (
	"strings"
	"sync"
	"unicode"
)

const (
	errInvalid = "%%!h(INVALID)" // invalid character in the highlight verb
	errMissing = "%%!h(MISSING)" // no attributes in the highlight verb
	errBadAttr = "%%!h(BADATTR)" // unknown attribute in the highlight verb
)

// highlighter holds the state of the scanner.
type highlighter struct {
	s     string // string being scanned
	pos   int    // position in s
	buf   buffer // where result is built
	attrs buffer // attributes of current verb
}

// shighlightf replaces the highlight verbs in s with their appropriate
// control sequences and then returns the resulting string.
func shighlightf(s string) string {
	hl := getHighlighter(s)
	defer hl.free()
	hl.run()
	s = string(hl.buf)
	return s
}

// highlighterPool allows the reuse of highlighters to avoid allocations.
var highlighterPool = sync.Pool{
	New: func() interface{} {
		hl := new(highlighter)
		// The initial capacities avoid constant reallocation during growth.
		hl.buf = make([]byte, 0, 30)
		hl.attrs = make([]byte, 0, 10)
		return hl
	},
}

// getHighlighter returns a new initialized highlighter from the pool.
func getHighlighter(s string) (hl *highlighter) {
	hl = highlighterPool.Get().(*highlighter)
	hl.s = s
	return
}

// free resets the highlighter.
func (hl *highlighter) free() {
	hl.buf.reset()
	hl.pos = 0
	highlighterPool.Put(hl)
}

// stateFn represents the state of the scanner as a function that returns the next state.
type stateFn func(*highlighter) stateFn

// run runs the state machine for the highlighter.
func (hl *highlighter) run() {
	for state := scanText; state != nil; {
		state = state(hl)
	}
}

const eof = -1

// get returns the current rune.
func (hl *highlighter) get() rune {
	if hl.pos >= len(hl.s) {
		return eof
	}
	return rune(hl.s[hl.pos])
}

// writeAttrs writes a control sequence derived from h.attrs[1:] to h.buf.
func (hl *highlighter) writeAttrs() {
	hl.buf.writeString(csi)
	hl.buf.write(hl.attrs[1:])
	hl.buf.writeByte('m')
}

// writePrev writes n previous characters to the buffer.
func (hl *highlighter) writePrev(n int) {
	hl.buf.writeString(hl.s[n:hl.pos])
}

// scanText scans until the next highlight or reset verb.
func scanText(hl *highlighter) stateFn {
	ppos := hl.pos
LOOP:
	// Find next verb.
	for {
		switch hl.get() {
		case eof:
			if hl.pos > ppos {
				// Append remaining characters.
				hl.writePrev(ppos)
			}
			return nil
		case '%':
			if hl.pos > ppos {
				// Append the characters after the last verb.
				hl.writePrev(ppos)
			}
			break LOOP

		}
		hl.pos++
	}
	hl.pos++
	// At the verb.
	switch hl.get() {
	case 'r':
		hl.pos++
		return verbReset
	case 'h':
		hl.pos += 2
		return scanHighlight
	case eof:
		// Let fmt handle "%!h(NOVERB)".
		hl.buf.writeByte('%')
		return nil
	}
	hl.pos++
	hl.writePrev(hl.pos - 2)
	return scanText
}

// verbReset writes the reset verb with the reset control sequence.
func verbReset(hl *highlighter) stateFn {
	hl.attrs.writeString(attrs["reset"])
	hl.writeAttrs()
	hl.attrs.reset()
	return scanText
}

// scanHighlight scans the highlight verb for attributes,
// then writes a control sequence derived from said attributes to the buffer.
func scanHighlight(hl *highlighter) stateFn {
	r := hl.get()
	switch {
	case r == 'f':
		return scanColor256(hl, preFg256)
	case r == 'b':
		return scanColor256(hl, preBg256)
	case unicode.IsLetter(r):
		return scanAttribute(hl, 0)
	case r == '+':
		hl.pos++
		return scanHighlight
	case r == ']':
		if len(hl.attrs) != 0 {
			hl.writeAttrs()
		} else {
			hl.buf.writeString(errMissing)
		}
		hl.attrs.reset()
		hl.pos++
		return scanText
	default:
		return abortHighlight(hl, errInvalid)
	}
}

// scanAttribute scans a named attribute.
func scanAttribute(hl *highlighter, off int) stateFn {
	start := hl.pos - off
	for unicode.IsLetter(hl.get()) {
		hl.pos++
	}
	if a, ok := attrs[hl.s[start:hl.pos]]; ok {
		hl.attrs.writeString(a)
	} else {
		return abortHighlight(hl, errBadAttr)
	}
	return scanHighlight
}

// abortHighlight writes a error to the buffer and
// then skips to the end of the highlight verb.
func abortHighlight(hl *highlighter, msg string) stateFn {
	hl.buf.writeString(msg)
	hl.attrs.reset()
	for {
		switch hl.get() {
		case ']':
			hl.pos++
			return scanText
		case eof:
			return nil
		}
		hl.pos++
	}
}

// scanColor256 scans a 256 color attribute.
func scanColor256(hl *highlighter, pre string) stateFn {
	hl.pos++
	if hl.get() != 'g' {
		return scanAttribute(hl, 1)
	}
	hl.pos++
	if !unicode.IsNumber(hl.get()) {
		return scanAttribute(hl, 2)
	}
	start := hl.pos
	hl.pos++
	for unicode.IsNumber(hl.get()) {
		hl.pos++
	}
	hl.attrs.writeString(pre)
	hl.attrs.writeString(hl.s[start:hl.pos])
	return scanHighlight
}

// bufferPool allows the reuse of buffers to avoid allocations.
var bufferPool = sync.Pool{
	New: func() interface{} {
		// The initial capacity avoids constant reallocation during growth.
		return buffer(make([]byte, 0, 30))
	},
}

// sstrip removes all highlight verbs in s.
func sstripf(s string) string {
	buf := bufferPool.Get().(buffer)
	// pi is the index after the last verb.
	var pi, i int
LOOP:
	for ; ; i++ {
		if i >= len(s) {
			if i > pi {
				buf.writeString(s[pi:i])
			}
			break
		} else if s[i] != '%' {
			continue
		}
		if i > pi {
			buf.writeString(s[pi:i])
		}
		i++
		if i >= len(s) {
			// Let fmt handle "%!h(NOVERB)".
			buf.writeByte('%')
			break
		}
		switch s[i] {
		case 'r':
			// Strip the reset verb.
			pi = i + 1
		case 'h':
			// Strip inside the highlight verb.
			j := strings.IndexByte(s[i+1:], ']')
			if j == -1 {
				buf.writeString(errInvalid)
				break LOOP
			}
			i += j + 1
			pi = i + 1
		default:
			// Include the verb.
			pi = i - 1
		}
	}
	s = string(buf)
	buf.reset()
	bufferPool.Put(buf)
	return s
}
<commit_msg>whoops, typo<commit_after>package color

import (
	"strings"
	"sync"
	"unicode"
)

const (
	errInvalid = "%%!h(INVALID)" // invalid character in the highlight verb
	errMissing = "%%!h(MISSING)" // no attributes in the highlight verb
	errBadAttr = "%%!h(BADATTR)" // unknown attribute in the highlight verb
)

// highlighter holds the state of the scanner.
type highlighter struct {
	s     string // string being scanned
	pos   int    // position in s
	buf   buffer // where result is built
	attrs buffer // attributes of current verb
}

// shighlightf replaces the highlight verbs in s with their appropriate
// control sequences and then returns the resulting string.
func shighlightf(s string) string {
	hl := getHighlighter(s)
	defer hl.free()
	hl.run()
	s = string(hl.buf)
	return s
}

// highlighterPool allows the reuse of highlighters to avoid allocations.
var highlighterPool = sync.Pool{
	New: func() interface{} {
		hl := new(highlighter)
		// The initial capacities avoid constant reallocation during growth.
		hl.buf = make([]byte, 0, 30)
		hl.attrs = make([]byte, 0, 10)
		return hl
	},
}

// getHighlighter returns a new initialized highlighter from the pool.
func getHighlighter(s string) (hl *highlighter) {
	hl = highlighterPool.Get().(*highlighter)
	hl.s = s
	return
}

// free resets the highlighter.
func (hl *highlighter) free() {
	hl.buf.reset()
	hl.pos = 0
	highlighterPool.Put(hl)
}

// stateFn represents the state of the scanner as a function that returns the next state.
type stateFn func(*highlighter) stateFn

// run runs the state machine for the highlighter.
func (hl *highlighter) run() {
	for state := scanText; state != nil; {
		state = state(hl)
	}
}

const eof = -1

// get returns the current rune.
func (hl *highlighter) get() rune {
	if hl.pos >= len(hl.s) {
		return eof
	}
	return rune(hl.s[hl.pos])
}

// writeAttrs writes a control sequence derived from h.attrs[1:] to h.buf.
func (hl *highlighter) writeAttrs() {
	hl.buf.writeString(csi)
	hl.buf.write(hl.attrs[1:])
	hl.buf.writeByte('m')
}

// writePrev writes n previous characters to the buffer.
func (hl *highlighter) writePrev(n int) {
	hl.buf.writeString(hl.s[n:hl.pos])
}

// scanText scans until the next highlight or reset verb.
func scanText(hl *highlighter) stateFn {
	ppos := hl.pos
LOOP:
	// Find next verb.
	for {
		switch hl.get() {
		case eof:
			if hl.pos > ppos {
				// Append remaining characters.
				hl.writePrev(ppos)
			}
			return nil
		case '%':
			if hl.pos > ppos {
				// Append the characters after the last verb.
				hl.writePrev(ppos)
			}
			break LOOP

		}
		hl.pos++
	}
	hl.pos++
	// At the verb.
	switch hl.get() {
	case 'r':
		hl.pos++
		return verbReset
	case 'h':
		hl.pos += 2
		return scanHighlight
	case eof:
		// Let fmt handle "%!h(NOVERB)".
		hl.buf.writeByte('%')
		return nil
	}
	hl.pos++
	hl.writePrev(hl.pos - 2)
	return scanText
}

// verbReset writes the reset verb with the reset control sequence.
func verbReset(hl *highlighter) stateFn {
	hl.attrs.writeString(attrs["reset"])
	hl.writeAttrs()
	hl.attrs.reset()
	return scanText
}

// scanHighlight scans the highlight verb for attributes,
// then writes a control sequence derived from said attributes to the buffer.
func scanHighlight(hl *highlighter) stateFn {
	r := hl.get()
	switch {
	case r == 'f':
		return scanColor256(hl, preFg256)
	case r == 'b':
		return scanColor256(hl, preBg256)
	case unicode.IsLetter(r):
		return scanAttribute(hl, 0)
	case r == '+':
		hl.pos++
		return scanHighlight
	case r == ']':
		if len(hl.attrs) != 0 {
			hl.writeAttrs()
		} else {
			hl.buf.writeString(errMissing)
		}
		hl.attrs.reset()
		hl.pos++
		return scanText
	default:
		return abortHighlight(hl, errInvalid)
	}
}

// scanAttribute scans a named attribute.
func scanAttribute(hl *highlighter, off int) stateFn {
	start := hl.pos - off
	for unicode.IsLetter(hl.get()) {
		hl.pos++
	}
	if a, ok := attrs[hl.s[start:hl.pos]]; ok {
		hl.attrs.writeString(a)
	} else {
		return abortHighlight(hl, errBadAttr)
	}
	return scanHighlight
}

// abortHighlight writes a error to the buffer and
// then skips to the end of the highlight verb.
func abortHighlight(hl *highlighter, msg string) stateFn {
	hl.buf.writeString(msg)
	hl.attrs.reset()
	for {
		switch hl.get() {
		case ']':
			hl.pos++
			return scanText
		case eof:
			return nil
		}
		hl.pos++
	}
}

// scanColor256 scans a 256 color attribute.
func scanColor256(hl *highlighter, pre string) stateFn {
	hl.pos++
	if hl.get() != 'g' {
		return scanAttribute(hl, 1)
	}
	hl.pos++
	if !unicode.IsNumber(hl.get()) {
		return scanAttribute(hl, 2)
	}
	start := hl.pos
	hl.pos++
	for unicode.IsNumber(hl.get()) {
		hl.pos++
	}
	hl.attrs.writeString(pre)
	hl.attrs.writeString(hl.s[start:hl.pos])
	return scanHighlight
}

// bufferPool allows the reuse of buffers to avoid allocations.
var bufferPool = sync.Pool{
	New: func() interface{} {
		// The initial capacity avoids constant reallocation during growth.
		return buffer(make([]byte, 0, 30))
	},
}

// sstripf removes all highlight verbs in s and then returns the resulting string.
func sstripf(s string) string {
	buf := bufferPool.Get().(buffer)
	// pi is the index after the last verb.
	var pi, i int
LOOP:
	for ; ; i++ {
		if i >= len(s) {
			if i > pi {
				buf.writeString(s[pi:i])
			}
			break
		} else if s[i] != '%' {
			continue
		}
		if i > pi {
			buf.writeString(s[pi:i])
		}
		i++
		if i >= len(s) {
			// Let fmt handle "%!h(NOVERB)".
			buf.writeByte('%')
			break
		}
		switch s[i] {
		case 'r':
			// Strip the reset verb.
			pi = i + 1
		case 'h':
			// Strip inside the highlight verb.
			j := strings.IndexByte(s[i+1:], ']')
			if j == -1 {
				buf.writeString(errInvalid)
				break LOOP
			}
			i += j + 1
			pi = i + 1
		default:
			// Include the verb.
			pi = i - 1
		}
	}
	s = string(buf)
	buf.reset()
	bufferPool.Put(buf)
	return s
}
<|endoftext|>


<commit_before>package cli

import (
	"os"

	g "github.com/onsi/ginkgo"
	o "github.com/onsi/gomega"

	exutil "github.com/openshift/origin/test/extended/util"
)

var _ = g.Describe("[sig-cli] oc observe", func() {
	defer g.GinkgoRecover()

	oc := exutil.NewCLIWithoutNamespace("oc-observe").AsAdmin()

	g.It("works as expected", func() {
		g.By("basic scenarios")
		out, err := oc.Run("observe").Output()
		o.Expect(err).To(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring("you must specify at least one argument containing the resource to observe"))

		out, err = oc.Run("observe").Args("serviceaccounts", "--once").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(out).To(o.Or(o.ContainSubstring("Sync ended"), o.ContainSubstring("Nothing to sync")))

		out, err = oc.Run("observe").Args("daemonsets", "--once").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(out).To(o.Or(o.ContainSubstring("Sync ended"), o.ContainSubstring("Nothing to sync, exiting immediately")))

		out, err = oc.Run("observe").Args("clusteroperators", "--once").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring("kube-apiserver"))

		out, err = oc.Run("observe").Args("services", "--once", "--all-namespaces").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring("default kubernetes"))

		out, err = oc.Run("observe").Args("services", "--once", "--all-namespaces", "--print-metrics-on-exit").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring(`observe_counts{type="Sync"}`))

		out, err = oc.Run("observe").Args("services", "--once", "--names", "echo").Output()
		o.Expect(err).To(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring("--delete and --names must both be specified"))

		out, err = oc.Run("observe").Args("services", "--exit-after=1s").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring("Shutting down after 1s ..."))

		out, err = oc.Run("observe").Args("services", "--exit-after=3s", "--all-namespaces", "--print-metrics-on-exit").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring(`observe_counts{type="Sync"}`))

		out, err = oc.Run("observe").Args("services", "--exit-after=3s", "--all-namespaces", "--names", "echo", "--names", "default/notfound", "--delete", "echo", "--delete", "remove").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring("remove default notfound"))

		g.By("error counting")
		out, err = oc.Run("observe").Args("services", "--exit-after=1m", "--all-namespaces", "--maximum-errors=1", "--", "/bin/sh", "-c", "exit 1").Output()
		o.Expect(err).To(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring("reached maximum error limit of 1, exiting"))

		out, err = oc.Run("observe").Args("services", "--exit-after=1m", "--all-namespaces", "--retry-on-exit-code=2", "--maximum-errors=1", "--loglevel=4", "--", "/bin/sh", "-c", "exit 2").Output()
		o.Expect(err).To(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring("retrying command: exit status 2"))

		g.By("argument templates")
		out, err = oc.Run("observe").Args("services", "--once", "--all-namespaces", "--template='{ .spec.clusterIP }'").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(out).To(o.Or(o.ContainSubstring("172.30.0.1"), o.ContainSubstring("fd02::1")))

		out, err = oc.Run("observe").Args("services", "--once", "--all-namespaces", "--template='{{ .spec.clusterIP }}'", "--output=go-template").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(out).To(o.Or(o.ContainSubstring("172.30.0.1"), o.ContainSubstring("fd02::1")))

		out, err = oc.Run("observe").Args("services", "--once", "--all-namespaces", "--template='bad{ .missingkey }key'").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring("badkey"))

		out, err = oc.Run("observe").Args("services", "--once", "--all-namespaces", "--template='bad{ .missingkey }key'", "--allow-missing-template-keys=false").Output()
		o.Expect(err).To(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring("missingkey is not found"))

		out, err = oc.Run("observe").Args("services", "--once", "--all-namespaces", "--template='{{ .unknown }}'", "--output=go-template").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring("default kubernetes"))

		out, err = oc.Run("observe").Args("services", "--once", "--all-namespaces", `--template='bad{{ or (.unknown) "" }}key'`, "--output=go-template").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring("badkey"))

		out, err = oc.Run("observe").Args("services", "--once", "--all-namespaces", "--template='bad{{ .unknown }}key'", "--output=go-template", "--allow-missing-template-keys=false").Output()
		o.Expect(err).To(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring("map has no entry for key"))

		g.By("event environment variables")
		o.Expect(os.Setenv("MYENV", "should_be_passed")).NotTo(o.HaveOccurred())
		out, err = oc.Run("observe").Args("services", "--once", "--all-namespaces", "--type-env-var=EVENT", "--", "/bin/sh", "-c", "echo $EVENT $MYENV").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring("Sync should_be_passed"))
		o.Expect(os.Unsetenv("MYENV")).NotTo(o.HaveOccurred())
	})
})
<commit_msg>Temporarily disable oc observe single test<commit_after>package cli

import (
	"os"

	g "github.com/onsi/ginkgo"
	o "github.com/onsi/gomega"

	exutil "github.com/openshift/origin/test/extended/util"
)

var _ = g.Describe("[sig-cli] oc observe", func() {
	defer g.GinkgoRecover()

	oc := exutil.NewCLIWithoutNamespace("oc-observe").AsAdmin()

	g.It("works as expected", func() {
		g.By("basic scenarios")
		out, err := oc.Run("observe").Output()
		o.Expect(err).To(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring("you must specify at least one argument containing the resource to observe"))

		out, err = oc.Run("observe").Args("serviceaccounts", "--once").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(out).To(o.Or(o.ContainSubstring("Sync ended"), o.ContainSubstring("Nothing to sync")))

		out, err = oc.Run("observe").Args("daemonsets", "--once").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(out).To(o.Or(o.ContainSubstring("Sync ended"), o.ContainSubstring("Nothing to sync, exiting immediately")))

		out, err = oc.Run("observe").Args("clusteroperators", "--once").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring("kube-apiserver"))

		out, err = oc.Run("observe").Args("services", "--once", "--all-namespaces").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring("default kubernetes"))

		out, err = oc.Run("observe").Args("services", "--once", "--all-namespaces", "--print-metrics-on-exit").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring(`observe_counts{type="Sync"}`))

		out, err = oc.Run("observe").Args("services", "--once", "--names", "echo").Output()
		o.Expect(err).To(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring("--delete and --names must both be specified"))

		out, err = oc.Run("observe").Args("services", "--exit-after=1s").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring("Shutting down after 1s ..."))

		out, err = oc.Run("observe").Args("services", "--exit-after=3s", "--all-namespaces", "--print-metrics-on-exit").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring(`observe_counts{type="Sync"}`))

		out, err = oc.Run("observe").Args("services", "--exit-after=3s", "--all-namespaces", "--names", "echo", "--names", "default/notfound", "--delete", "echo", "--delete", "remove").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring("remove default notfound"))

		g.By("error counting")
		out, err = oc.Run("observe").Args("services", "--exit-after=1m", "--all-namespaces", "--maximum-errors=1", "--", "/bin/sh", "-c", "exit 1").Output()
		o.Expect(err).To(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring("reached maximum error limit of 1, exiting"))

		out, err = oc.Run("observe").Args("services", "--exit-after=1m", "--all-namespaces", "--retry-on-exit-code=2", "--maximum-errors=1", "--loglevel=4", "--", "/bin/sh", "-c", "exit 2").Output()
		o.Expect(err).To(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring("retrying command: exit status 2"))

		g.By("argument templates")
		out, err = oc.Run("observe").Args("services", "--once", "--all-namespaces", "--template='{ .spec.clusterIP }'").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(out).To(o.Or(o.ContainSubstring("172.30.0.1"), o.ContainSubstring("fd02::1")))

		out, err = oc.Run("observe").Args("services", "--once", "--all-namespaces", "--template='{{ .spec.clusterIP }}'", "--output=go-template").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(out).To(o.Or(o.ContainSubstring("172.30.0.1"), o.ContainSubstring("fd02::1")))

		// https://bugzilla.redhat.com/show_bug.cgi?id=1989505
		// out, err = oc.Run("observe").Args("services", "--once", "--all-namespaces", "--template='bad{ .missingkey }key'").Output()
		// o.Expect(err).NotTo(o.HaveOccurred())
		// o.Expect(out).To(o.ContainSubstring("badkey"))

		out, err = oc.Run("observe").Args("services", "--once", "--all-namespaces", "--template='bad{ .missingkey }key'", "--allow-missing-template-keys=false").Output()
		o.Expect(err).To(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring("missingkey is not found"))

		out, err = oc.Run("observe").Args("services", "--once", "--all-namespaces", "--template='{{ .unknown }}'", "--output=go-template").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring("default kubernetes"))

		out, err = oc.Run("observe").Args("services", "--once", "--all-namespaces", `--template='bad{{ or (.unknown) "" }}key'`, "--output=go-template").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring("badkey"))

		out, err = oc.Run("observe").Args("services", "--once", "--all-namespaces", "--template='bad{{ .unknown }}key'", "--output=go-template", "--allow-missing-template-keys=false").Output()
		o.Expect(err).To(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring("map has no entry for key"))

		g.By("event environment variables")
		o.Expect(os.Setenv("MYENV", "should_be_passed")).NotTo(o.HaveOccurred())
		out, err = oc.Run("observe").Args("services", "--once", "--all-namespaces", "--type-env-var=EVENT", "--", "/bin/sh", "-c", "echo $EVENT $MYENV").Output()
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(out).To(o.ContainSubstring("Sync should_be_passed"))
		o.Expect(os.Unsetenv("MYENV")).NotTo(o.HaveOccurred())
	})
})
<|endoftext|>


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

package hello_test

import (
	"fmt"
	"os"
	"time"

	"v.io/x/ref"
	"v.io/x/ref/lib/security"
	_ "v.io/x/ref/runtime/factories/generic"
	"v.io/x/ref/test/modules"
	"v.io/x/ref/test/testutil"
	"v.io/x/ref/test/v23tests"
)

//go:generate jiri test generate

func init() {
	ref.EnvClearCredentials()
}

var opts = modules.StartOpts{
	StartTimeout:    20 * time.Second,
	ShutdownTimeout: 20 * time.Second,
	ExpectTimeout:   20 * time.Second,
	ExecProtocol:    false,
	External:        true,
}

// setupCredentials makes a bunch of credentials directories.
// Note that I do this myself instead of allowing the test framework
// to do it because I really want to use the agentd binary, not
// the agent that is locally hosted inside v23Tests.T.
// This is important for regression tests where we want to test against
// old agent binaries.
func setupCredentials(i *v23tests.T, names ...string) (map[string]string, error) {
	idp := testutil.NewIDProvider("root")
	out := make(map[string]string, len(names))
	for _, name := range names {
		dir := i.NewTempDir("")
		p, err := security.CreatePersistentPrincipal(dir, nil)
		if err != nil {
			return nil, err
		}
		if err := idp.Bless(p, name); err != nil {
			return nil, err
		}
		out[name] = fmt.Sprintf("%s=%s", ref.EnvCredentials, dir)
	}
	return out, nil
}

func V23TestHelloDirect(i *v23tests.T) {
	creds, err := setupCredentials(i, "helloclient", "helloserver")
	if err != nil {
		i.Fatalf("Could not create credentials: %v", err)
	}
	clientbin := i.BuildGoPkg("v.io/x/ref/test/hello/helloclient")
	serverbin := i.BuildGoPkg("v.io/x/ref/test/hello/helloserver")
	server := serverbin.WithStartOpts(opts).WithEnv(creds["helloserver"]).Start()
	name := server.ExpectVar("SERVER_NAME")
	if server.Failed() {
		server.Wait(os.Stdout, os.Stderr)
		i.Fatalf("Could not get SERVER_NAME: %v", server.Error())
	}
	clientbin.WithEnv(creds["helloclient"]).WithStartOpts(opts).Run("--name", name)
}

func V23TestHelloAgentd(i *v23tests.T) {
	creds, err := setupCredentials(i, "helloclient", "helloserver")
	if err != nil {
		i.Fatalf("Could not create credentials: %v", err)
	}
	agentdbin := i.BuildGoPkg("v.io/x/ref/services/agent/agentd").WithStartOpts(opts)
	serverbin := i.BuildGoPkg("v.io/x/ref/test/hello/helloserver")
	clientbin := i.BuildGoPkg("v.io/x/ref/test/hello/helloclient")
	server := agentdbin.WithEnv(creds["helloserver"]).Start(serverbin.Path())
	name := server.ExpectVar("SERVER_NAME")
	if server.Failed() {
		server.Wait(os.Stdout, os.Stderr)
		i.Fatalf("Could not get SERVER_NAME: %v", server.Error())
	}
	agentdbin.WithEnv(creds["helloclient"]).Run(clientbin.Path(), "--name", name)
}

func V23TestHelloMounttabled(i *v23tests.T) {
	creds, err := setupCredentials(i, "helloclient", "helloserver", "mounttabled")
	if err != nil {
		i.Fatalf("Could not create credentials: %v", err)
	}
	agentdbin := i.BuildGoPkg("v.io/x/ref/services/agent/agentd").WithStartOpts(opts)
	mounttabledbin := i.BuildGoPkg("v.io/x/ref/services/mounttable/mounttabled")
	serverbin := i.BuildGoPkg("v.io/x/ref/test/hello/helloserver")
	clientbin := i.BuildGoPkg("v.io/x/ref/test/hello/helloclient")
	name := "hello"
	mounttabled := agentdbin.WithEnv(creds["mounttabled"]).Start(mounttabledbin.Path(),
		"--v23.tcp.address", "127.0.0.1:0")
	mtname := mounttabled.ExpectVar("NAME")
	if mounttabled.Failed() {
		mounttabled.Wait(os.Stdout, os.Stderr)
		i.Fatalf("Could not get NAME: %v", mounttabled.Error())
	}
	agentdbin.WithEnv(creds["helloserver"]).Start(serverbin.Path(), "--name", name,
		"--v23.namespace.root", mtname)
	agentdbin.WithEnv(creds["helloclient"]).Run(clientbin.Path(), "--name", name,
		"--v23.namespace.root", mtname)
}

func V23TestHelloProxy(i *v23tests.T) {
	creds, err := setupCredentials(i, "helloclient", "helloserver",
		"mounttabled", "proxyd")
	if err != nil {
		i.Fatalf("Could not create credentials: %v", err)
	}
	agentdbin := i.BuildGoPkg("v.io/x/ref/services/agent/agentd").WithStartOpts(opts)
	mounttabledbin := i.BuildGoPkg("v.io/x/ref/services/mounttable/mounttabled")
	var proxydbin *v23tests.Binary
	if ref.RPCTransitionState() >= ref.XServers {
		proxydbin = i.BuildGoPkg("v.io/x/ref/services/xproxy/xproxyd")
	} else {
		proxydbin = i.BuildGoPkg("v.io/x/ref/services/proxy/proxyd")
	}
	serverbin := i.BuildGoPkg("v.io/x/ref/test/hello/helloserver")
	clientbin := i.BuildGoPkg("v.io/x/ref/test/hello/helloclient")
	proxyname := "proxy"
	name := "hello"
	mounttabled := agentdbin.WithEnv(creds["mounttabled"]).Start(mounttabledbin.Path(),
		"--v23.tcp.address", "127.0.0.1:0")
	mtname := mounttabled.ExpectVar("NAME")
	if mounttabled.Failed() {
		mounttabled.Wait(os.Stdout, os.Stderr)
		i.Fatalf("Could not get NAME: %v", mounttabled.Error())
	}
	agentdbin.WithEnv(creds["proxyd"]).Start(proxydbin.Path(),
		"--name", proxyname, "--v23.tcp.address", "127.0.0.1:0",
		"--v23.namespace.root", mtname,
		"--access-list", "{\"In\":[\"root\"]}")
	agentdbin.WithEnv(creds["helloserver"]).Start(serverbin.Path(),
		"--name", name, "--v23.proxy", proxyname, "--v23.tcp.address", "",
		"--v23.namespace.root", mtname)
	agentdbin.WithEnv(creds["helloclient"]).Run(clientbin.Path(), "--name", name,
		"--v23.namespace.root", mtname)
}
<commit_msg>ref/test: Fix the regression test by starting both proxies, not one or the other.<commit_after>// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package hello_test

import (
	"fmt"
	"os"
	"time"

	"v.io/x/ref"
	"v.io/x/ref/lib/security"
	_ "v.io/x/ref/runtime/factories/generic"
	"v.io/x/ref/test/modules"
	"v.io/x/ref/test/testutil"
	"v.io/x/ref/test/v23tests"
)

//go:generate jiri test generate

func init() {
	ref.EnvClearCredentials()
}

var opts = modules.StartOpts{
	StartTimeout:    20 * time.Second,
	ShutdownTimeout: 20 * time.Second,
	ExpectTimeout:   20 * time.Second,
	ExecProtocol:    false,
	External:        true,
}

// setupCredentials makes a bunch of credentials directories.
// Note that I do this myself instead of allowing the test framework
// to do it because I really want to use the agentd binary, not
// the agent that is locally hosted inside v23Tests.T.
// This is important for regression tests where we want to test against
// old agent binaries.
func setupCredentials(i *v23tests.T, names ...string) (map[string]string, error) {
	idp := testutil.NewIDProvider("root")
	out := make(map[string]string, len(names))
	for _, name := range names {
		dir := i.NewTempDir("")
		p, err := security.CreatePersistentPrincipal(dir, nil)
		if err != nil {
			return nil, err
		}
		if err := idp.Bless(p, name); err != nil {
			return nil, err
		}
		out[name] = fmt.Sprintf("%s=%s", ref.EnvCredentials, dir)
	}
	return out, nil
}

func V23TestHelloDirect(i *v23tests.T) {
	creds, err := setupCredentials(i, "helloclient", "helloserver")
	if err != nil {
		i.Fatalf("Could not create credentials: %v", err)
	}
	clientbin := i.BuildGoPkg("v.io/x/ref/test/hello/helloclient")
	serverbin := i.BuildGoPkg("v.io/x/ref/test/hello/helloserver")
	server := serverbin.WithStartOpts(opts).WithEnv(creds["helloserver"]).Start()
	name := server.ExpectVar("SERVER_NAME")
	if server.Failed() {
		server.Wait(os.Stdout, os.Stderr)
		i.Fatalf("Could not get SERVER_NAME: %v", server.Error())
	}
	clientbin.WithEnv(creds["helloclient"]).WithStartOpts(opts).Run("--name", name)
}

func V23TestHelloAgentd(i *v23tests.T) {
	creds, err := setupCredentials(i, "helloclient", "helloserver")
	if err != nil {
		i.Fatalf("Could not create credentials: %v", err)
	}
	agentdbin := i.BuildGoPkg("v.io/x/ref/services/agent/agentd").WithStartOpts(opts)
	serverbin := i.BuildGoPkg("v.io/x/ref/test/hello/helloserver")
	clientbin := i.BuildGoPkg("v.io/x/ref/test/hello/helloclient")
	server := agentdbin.WithEnv(creds["helloserver"]).Start(serverbin.Path())
	name := server.ExpectVar("SERVER_NAME")
	if server.Failed() {
		server.Wait(os.Stdout, os.Stderr)
		i.Fatalf("Could not get SERVER_NAME: %v", server.Error())
	}
	agentdbin.WithEnv(creds["helloclient"]).Run(clientbin.Path(), "--name", name)
}

func V23TestHelloMounttabled(i *v23tests.T) {
	creds, err := setupCredentials(i, "helloclient", "helloserver", "mounttabled")
	if err != nil {
		i.Fatalf("Could not create credentials: %v", err)
	}
	agentdbin := i.BuildGoPkg("v.io/x/ref/services/agent/agentd").WithStartOpts(opts)
	mounttabledbin := i.BuildGoPkg("v.io/x/ref/services/mounttable/mounttabled")
	serverbin := i.BuildGoPkg("v.io/x/ref/test/hello/helloserver")
	clientbin := i.BuildGoPkg("v.io/x/ref/test/hello/helloclient")
	name := "hello"
	mounttabled := agentdbin.WithEnv(creds["mounttabled"]).Start(mounttabledbin.Path(),
		"--v23.tcp.address", "127.0.0.1:0")
	mtname := mounttabled.ExpectVar("NAME")
	if mounttabled.Failed() {
		mounttabled.Wait(os.Stdout, os.Stderr)
		i.Fatalf("Could not get NAME: %v", mounttabled.Error())
	}
	agentdbin.WithEnv(creds["helloserver"]).Start(serverbin.Path(), "--name", name,
		"--v23.namespace.root", mtname)
	agentdbin.WithEnv(creds["helloclient"]).Run(clientbin.Path(), "--name", name,
		"--v23.namespace.root", mtname)
}

func V23TestHelloProxy(i *v23tests.T) {
	creds, err := setupCredentials(i, "helloclient", "helloserver",
		"mounttabled", "proxyd", "xproxyd")
	if err != nil {
		i.Fatalf("Could not create credentials: %v", err)
	}
	agentdbin := i.BuildGoPkg("v.io/x/ref/services/agent/agentd").WithStartOpts(opts)
	mounttabledbin := i.BuildGoPkg("v.io/x/ref/services/mounttable/mounttabled")
	xproxydbin := i.BuildGoPkg("v.io/x/ref/services/xproxy/xproxyd")
	proxydbin := i.BuildGoPkg("v.io/x/ref/services/proxy/proxyd")
	serverbin := i.BuildGoPkg("v.io/x/ref/test/hello/helloserver")
	clientbin := i.BuildGoPkg("v.io/x/ref/test/hello/helloclient")
	proxyname := "proxy"
	name := "hello"
	mounttabled := agentdbin.WithEnv(creds["mounttabled"]).Start(mounttabledbin.Path(),
		"--v23.tcp.address", "127.0.0.1:0")
	mtname := mounttabled.ExpectVar("NAME")
	if mounttabled.Failed() {
		mounttabled.Wait(os.Stdout, os.Stderr)
		i.Fatalf("Could not get NAME: %v", mounttabled.Error())
	}
	agentdbin.WithEnv(creds["proxyd"]).Start(proxydbin.Path(),
		"--name", proxyname, "--v23.tcp.address", "127.0.0.1:0",
		"--v23.namespace.root", mtname,
		"--access-list", "{\"In\":[\"root\"]}")
	agentdbin.WithEnv(creds["xproxyd"]).Start(xproxydbin.Path(),
		"--name", proxyname, "--v23.tcp.address", "127.0.0.1:0",
		"--v23.namespace.root", mtname,
		"--access-list", "{\"In\":[\"root\"]}")
	agentdbin.WithEnv(creds["helloserver"]).Start(serverbin.Path(),
		"--name", name, "--v23.proxy", proxyname, "--v23.tcp.address", "",
		"--v23.namespace.root", mtname)
	agentdbin.WithEnv(creds["helloclient"]).Run(clientbin.Path(), "--name", name,
		"--v23.namespace.root", mtname)
}
<|endoftext|>


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

package main

import (
	"../lib/twodee"
)

type UiState interface {
	Register(level *Level)
	Unregister(level *Level)
	HandleEvent(level *Level, evt twodee.Event) UiState
}

type BaseUiState struct {
}

func (s BaseUiState) HandleEvent(level *Level, evt twodee.Event) UiState {
	switch event := evt.(type) {
	case *twodee.MouseMoveEvent:
		level.SetMouse(event.X, event.Y)
	case *twodee.KeyEvent:
		if event.Type == twodee.Press {
			code := int(event.Code - twodee.Key1)
			if code >= 0 && code < 9 && code < len(HudBlocks) {
				return NewBlockUiState(HudBlocks[code])
			}
			switch event.Code {
			case twodee.Key0:
				return NewNormalUiState()
			}
		}
	}
	return nil
}

type NormalUiState struct {
	BaseUiState
}

func NewNormalUiState() UiState {
	return &NormalUiState{}
}

func (s *NormalUiState) Register(level *Level) {
	level.SetCursor("mouse_00")
}

func (s *NormalUiState) Unregister(level *Level) {
}

func (s *NormalUiState) HandleEvent(level *Level, evt twodee.Event) UiState {
	if state := s.BaseUiState.HandleEvent(level, evt); state != nil {
		return state
	}
	switch event := evt.(type) {
	case *twodee.MouseButtonEvent:
		if event.Type == twodee.Press && event.Button == twodee.MouseButtonLeft {
			level.AddMob(level.GetMouse())
		}
	}
	return nil
}

type BlockUiState struct {
	BaseUiState
	target  *Block
	variant int
}

func NewBlockUiState(target *Block) UiState {
	return &BlockUiState{
		target:  target,
		variant: 0,
	}
}

func (s *BlockUiState) Register(level *Level) {
	level.SetCursor("mouse_01")
	level.SetHighlights(level.GetMouse(), s.target, s.variant)
}

func (s *BlockUiState) Unregister(level *Level) {
	level.UnsetHighlights()
}

func (s *BlockUiState) HandleEvent(level *Level, evt twodee.Event) UiState {
	if state := s.BaseUiState.HandleEvent(level, evt); state != nil {
		return state
	}
	switch event := evt.(type) {
	case *twodee.MouseMoveEvent:
		level.SetHighlights(level.GetMouse(), s.target, s.variant)
	case *twodee.MouseButtonEvent:
		if event.Type == twodee.Press && event.Button == twodee.MouseButtonLeft {
			if s.target.Cost <= level.State.Geld {
				level.State.Geld = level.State.Geld - s.target.Cost
				level.SetBlock(level.GetMouse(), s.target, s.variant)
			}
		}
	case *twodee.KeyEvent:
		if event.Type == twodee.Press {
			switch event.Code {
			case twodee.KeyR:
				s.variant = (s.variant + 1) % len(s.target.Variants)
				level.SetHighlights(level.GetMouse(), s.target, s.variant)
			}
		}
	}
	return nil
}
<commit_msg>Only drop mobs in debug mode<commit_after>// Copyright 2015 Pikkpoiss
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"../lib/twodee"
)

type UiState interface {
	Register(level *Level)
	Unregister(level *Level)
	HandleEvent(level *Level, evt twodee.Event) UiState
}

type BaseUiState struct {
}

func (s BaseUiState) HandleEvent(level *Level, evt twodee.Event) UiState {
	switch event := evt.(type) {
	case *twodee.MouseMoveEvent:
		level.SetMouse(event.X, event.Y)
	case *twodee.KeyEvent:
		if event.Type == twodee.Press {
			code := int(event.Code - twodee.Key1)
			if code >= 0 && code < 9 && code < len(HudBlocks) {
				return NewBlockUiState(HudBlocks[code])
			}
			switch event.Code {
			case twodee.Key0:
				return NewNormalUiState()
			}
		}
	}
	return nil
}

type NormalUiState struct {
	BaseUiState
}

func NewNormalUiState() UiState {
	return &NormalUiState{}
}

func (s *NormalUiState) Register(level *Level) {
	level.SetCursor("mouse_00")
}

func (s *NormalUiState) Unregister(level *Level) {
}

func (s *NormalUiState) HandleEvent(level *Level, evt twodee.Event) UiState {
	if state := s.BaseUiState.HandleEvent(level, evt); state != nil {
		return state
	}
	switch event := evt.(type) {
	case *twodee.MouseButtonEvent:
		if event.Type == twodee.Press && event.Button == twodee.MouseButtonLeft {
			if level.State.Debug {
				level.AddMob(level.GetMouse())
			}
		}
	}
	return nil
}

type BlockUiState struct {
	BaseUiState
	target  *Block
	variant int
}

func NewBlockUiState(target *Block) UiState {
	return &BlockUiState{
		target:  target,
		variant: 0,
	}
}

func (s *BlockUiState) Register(level *Level) {
	level.SetCursor("mouse_01")
	level.SetHighlights(level.GetMouse(), s.target, s.variant)
}

func (s *BlockUiState) Unregister(level *Level) {
	level.UnsetHighlights()
}

func (s *BlockUiState) HandleEvent(level *Level, evt twodee.Event) UiState {
	if state := s.BaseUiState.HandleEvent(level, evt); state != nil {
		return state
	}
	switch event := evt.(type) {
	case *twodee.MouseMoveEvent:
		level.SetHighlights(level.GetMouse(), s.target, s.variant)
	case *twodee.MouseButtonEvent:
		if event.Type == twodee.Press && event.Button == twodee.MouseButtonLeft {
			if s.target.Cost <= level.State.Geld {
				level.State.Geld = level.State.Geld - s.target.Cost
				level.SetBlock(level.GetMouse(), s.target, s.variant)
			}
		}
	case *twodee.KeyEvent:
		if event.Type == twodee.Press {
			switch event.Code {
			case twodee.KeyR:
				s.variant = (s.variant + 1) % len(s.target.Variants)
				level.SetHighlights(level.GetMouse(), s.target, s.variant)
			}
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package common

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
)

type GitHubRequestService struct {
	APIKeyChain *GitHubAPIKeyChain
}

func NewGitHubRequestService() *GitHubRequestService {
	newGitHubRequestService := GitHubRequestService{}
	newGitHubRequestService.APIKeyChain = NewGitHubAPIKeyChain()

	return &newGitHubRequestService
}

func (gitHubRequestService *GitHubRequestService) FetchGitHubDataForPackageModel(packageModel PackageModel) (map[string]interface{}, error) {
	APIKeyModel := gitHubRequestService.APIKeyChain.getAPIKeyModel()
	log.Println(APIKeyModel)
	fmt.Printf("%+v \n", APIKeyModel)
	log.Printf("Determining APIKey %s \n", APIKeyModel.Key)
	githubURL := buildGithubAPIURL(packageModel, *APIKeyModel)
	log.Printf("Fetching GitHub data for %s \n", githubURL)

	resp, err := http.Get(githubURL)
	defer resp.Body.Close()
	// TODO Drop 404s
	// resp.StatusCode != 200 check for 404s
	if err != nil {
		log.Printf("PANIC %v \n", err)
		log.Printf("STATUS CODE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! %d", resp.StatusCode)
	}

	responseHeader := resp.Header
	remaingRequests := responseHeader.Get("X-RateLimit-Remaining")
	rateLimitResetTime := responseHeader.Get("X-RateLimit-Reset")
	APIKeyModel.incrementUsage(remaingRequests, rateLimitResetTime)
	log.Printf("Rate limit reset time %s \n", rateLimitResetTime)
	log.Printf("Rate limit remaining requests %s \n", remaingRequests)
	APIKeyModel.print()

	// Parse Body Values
	responseBodyMap, err := parseResponseBody(resp)
	if err != nil {
		log.Printf("PANIC %v \n", err)
		os.Exit(3)
	}

	return responseBodyMap, nil
}

func buildGithubAPIURL(packageModel PackageModel, APIKeyModel GitHubAPIKeyModel) string {
	author := packageModel.Author
	repo := packageModel.Repo
	url := "https://api.github.com/repos/" + *author + "/" + *repo + "?access_token=" + APIKeyModel.Key
	return url
}

type GitHubPackageModelDTO struct {
	Package      PackageModel
	ResponseBody map[string]interface{}
}

func parseResponseBody(response *http.Response) (map[string]interface{}, error) {
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		log.Printf("PANIC %v \n", err)
		os.Exit(3)
	}

	var bodyMap map[string]interface{}
	err = json.Unmarshal(body, &bodyMap)
	if err != nil {
		log.Printf("PANIC %v \n", err)
		os.Exit(3)
	}

	return bodyMap, nil
}
<commit_msg>return error on 404<commit_after>package common

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
)

type GitHubRequestService struct {
	APIKeyChain *GitHubAPIKeyChain
}

func NewGitHubRequestService() *GitHubRequestService {
	newGitHubRequestService := GitHubRequestService{}
	newGitHubRequestService.APIKeyChain = NewGitHubAPIKeyChain()

	return &newGitHubRequestService
}

func (gitHubRequestService *GitHubRequestService) FetchGitHubDataForPackageModel(packageModel PackageModel) (map[string]interface{}, error) {
	APIKeyModel := gitHubRequestService.APIKeyChain.getAPIKeyModel()
	log.Println(APIKeyModel)
	fmt.Printf("%+v \n", APIKeyModel)
	log.Printf("Determining APIKey %s \n", APIKeyModel.Key)
	githubURL := buildGithubAPIURL(packageModel, *APIKeyModel)
	log.Printf("Fetching GitHub data for %s \n", githubURL)

	resp, err := http.Get(githubURL)
	defer resp.Body.Close()
	// TODO Drop 404s
	// resp.StatusCode != 200 check for 404s
	if err != nil {
		log.Printf("PANIC %v \n", err)
		log.Printf("STATUS CODE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! %d", resp.StatusCode)
	}

	if resp.StatusCode == 404 {
		return nil, errors.New("Package does not exist")
	}

	responseHeader := resp.Header
	remaingRequests := responseHeader.Get("X-RateLimit-Remaining")
	rateLimitResetTime := responseHeader.Get("X-RateLimit-Reset")
	APIKeyModel.incrementUsage(remaingRequests, rateLimitResetTime)
	log.Printf("Rate limit reset time %s \n", rateLimitResetTime)
	log.Printf("Rate limit remaining requests %s \n", remaingRequests)
	APIKeyModel.print()

	// Parse Body Values
	responseBodyMap, err := parseResponseBody(resp)
	if err != nil {
		log.Printf("PANIC %v \n", err)
		os.Exit(3)
	}

	return responseBodyMap, nil
}

func buildGithubAPIURL(packageModel PackageModel, APIKeyModel GitHubAPIKeyModel) string {
	author := packageModel.Author
	repo := packageModel.Repo
	url := "https://api.github.com/repos/" + *author + "/" + *repo + "?access_token=" + APIKeyModel.Key
	return url
}

type GitHubPackageModelDTO struct {
	Package      PackageModel
	ResponseBody map[string]interface{}
}

func parseResponseBody(response *http.Response) (map[string]interface{}, error) {
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		log.Printf("PANIC %v \n", err)
		os.Exit(3)
	}

	var bodyMap map[string]interface{}
	err = json.Unmarshal(body, &bodyMap)
	if err != nil {
		log.Printf("PANIC %v \n", err)
		os.Exit(3)
	}

	return bodyMap, nil
}
<|endoftext|>


<commit_before>package common

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
	"time"

	"github.com/skeswa/gophr/common/models"
)

type GitHubRequestService struct {
	APIKeyChain *GitHubAPIKeyChain
}

func NewGitHubRequestService() *GitHubRequestService {
	newGitHubRequestService := GitHubRequestService{}
	newGitHubRequestService.APIKeyChain = NewGitHubAPIKeyChain()

	return &newGitHubRequestService
}

func (gitHubRequestService *GitHubRequestService) FetchGitHubDataForPackageModel(packageModel models.PackageModel) (map[string]interface{}, error) {
	APIKeyModel := gitHubRequestService.APIKeyChain.getAPIKeyModel()
	log.Println(APIKeyModel)
	fmt.Printf("%+v \n", APIKeyModel)
	log.Printf("Determining APIKey %s \n", APIKeyModel.Key)
	githubURL := buildGithubAPIURL(packageModel, *APIKeyModel)
	log.Printf("Fetching GitHub data for %s \n", githubURL)

	resp, err := http.Get(githubURL)
	defer resp.Body.Close()

	if err != nil {
		return nil, errors.New("Request error.")
	}

	if resp.StatusCode == 404 {
		log.Println("PackageModel was not found on Github")
		return nil, nil
	}

	responseHeader := resp.Header
	remaingRequests := responseHeader.Get("X-RateLimit-Remaining")
	rateLimitResetTime := responseHeader.Get("X-RateLimit-Reset")
	APIKeyModel.incrementUsage(remaingRequests, rateLimitResetTime)
	log.Printf("Rate limit reset time %s \n", rateLimitResetTime)
	log.Printf("Rate limit remaining requests %s \n", remaingRequests)
	APIKeyModel.print()

	// Parse Body Values
	responseBodyMap, err := parseResponseBody(resp)
	if err != nil {
		return nil, err
	}

	return responseBodyMap, nil
}

func (gitHubRequestService *GitHubRequestService) FetchCommitByDateRangeForPackageModel(packageModel models.PackageModel, timestamp time.Time) (string, error) {
	APIKeyModel := gitHubRequestService.APIKeyChain.getAPIKeyModel()
	log.Println(APIKeyModel)
	fmt.Printf("%+v \n", APIKeyModel)
	log.Printf("Determining APIKey %s \n", APIKeyModel.Key)

	githubURL := buildGitHubRepoCommitsFromTimestampAPIURL(packageModel, *APIKeyModel, timestamp)
	log.Printf("Fetching GitHub data for %s \n", githubURL)

	resp, err := http.Get(githubURL)
	defer resp.Body.Close()

	if err != nil {
		return "", errors.New("Request error.")
	}

	if resp.StatusCode == 404 {
		log.Println("PackageModel was not found on Github")
		return "", nil
	}

	responseHeader := resp.Header
	remaingRequests := responseHeader.Get("X-RateLimit-Remaining")
	rateLimitResetTime := responseHeader.Get("X-RateLimit-Reset")
	APIKeyModel.incrementUsage(remaingRequests, rateLimitResetTime)
	log.Printf("Rate limit reset time %s \n", rateLimitResetTime)
	log.Printf("Rate limit remaining requests %s \n", remaingRequests)
	APIKeyModel.print()

	// Parse Body Values
	responseBodyMap, err := parseRespBody(resp)
	if err != nil {
		return "", err
	}

	return string(responseBodyMap[0]["sha"].(string)), nil
}

// TODO potentially return error here
func buildGithubAPIURL(packageModel models.PackageModel, APIKeyModel GitHubAPIKeyModel) string {
	author := *packageModel.Author
	repo := *packageModel.Repo
	url := fmt.Sprintf("https://api.github.com/repos/%s/%s?access_token=%s", author, repo, APIKeyModel.Key)
	return url
}

func buildGitHubRepoCommitsFromTimestampAPIURL(packageModel models.PackageModel, APIKeyModel GitHubAPIKeyModel, timestamp time.Time) string {
	author := *packageModel.Author
	repo := *packageModel.Repo

	url := fmt.Sprintf("https://api.github.com/repos/%s/%s/commits?until=%s&access_token=%s", author, repo, strings.Replace(timestamp.String(), " ", "", -1), APIKeyModel.Key)
	log.Println("URL = ", url)
	return url
}

func parseResponseBody(response *http.Response) (map[string]interface{}, error) {
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, errors.New("Failed to parse response body")
	}

	var bodyMap map[string]interface{}
	err = json.Unmarshal(body, &bodyMap)
	if err != nil {
		return nil, errors.New("Failed to unmarshal response body")
	}

	return bodyMap, nil
}

func parseRespBody(response *http.Response) ([]map[string]interface{}, error) {
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, errors.New("Failed to parse response body")
	}

	var bodyMap []map[string]interface{}
	err = json.Unmarshal(body, &bodyMap)
	if err != nil {
		return nil, errors.New("Failed to unmarshal response body")
	}

	return bodyMap, nil
}

func ParseStarCount(responseBody map[string]interface{}) int {
	starCount := responseBody["stargazers_count"]
	if starCount == nil {
		return 0
	}

	return int(starCount.(float64))
}

type GitHubPackageModelDTO struct {
	Package      models.PackageModel
	ResponseBody map[string]interface{}
}
<commit_msg>cleaned up the github request library and added some todos<commit_after>package common

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
	"time"

	"github.com/skeswa/gophr/common/dtos"
	"github.com/skeswa/gophr/common/models"
)

type GitHubRequestService struct {
	APIKeyChain *GitHubAPIKeyChain
}

func NewGitHubRequestService() *GitHubRequestService {
	newGitHubRequestService := GitHubRequestService{}
	newGitHubRequestService.APIKeyChain = NewGitHubAPIKeyChain()

	return &newGitHubRequestService
}

func (gitHubRequestService *GitHubRequestService) FetchGitHubDataForPackageModel(packageModel models.PackageModel) (map[string]interface{}, error) {
	APIKeyModel := gitHubRequestService.APIKeyChain.getAPIKeyModel()
	log.Println(APIKeyModel)
	fmt.Printf("%+v \n", APIKeyModel)
	log.Printf("Determining APIKey %s \n", APIKeyModel.Key)
	githubURL := buildGitHubRepoDataAPIURL(packageModel, *APIKeyModel)
	log.Printf("Fetching GitHub data for %s \n", githubURL)

	resp, err := http.Get(githubURL)
	defer resp.Body.Close()

	if err != nil {
		return nil, errors.New("Request error.")
	}

	if resp.StatusCode == 404 {
		log.Println("PackageModel was not found on Github")
		return nil, nil
	}

	APIKeyModel.incrementUsageFromResponseHeader(resp.Header)
	APIKeyModel.print()

	// Parse Body Values
	responseBodyMap, err := parseGitHubRepoDataResponseBody(resp)
	if err != nil {
		return nil, err
	}

	return responseBodyMap, nil
}

// TODO potentially return error here
func buildGitHubRepoDataAPIURL(packageModel models.PackageModel, APIKeyModel GitHubAPIKeyModel) string {
	author := *packageModel.Author
	repo := *packageModel.Repo
	url := fmt.Sprintf("https://api.github.com/repos/%s/%s?access_token=%s", author, repo, APIKeyModel.Key)
	return url
}

// TODO Optimize this with ffjson struct!
func parseGitHubRepoDataResponseBody(response *http.Response) (map[string]interface{}, error) {
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, errors.New("Failed to parse response body")
	}

	var bodyMap map[string]interface{}
	err = json.Unmarshal(body, &bodyMap)
	if err != nil {
		return nil, errors.New("Failed to unmarshal response body")
	}

	return bodyMap, nil
}

func (gitHubRequestService *GitHubRequestService) FetchCommitSHAByDateRangeForPackageModel(packageModel models.PackageModel, timestamp time.Time) (string, error) {
	APIKeyModel := gitHubRequestService.APIKeyChain.getAPIKeyModel()
	log.Println(APIKeyModel)
	fmt.Printf("%+v \n", APIKeyModel)
	log.Printf("Determining APIKey %s \n", APIKeyModel.Key)

	githubURL := buildGitHubRepoCommitsFromTimestampAPIURL(packageModel, *APIKeyModel, timestamp)
	log.Printf("Fetching GitHub data for %s \n", githubURL)

	resp, err := http.Get(githubURL)
	defer resp.Body.Close()

	if err != nil {
		return "", errors.New("Request error.")
	}

	if resp.StatusCode == 404 {
		log.Println("PackageModel was not found on Github")
		return "", nil
	}

	APIKeyModel.incrementUsageFromResponseHeader(resp.Header)
	APIKeyModel.print()

	commitSHA, err := parseGitHubCommitLookUpResponseBody(resp)
	if err != nil {
		// TODO if we can't find date need to do something here
		return "", err
	}

	return commitSHA, nil
}

func buildGitHubRepoCommitsFromTimestampAPIURL(packageModel models.PackageModel, APIKeyModel GitHubAPIKeyModel, timestamp time.Time) string {
	author := *packageModel.Author
	repo := *packageModel.Repo

	url := fmt.Sprintf("https://api.github.com/repos/%s/%s/commits?until=%s&access_token=%s", author, repo, strings.Replace(timestamp.String(), " ", "", -1), APIKeyModel.Key)
	log.Println("URL = ", url)
	return url
}

func parseGitHubCommitLookUpResponseBody(response *http.Response) (string, error) {
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return "", errors.New("Failed to parse response body")
	}

	var commitSHAArray []dtos.GitCommitDTO
	err = json.Unmarshal(body, &commitSHAArray)
	if err != nil {
		return "", errors.New("Failed to unmarshal response body")
	}

	if len(commitSHAArray) >= 1 {
		return commitSHAArray[0].SHA, nil
	}

	return "", errors.New("No commit SHAs available for timestamp given")
}

// ==== Misc ====

// TODO Won't need this after implementing FFJSON
func ParseStarCount(responseBody map[string]interface{}) int {
	starCount := responseBody["stargazers_count"]
	if starCount == nil {
		return 0
	}

	return int(starCount.(float64))
}

// TODO same here
type GitHubPackageModelDTO struct {
	Package      models.PackageModel
	ResponseBody map[string]interface{}
}
<|endoftext|>


<commit_before>package main

const VERSION = "1.1-alpha"
<commit_msg>bump to version 1.1<commit_after>package main

const VERSION = "1.1"
<|endoftext|>


<commit_before>package amino

// Version
const Version = "0.10.0-rc2"
<commit_msg>Bump version to 0.10.0<commit_after>package amino

// Version
const Version = "0.10.0"
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"

	"github.com/cubicdaiya/nginx-build/builder"
)

func versionsSubmajorGen(major, submajor, minor int) []string {
	var versions []string

	for i := 0; i <= minor; i++ {
		v := fmt.Sprintf("%d.%d.%d", major, submajor, i)
		versions = append(versions, v)
	}
	return versions
}

func versionsGen() []string {
	var versions []string
	// 0.x.x
	versionsMinor0 := []int{
		45, // 0.1.x
		6,  // 0.2.x
		61, // 0.3.x
		14, // 0.4.x
		38, // 0.5.x
		39, // 0.6.x
		69, // 0.7.x
		55, // 0.8.x
		7,  // 0.9.x
	}
	// 1.x.x
	versionsMinor1 := []int{
		15, // 1.0.x
		19, // 1.1.x
		9,  // 1.2.x
		16, // 1.3.x
		7,  // 1.4.x
		13, // 1.5.x
		3,  // 1.6.x
		12, // 1.7.x
		1,  // 1.8.x
		15, // 1.9.x
		3,  // 1.10.x
		13, // 1.11.x
		2,  // 1.12.x
		12, // 1.13.x
		2,  // 1.14.x
		12, // 1.15.x
		1,  // 1.16.x
		9,  // 1.17.x
		0,  // 1.18.x
		10, // 1.19.x
		1,  // 1.20.x
		4,  // 1.21.x
	}

	// 0.1.0 ~ 0.9.7
	for i := 0; i < len(versionsMinor0); i++ {
		versions = append(versions, versionsSubmajorGen(0, i+1, versionsMinor0[i])...)
	}

	// 1.0.0 ~
	for i := 0; i < len(versionsMinor1); i++ {
		versions = append(versions, versionsSubmajorGen(1, i, versionsMinor1[i])...)
	}

	return versions
}

func versionsGenOpenResty() []string {
	return []string{
		fmt.Sprintf("openresty-%s", builder.OpenRestyVersion),
	}
}

func versionsGenTengine() []string {
	return []string{
		fmt.Sprintf("tengine-%s", builder.TengineVersion),
	}
}

func printNginxVersions() {
	versions := versionsGen()
	versions = append(versions, versionsGenOpenResty()...)
	versions = append(versions, versionsGenTengine()...)
	for _, v := range versions {
		fmt.Println(v)
	}
}

func versionCheck(version string) {
	if len(version) == 0 {
		log.Println("[warn]nginx version is not set.")
		log.Printf("[warn]nginx-build use %s.\n", builder.NginxVersion)
	}
}
<commit_msg>bumped default nginx version for 1.20.x.<commit_after>package main

import (
	"fmt"
	"log"

	"github.com/cubicdaiya/nginx-build/builder"
)

func versionsSubmajorGen(major, submajor, minor int) []string {
	var versions []string

	for i := 0; i <= minor; i++ {
		v := fmt.Sprintf("%d.%d.%d", major, submajor, i)
		versions = append(versions, v)
	}
	return versions
}

func versionsGen() []string {
	var versions []string
	// 0.x.x
	versionsMinor0 := []int{
		45, // 0.1.x
		6,  // 0.2.x
		61, // 0.3.x
		14, // 0.4.x
		38, // 0.5.x
		39, // 0.6.x
		69, // 0.7.x
		55, // 0.8.x
		7,  // 0.9.x
	}
	// 1.x.x
	versionsMinor1 := []int{
		15, // 1.0.x
		19, // 1.1.x
		9,  // 1.2.x
		16, // 1.3.x
		7,  // 1.4.x
		13, // 1.5.x
		3,  // 1.6.x
		12, // 1.7.x
		1,  // 1.8.x
		15, // 1.9.x
		3,  // 1.10.x
		13, // 1.11.x
		2,  // 1.12.x
		12, // 1.13.x
		2,  // 1.14.x
		12, // 1.15.x
		1,  // 1.16.x
		9,  // 1.17.x
		0,  // 1.18.x
		10, // 1.19.x
		2,  // 1.20.x
		4,  // 1.21.x
	}

	// 0.1.0 ~ 0.9.7
	for i := 0; i < len(versionsMinor0); i++ {
		versions = append(versions, versionsSubmajorGen(0, i+1, versionsMinor0[i])...)
	}

	// 1.0.0 ~
	for i := 0; i < len(versionsMinor1); i++ {
		versions = append(versions, versionsSubmajorGen(1, i, versionsMinor1[i])...)
	}

	return versions
}

func versionsGenOpenResty() []string {
	return []string{
		fmt.Sprintf("openresty-%s", builder.OpenRestyVersion),
	}
}

func versionsGenTengine() []string {
	return []string{
		fmt.Sprintf("tengine-%s", builder.TengineVersion),
	}
}

func printNginxVersions() {
	versions := versionsGen()
	versions = append(versions, versionsGenOpenResty()...)
	versions = append(versions, versionsGenTengine()...)
	for _, v := range versions {
		fmt.Println(v)
	}
}

func versionCheck(version string) {
	if len(version) == 0 {
		log.Println("[warn]nginx version is not set.")
		log.Printf("[warn]nginx-build use %s.\n", builder.NginxVersion)
	}
}
<|endoftext|>


<commit_before>package main

// The git commit that was compiled. This will be filled in by the compiler.
var GitCommit string
var GitDescribe string

// The main version number that is being run at the moment.
const Version = "0.5.1"

// A pre-release marker for the version. If this is "" (empty string)
// then it means that it is a final release. Otherwise, this is a pre-release
// such as "dev" (in development), "beta", "rc1", etc.
const VersionPrerelease = "rc1"
<commit_msg>Updating the version<commit_after>package main

// The git commit that was compiled. This will be filled in by the compiler.
var GitCommit string
var GitDescribe string

// The main version number that is being run at the moment.
const Version = "0.5.1"

// A pre-release marker for the version. If this is "" (empty string)
// then it means that it is a final release. Otherwise, this is a pre-release
// such as "dev" (in development), "beta", "rc1", etc.
const VersionPrerelease = "rc2"
<|endoftext|>


<commit_before>// Copyright 2018 Gin Core Team.  All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.

package gin

// Version is the current gin framework's version.
const Version = "v1.6.1"
<commit_msg>Update version.go (#2307)<commit_after>// Copyright 2018 Gin Core Team.  All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.

package gin

// Version is the current gin framework's version.
const Version = "v1.6.2"
<|endoftext|>


<commit_before>package inetdata

var Version string = "0.0.32"
<commit_msg>Bump version<commit_after>package inetdata

var Version string = "0.0.33"
<|endoftext|>


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

package main

import (
	"bytes"
	"fmt"
	"strings"
)

// semanticAlphabet
const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-"

// These constants define the application version and follow the semantic
// versioning 2.0.0 spec (http://semver.org/).
const (
	appMajor uint = 0
	appMinor uint = 1
	appPatch uint = 5

	// appPreRelease MUST only contain characters from semanticAlphabet
	// per the semantic versioning spec.
	appPreRelease = "beta"
)

// appBuild is defined as a variable so it can be overridden during the build
// process with '-ldflags "-X main.appBuild foo' if needed.  It MUST only
// contain characters from semanticAlphabet per the semantic versioning spec.
var appBuild string

// version returns the application version as a properly formed string per the
// semantic versioning 2.0.0 spec (http://semver.org/).
func version() string {
	// Start with the major, minor, and path versions.
	version := fmt.Sprintf("%d.%d.%d", appMajor, appMinor, appPatch)

	// Append pre-release version if there is one.  The hyphen called for
	// by the semantic versioning spec is automatically appended and should
	// not be contained in the pre-release string.  The pre-release version
	// is not appended if it contains invalid characters.
	preRelease := normalizeVerString(appPreRelease)
	if preRelease != "" {
		version = fmt.Sprintf("%s-%s", version, preRelease)
	}

	// Append build metadata if there is any.  The plus called for
	// by the semantic versioning spec is automatically appended and should
	// not be contained in the build metadata string.  The build metadata
	// string is not appended if it contains invalid characters.
	build := normalizeVerString(appBuild)
	if build != "" {
		version = fmt.Sprintf("%s+%s", version, build)
	}

	return version
}

// normalizeVerString returns the passed string stripped of all characters which
// are not valid according to the semantic versioning guidelines for pre-release
// version and build metadata strings.  In particular they MUST only contain
// characters in semanticAlphabet.
func normalizeVerString(str string) string {
	result := bytes.Buffer{}
	for _, r := range str {
		if strings.ContainsRune(semanticAlphabet, r) {
			_, err := result.WriteRune(r)
			// Writing to a bytes.Buffer panics on OOM, and all
			// errors are unexpected.
			if err != nil {
				panic(err)
			}
		}
	}
	return result.String()
}
<commit_msg>Bump for v0.1.6<commit_after>// Copyright (c) 2013-2014 The btcsuite developers
// Copyright (c) 2015 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package main

import (
	"bytes"
	"fmt"
	"strings"
)

// semanticAlphabet
const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-"

// These constants define the application version and follow the semantic
// versioning 2.0.0 spec (http://semver.org/).
const (
	appMajor uint = 0
	appMinor uint = 1
	appPatch uint = 6

	// appPreRelease MUST only contain characters from semanticAlphabet
	// per the semantic versioning spec.
	appPreRelease = "beta"
)

// appBuild is defined as a variable so it can be overridden during the build
// process with '-ldflags "-X main.appBuild foo' if needed.  It MUST only
// contain characters from semanticAlphabet per the semantic versioning spec.
var appBuild string

// version returns the application version as a properly formed string per the
// semantic versioning 2.0.0 spec (http://semver.org/).
func version() string {
	// Start with the major, minor, and path versions.
	version := fmt.Sprintf("%d.%d.%d", appMajor, appMinor, appPatch)

	// Append pre-release version if there is one.  The hyphen called for
	// by the semantic versioning spec is automatically appended and should
	// not be contained in the pre-release string.  The pre-release version
	// is not appended if it contains invalid characters.
	preRelease := normalizeVerString(appPreRelease)
	if preRelease != "" {
		version = fmt.Sprintf("%s-%s", version, preRelease)
	}

	// Append build metadata if there is any.  The plus called for
	// by the semantic versioning spec is automatically appended and should
	// not be contained in the build metadata string.  The build metadata
	// string is not appended if it contains invalid characters.
	build := normalizeVerString(appBuild)
	if build != "" {
		version = fmt.Sprintf("%s+%s", version, build)
	}

	return version
}

// normalizeVerString returns the passed string stripped of all characters which
// are not valid according to the semantic versioning guidelines for pre-release
// version and build metadata strings.  In particular they MUST only contain
// characters in semanticAlphabet.
func normalizeVerString(str string) string {
	result := bytes.Buffer{}
	for _, r := range str {
		if strings.ContainsRune(semanticAlphabet, r) {
			_, err := result.WriteRune(r)
			// Writing to a bytes.Buffer panics on OOM, and all
			// errors are unexpected.
			if err != nil {
				panic(err)
			}
		}
	}
	return result.String()
}
<|endoftext|>