<commit_before>package flow

import (
	"log"
	"sync"
	"testing"
	"time"
)

// A component that doubles its int input
type doubler struct {
	Component
	In  <-chan int
	Out chan<- int
}

// Doubles the input and sends it to output
func (d *doubler) OnIn(i int) {
	d.Out <- i * 2
}

// A constructor that can be used by component registry/factory
func newDoubler() interface{} {
	return new(doubler)
}

func init() {
	Register("doubler", newDoubler)
	Annotate("doubler", ComponentInfo{
		Description: "Doubles its input",
	})
}

// Tests a component with single input and single output
func TestSingleInput(t *testing.T) {
	d := new(doubler)
	in := make(chan int, 10)
	out := make(chan int, 10)
	d.In = in
	d.Out = out
	RunProc(d)
	for i := 0; i < 10; i++ {
		in <- i
		i2 := <-out
		ix2 := i * 2
		if i2 != ix2 {
			t.Errorf("%d != %d", i2, ix2)
		}
	}
	// Shutdown the component
	close(in)
}

// A component that locks to preserve concurrent modification of its state
type locker struct {
	Component
	In  <-chan int
	Out chan<- int

	StateLock *sync.Mutex

	counter int
	sum     int
}

// Creates a locker instance. This is required because StateLock must be a pointer
func newLocker() *locker {
	l := new(locker)
	l.counter = 0
	l.sum = 0
	l.StateLock = new(sync.Mutex)
	return l
}

// A constructor that can be used by component registry/factory
func newLockerConstructor() interface{} {
	return newLocker()
}

func init() {
	Register("locker", newLockerConstructor)
}

// Simulates long processing and read/write access
func (l *locker) OnIn(i int) {
	l.counter++
	// Half of the calls will wait to simulate long processing
	if l.counter%2 == 0 {
		time.Sleep(1000)
	}

	// Parellel write data race danger is here
	l.sum += i
}

func (l *locker) Shutdown() {
	// Emit the result and don't close the outport
	l.Out <- l.sum
}

// Tests internal state locking feature.
// Run with GOMAXPROCS > 1.
func TestStateLock(t *testing.T) {
	l := newLocker()
	in := make(chan int, 10)
	out := make(chan int, 10)
	l.In = in
	l.Out = out
	RunProc(l)
	// Simulate parallel writing and count the sum
	sum := 0
	for i := 1; i <= 1000; i++ {
		in <- i
		sum += i
	}
	// Send the close signal
	close(in)
	// Get the result and check if it is consistent
	sum2 := <-out
	if sum2 != sum {
		t.Errorf("%d != %d", sum2, sum)
	}
}

// Similar to locker, but intended to test ComponentModeSync
type syncLocker struct {
	Component
	In  <-chan int
	Out chan<- int

	counter int
	sum     int
}

// Creates a syncLocker instance
func newSyncLocker() *syncLocker {
	l := new(syncLocker)
	l.counter = 0
	l.sum = 0
	l.Component.Mode = ComponentModeSync // Change this to ComponentModeAsync and the test will fail
	return l
}

// A constructor that can be used by component registry/factory
func newSyncLockerConstructor() interface{} {
	return newSyncLocker()
}

func init() {
	Register("syncLocker", newSyncLockerConstructor)
}

// Simulates long processing and read/write access
func (l *syncLocker) OnIn(i int) {
	l.counter++
	// Half of the calls will wait to simulate long processing
	if l.counter%2 == 0 {
		time.Sleep(1000)
	}

	// Parellel write data race danger is here
	l.sum += i
}

func (l *syncLocker) Shutdown() {
	// Emit the result and don't close the outport
	l.Out <- l.sum
}

// Tests synchronous process execution feature.
// Run with GOMAXPROCS > 1.
func TestSyncLock(t *testing.T) {
	l := newSyncLocker()
	in := make(chan int, 10)
	out := make(chan int, 10)
	l.In = in
	l.Out = out
	RunProc(l)
	// Simulate parallel writing and count the sum
	sum := 0
	for i := 1; i <= 1000; i++ {
		in <- i
		sum += i
	}
	// Send the close signal
	close(in)
	// Get the result and check if it is consistent
	sum2 := <-out
	if sum2 != sum {
		t.Errorf("%d != %d", sum2, sum)
	}
}

// An external variable
var testInitFinFlag int

// Simple component
type initfin struct {
	Component
	In  <-chan int
	Out chan<- int
}

// Echo input
func (i *initfin) OnIn(n int) {
	// Dependent behavior
	if testInitFinFlag == 123 {
		i.Out <- n * 2
	} else {
		i.Out <- n
	}
}

// Initialization code, affects a global var
func (i *initfin) Init() {
	testInitFinFlag = 123
}

// Finalization code
func (i *initfin) Finish() {
	testInitFinFlag = 456
}

// Tests user initialization and finalization functions
func TestInitFinish(t *testing.T) {
	// Create and run the component
	i := new(initfin)
	i.Net = new(Graph)
	i.Net.InitGraphState()
	i.Net.waitGrp.Add(1)
	in := make(chan int)
	out := make(chan int)
	i.In = in
	i.Out = out
	RunProc(i)
	// Pass a value, the result must be affected by flag state
	in <- 2
	n2 := <-out
	if n2 != 4 {
		t.Errorf("%d != %d", n2, 4)
	}
	// Shut the component down and wait for Finish() code
	close(in)
	i.Net.waitGrp.Wait()
	if testInitFinFlag != 456 {
		t.Errorf("%d != %d", testInitFinFlag, 456)
	}
}

// A flag to test OnClose
var closeTestFlag int

// A component to test OnClose handlers
type closeTest struct {
	Component
	In <-chan int
}

// In channel close event handler
func (c *closeTest) OnInClose() {
	closeTestFlag = 789
}

// Tests close handler of input ports
func TestClose(t *testing.T) {
	c := new(closeTest)
	c.Net = new(Graph)
	c.Net.InitGraphState()
	c.Net.waitGrp.Add(1)
	in := make(chan int)
	c.In = in
	RunProc(c)
	in <- 1
	close(in)
	c.Net.waitGrp.Wait()
	if closeTestFlag != 789 {
		t.Errorf("%d != %d", closeTestFlag, 789)
	}
}

// A flag to test OnClose
var shutdownTestFlag int

// A component to test OnClose handlers
type shutdownTest struct {
	Component
	In <-chan int
}

// In channel close event handler
func (s *shutdownTest) OnIn(i int) {
	shutdownTestFlag = i
}

// Custom shutdown handler
func (s *shutdownTest) Shutdown() {
	shutdownTestFlag = 789
}

// Tests close handler of input ports
func TestShutdown(t *testing.T) {
	s := new(shutdownTest)
	s.Net = new(Graph)
	s.Net.InitGraphState()
	s.Net.waitGrp.Add(1)
	in := make(chan int)
	s.In = in
	RunProc(s)
	in <- 1
	close(in)
	s.Net.waitGrp.Wait()
	if shutdownTestFlag != 789 {
		t.Errorf("%d != %d", shutdownTestFlag, 789)
	}
}

func TestPoolMode(t *testing.T) {
	d := new(doubler)
	d.Component.Mode = ComponentModePool
	d.Component.PoolSize = 4
	in := make(chan int, 20)
	out := make(chan int, 20)
	d.In = in
	d.Out = out
	RunProc(d)
	for i := 0; i < 10; i++ {
		in <- i
	}
	for i := 0; i < 10; i++ {
		i2 := <-out
		if i2 < 0 {
			t.Errorf("%d < 0", i2)
		}
	}
	// Shutdown the component
	close(in)
}

// A component to test manual termination
type stopMe struct {
	Component
	In  <-chan int
	Out chan<- int
}

func (s *stopMe) OnIn(i int) {
	s.Out <- i * 2
}

func (s *stopMe) Finish() {
	s.Out <- 909
}

// Tests manual termination via StopProc()
func TestStopProc(t *testing.T) {
	s := new(stopMe)
	in := make(chan int, 20)
	out := make(chan int, 20)
	s.In = in
	s.Out = out
	// Test normal mode first
	RunProc(s)
	for i := 0; i < 10; i++ {
		in <- i
	}
	for i := 0; i < 10; i++ {
		i2 := <-out
		if i2 < 0 {
			t.Errorf("%d < 0", i2)
		}
	}
	// Stop without closing chans
	StopProc(s)
	// Wait for finish signal
	fin := <-out
	if fin != 909 {
		t.Errorf("Invalid final signal: %d", fin)
	}
	// Run again in Pool mode
	s.Component.Mode = ComponentModePool
	s.Component.PoolSize = 4
	RunProc(s)
	for i := 0; i < 10; i++ {
		in <- i
	}
	for i := 0; i < 10; i++ {
		i2 := <-out
		if i2 < 0 {
			t.Errorf("%d < 0", i2)
		}
	}
	// Stop without closing chans
	StopProc(s)
	// Wait for finish signal
	fin = <-out
	if fin != 909 {
		t.Errorf("Invalid final signal: %d", fin)
	}
}

// An active Looper component in classical FBP style
type counter struct {
	Component
	In    <-chan int      `description:"Packets to count"`
	Reset <-chan struct{} `description:"Reset counter signal"`
	Count chan<- int      `description:"Number of packets counted"`

	counter int
}

func (c *counter) Loop() {
	for {
		select {
		// Handle immediate terminate signal from network
		case <-c.Component.Term:
			return
		case _, reset := <-c.Reset:
			if reset {
				c.counter = 0
				c.Count <- c.counter
			} else {
				return
			}
		case _, input := <-c.In:
			if input {
				c.counter++
				c.Count <- c.counter
			} else {
				return
			}
		}
	}
}

func init() {
	Register("counter", func() interface{} {
		return new(counter)
	})
	Annotate("counter", ComponentInfo{
		Description: "Counts input packets",
	})
}

// Tests an active Looper component
func TestLooper(t *testing.T) {
	c := new(counter)
	in := make(chan int, 10)
	rs := make(chan struct{})
	out := make(chan int, 10)
	c.In = in
	c.Reset = rs
	c.Count = out
	RunProc(c)
	for i := 0; i < 10; i++ {
		in <- i
		i2 := <-out
		if i2 != i+1 {
			t.Errorf("%d != %d", i2, i+1)
		}
	}
	rs <- struct{}{}
	i2 := <-out
	if i2 != 0 {
		t.Errorf("%d != 0", i2)
	}
	// Shutdown the component
	close(in)
}

type unexportedChannel struct {
	Component

	In       <-chan bool
	aChannel chan bool
}

func (c *unexportedChannel) OnIn(b bool) {
	log.Println(b)
}

// Tests a component with an unexported channel
func TestUnexportedChannel(t *testing.T) {
	c := new(unexportedChannel)
	c.aChannel = make(chan bool)
	in := make(chan bool)
	c.In = in
	RunProc(c)
	in <- true
	close(in)
	return
}
<commit_msg>Disable the old component test cases<commit_after>package flow

// import (
// 	"log"
// 	"sync"
// 	"testing"
// 	"time"
// )
//
// // A component that doubles its int input
// type doubler struct {
// 	Component
// 	In  <-chan int
// 	Out chan<- int
// }
//
// // Doubles the input and sends it to output
// func (d *doubler) OnIn(i int) {
// 	d.Out <- i * 2
// }
//
// // A constructor that can be used by component registry/factory
// func newDoubler() interface{} {
// 	return new(doubler)
// }
//
// func init() {
// 	Register("doubler", newDoubler)
// 	Annotate("doubler", ComponentInfo{
// 		Description: "Doubles its input",
// 	})
// }
//
// // Tests a component with single input and single output
// func TestSingleInput(t *testing.T) {
// 	d := new(doubler)
// 	in := make(chan int, 10)
// 	out := make(chan int, 10)
// 	d.In = in
// 	d.Out = out
// 	RunProc(d)
// 	for i := 0; i < 10; i++ {
// 		in <- i
// 		i2 := <-out
// 		ix2 := i * 2
// 		if i2 != ix2 {
// 			t.Errorf("%d != %d", i2, ix2)
// 		}
// 	}
// 	// Shutdown the component
// 	close(in)
// }
//
// // A component that locks to preserve concurrent modification of its state
// type locker struct {
// 	Component
// 	In  <-chan int
// 	Out chan<- int
//
// 	StateLock *sync.Mutex
//
// 	counter int
// 	sum     int
// }
//
// // Creates a locker instance. This is required because StateLock must be a pointer
// func newLocker() *locker {
// 	l := new(locker)
// 	l.counter = 0
// 	l.sum = 0
// 	l.StateLock = new(sync.Mutex)
// 	return l
// }
//
// // A constructor that can be used by component registry/factory
// func newLockerConstructor() interface{} {
// 	return newLocker()
// }
//
// func init() {
// 	Register("locker", newLockerConstructor)
// }
//
// // Simulates long processing and read/write access
// func (l *locker) OnIn(i int) {
// 	l.counter++
// 	// Half of the calls will wait to simulate long processing
// 	if l.counter%2 == 0 {
// 		time.Sleep(1000)
// 	}
//
// 	// Parellel write data race danger is here
// 	l.sum += i
// }
//
// func (l *locker) Shutdown() {
// 	// Emit the result and don't close the outport
// 	l.Out <- l.sum
// }
//
// // Tests internal state locking feature.
// // Run with GOMAXPROCS > 1.
// func TestStateLock(t *testing.T) {
// 	l := newLocker()
// 	in := make(chan int, 10)
// 	out := make(chan int, 10)
// 	l.In = in
// 	l.Out = out
// 	RunProc(l)
// 	// Simulate parallel writing and count the sum
// 	sum := 0
// 	for i := 1; i <= 1000; i++ {
// 		in <- i
// 		sum += i
// 	}
// 	// Send the close signal
// 	close(in)
// 	// Get the result and check if it is consistent
// 	sum2 := <-out
// 	if sum2 != sum {
// 		t.Errorf("%d != %d", sum2, sum)
// 	}
// }
//
// // Similar to locker, but intended to test ComponentModeSync
// type syncLocker struct {
// 	Component
// 	In  <-chan int
// 	Out chan<- int
//
// 	counter int
// 	sum     int
// }
//
// // Creates a syncLocker instance
// func newSyncLocker() *syncLocker {
// 	l := new(syncLocker)
// 	l.counter = 0
// 	l.sum = 0
// 	l.Component.Mode = ComponentModeSync // Change this to ComponentModeAsync and the test will fail
// 	return l
// }
//
// // A constructor that can be used by component registry/factory
// func newSyncLockerConstructor() interface{} {
// 	return newSyncLocker()
// }
//
// func init() {
// 	Register("syncLocker", newSyncLockerConstructor)
// }
//
// // Simulates long processing and read/write access
// func (l *syncLocker) OnIn(i int) {
// 	l.counter++
// 	// Half of the calls will wait to simulate long processing
// 	if l.counter%2 == 0 {
// 		time.Sleep(1000)
// 	}
//
// 	// Parellel write data race danger is here
// 	l.sum += i
// }
//
// func (l *syncLocker) Shutdown() {
// 	// Emit the result and don't close the outport
// 	l.Out <- l.sum
// }
//
// // Tests synchronous process execution feature.
// // Run with GOMAXPROCS > 1.
// func TestSyncLock(t *testing.T) {
// 	l := newSyncLocker()
// 	in := make(chan int, 10)
// 	out := make(chan int, 10)
// 	l.In = in
// 	l.Out = out
// 	RunProc(l)
// 	// Simulate parallel writing and count the sum
// 	sum := 0
// 	for i := 1; i <= 1000; i++ {
// 		in <- i
// 		sum += i
// 	}
// 	// Send the close signal
// 	close(in)
// 	// Get the result and check if it is consistent
// 	sum2 := <-out
// 	if sum2 != sum {
// 		t.Errorf("%d != %d", sum2, sum)
// 	}
// }
//
// // An external variable
// var testInitFinFlag int
//
// // Simple component
// type initfin struct {
// 	Component
// 	In  <-chan int
// 	Out chan<- int
// }
//
// // Echo input
// func (i *initfin) OnIn(n int) {
// 	// Dependent behavior
// 	if testInitFinFlag == 123 {
// 		i.Out <- n * 2
// 	} else {
// 		i.Out <- n
// 	}
// }
//
// // Initialization code, affects a global var
// func (i *initfin) Init() {
// 	testInitFinFlag = 123
// }
//
// // Finalization code
// func (i *initfin) Finish() {
// 	testInitFinFlag = 456
// }
//
// // Tests user initialization and finalization functions
// func TestInitFinish(t *testing.T) {
// 	// Create and run the component
// 	i := new(initfin)
// 	i.Net = new(Graph)
// 	i.Net.InitGraphState()
// 	i.Net.waitGrp.Add(1)
// 	in := make(chan int)
// 	out := make(chan int)
// 	i.In = in
// 	i.Out = out
// 	RunProc(i)
// 	// Pass a value, the result must be affected by flag state
// 	in <- 2
// 	n2 := <-out
// 	if n2 != 4 {
// 		t.Errorf("%d != %d", n2, 4)
// 	}
// 	// Shut the component down and wait for Finish() code
// 	close(in)
// 	i.Net.waitGrp.Wait()
// 	if testInitFinFlag != 456 {
// 		t.Errorf("%d != %d", testInitFinFlag, 456)
// 	}
// }
//
// // A flag to test OnClose
// var closeTestFlag int
//
// // A component to test OnClose handlers
// type closeTest struct {
// 	Component
// 	In <-chan int
// }
//
// // In channel close event handler
// func (c *closeTest) OnInClose() {
// 	closeTestFlag = 789
// }
//
// // Tests close handler of input ports
// func TestClose(t *testing.T) {
// 	c := new(closeTest)
// 	c.Net = new(Graph)
// 	c.Net.InitGraphState()
// 	c.Net.waitGrp.Add(1)
// 	in := make(chan int)
// 	c.In = in
// 	RunProc(c)
// 	in <- 1
// 	close(in)
// 	c.Net.waitGrp.Wait()
// 	if closeTestFlag != 789 {
// 		t.Errorf("%d != %d", closeTestFlag, 789)
// 	}
// }
//
// // A flag to test OnClose
// var shutdownTestFlag int
//
// // A component to test OnClose handlers
// type shutdownTest struct {
// 	Component
// 	In <-chan int
// }
//
// // In channel close event handler
// func (s *shutdownTest) OnIn(i int) {
// 	shutdownTestFlag = i
// }
//
// // Custom shutdown handler
// func (s *shutdownTest) Shutdown() {
// 	shutdownTestFlag = 789
// }
//
// // Tests close handler of input ports
// func TestShutdown(t *testing.T) {
// 	s := new(shutdownTest)
// 	s.Net = new(Graph)
// 	s.Net.InitGraphState()
// 	s.Net.waitGrp.Add(1)
// 	in := make(chan int)
// 	s.In = in
// 	RunProc(s)
// 	in <- 1
// 	close(in)
// 	s.Net.waitGrp.Wait()
// 	if shutdownTestFlag != 789 {
// 		t.Errorf("%d != %d", shutdownTestFlag, 789)
// 	}
// }
//
// func TestPoolMode(t *testing.T) {
// 	d := new(doubler)
// 	d.Component.Mode = ComponentModePool
// 	d.Component.PoolSize = 4
// 	in := make(chan int, 20)
// 	out := make(chan int, 20)
// 	d.In = in
// 	d.Out = out
// 	RunProc(d)
// 	for i := 0; i < 10; i++ {
// 		in <- i
// 	}
// 	for i := 0; i < 10; i++ {
// 		i2 := <-out
// 		if i2 < 0 {
// 			t.Errorf("%d < 0", i2)
// 		}
// 	}
// 	// Shutdown the component
// 	close(in)
// }
//
// // A component to test manual termination
// type stopMe struct {
// 	Component
// 	In  <-chan int
// 	Out chan<- int
// }
//
// func (s *stopMe) OnIn(i int) {
// 	s.Out <- i * 2
// }
//
// func (s *stopMe) Finish() {
// 	s.Out <- 909
// }
//
// // Tests manual termination via StopProc()
// func TestStopProc(t *testing.T) {
// 	s := new(stopMe)
// 	in := make(chan int, 20)
// 	out := make(chan int, 20)
// 	s.In = in
// 	s.Out = out
// 	// Test normal mode first
// 	RunProc(s)
// 	for i := 0; i < 10; i++ {
// 		in <- i
// 	}
// 	for i := 0; i < 10; i++ {
// 		i2 := <-out
// 		if i2 < 0 {
// 			t.Errorf("%d < 0", i2)
// 		}
// 	}
// 	// Stop without closing chans
// 	StopProc(s)
// 	// Wait for finish signal
// 	fin := <-out
// 	if fin != 909 {
// 		t.Errorf("Invalid final signal: %d", fin)
// 	}
// 	// Run again in Pool mode
// 	s.Component.Mode = ComponentModePool
// 	s.Component.PoolSize = 4
// 	RunProc(s)
// 	for i := 0; i < 10; i++ {
// 		in <- i
// 	}
// 	for i := 0; i < 10; i++ {
// 		i2 := <-out
// 		if i2 < 0 {
// 			t.Errorf("%d < 0", i2)
// 		}
// 	}
// 	// Stop without closing chans
// 	StopProc(s)
// 	// Wait for finish signal
// 	fin = <-out
// 	if fin != 909 {
// 		t.Errorf("Invalid final signal: %d", fin)
// 	}
// }
//
// // An active Looper component in classical FBP style
// type counter struct {
// 	Component
// 	In    <-chan int      `description:"Packets to count"`
// 	Reset <-chan struct{} `description:"Reset counter signal"`
// 	Count chan<- int      `description:"Number of packets counted"`
//
// 	counter int
// }
//
// func (c *counter) Loop() {
// 	for {
// 		select {
// 		// Handle immediate terminate signal from network
// 		case <-c.Component.Term:
// 			return
// 		case _, reset := <-c.Reset:
// 			if reset {
// 				c.counter = 0
// 				c.Count <- c.counter
// 			} else {
// 				return
// 			}
// 		case _, input := <-c.In:
// 			if input {
// 				c.counter++
// 				c.Count <- c.counter
// 			} else {
// 				return
// 			}
// 		}
// 	}
// }
//
// func init() {
// 	Register("counter", func() interface{} {
// 		return new(counter)
// 	})
// 	Annotate("counter", ComponentInfo{
// 		Description: "Counts input packets",
// 	})
// }
//
// // Tests an active Looper component
// func TestLooper(t *testing.T) {
// 	c := new(counter)
// 	in := make(chan int, 10)
// 	rs := make(chan struct{})
// 	out := make(chan int, 10)
// 	c.In = in
// 	c.Reset = rs
// 	c.Count = out
// 	RunProc(c)
// 	for i := 0; i < 10; i++ {
// 		in <- i
// 		i2 := <-out
// 		if i2 != i+1 {
// 			t.Errorf("%d != %d", i2, i+1)
// 		}
// 	}
// 	rs <- struct{}{}
// 	i2 := <-out
// 	if i2 != 0 {
// 		t.Errorf("%d != 0", i2)
// 	}
// 	// Shutdown the component
// 	close(in)
// }
//
// type unexportedChannel struct {
// 	Component
//
// 	In       <-chan bool
// 	aChannel chan bool
// }
//
// func (c *unexportedChannel) OnIn(b bool) {
// 	log.Println(b)
// }
//
// // Tests a component with an unexported channel
// func TestUnexportedChannel(t *testing.T) {
// 	c := new(unexportedChannel)
// 	c.aChannel = make(chan bool)
// 	in := make(chan bool)
// 	c.In = in
// 	RunProc(c)
// 	in <- true
// 	close(in)
// 	return
// }
<|endoftext|>


<commit_before>package diffy

import (
	"fmt"
)

// PluginsService contains Plugin related REST endpoints
//
// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-plugins.html
type PluginsService struct {
	client *Client
}

// PluginInfo entity describes a plugin.
type PluginInfo struct {
	ID       string `json:"id"`
	Version  string `json:"version"`
	IndexURL string `json:"index_url,omitempty"`
	Disabled bool   `json:"disabled,omitempty"`
}

// PluginInput entity describes a plugin that should be installed.
type PluginInput struct {
	URL string `json:"url"`
}

// PluginOptions specifies the different options for the ListPlugins call.
//
// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-plugins.html#list-plugins
type PluginOptions struct {
	// All enabled that all plugins are returned (enabled and disabled).
	All bool `url:"all,omitempty"`
}

// ListPlugins lists the plugins installed on the Gerrit server.
// Only the enabled plugins are returned unless the all option is specified.
//
// To be allowed to see the installed plugins, a user must be a member of a group that is granted the 'View Plugins' capability or the 'Administrate Server' capability.
// The entries in the map are sorted by plugin ID.
//
// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-plugins.html#list-plugins
func (s *PluginsService) ListPlugins(opt *PluginOptions) (*map[string]PluginInfo, *Response, error) {
	u := "plugins/"

	u, err := addOptions(u, opt)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	v := new(map[string]PluginInfo)
	resp, err := s.client.Do(req, v)
	if err != nil {
		return nil, resp, err
	}

	return v, resp, err
}

// GetPluginStatus retrieves the status of a plugin on the Gerrit server.
//
// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-plugins.html#get-plugin-status
func (s *PluginsService) GetPluginStatus(pluginID string) (*PluginInfo, *Response, error) {
	u := fmt.Sprintf("plugins/%s/gerrit~status", pluginID)

	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	v := new(PluginInfo)
	resp, err := s.client.Do(req, v)
	if err != nil {
		return nil, resp, err
	}

	return v, resp, err
}

/*
Missing Plugin Endpoints
	Install Plugin
	Enable Plugin
	Disable Plugin
	Reload Plugin
*/
<commit_msg>Implemented missing Plugin endpoints<commit_after>package diffy

import (
	"fmt"
)

// PluginsService contains Plugin related REST endpoints
//
// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-plugins.html
type PluginsService struct {
	client *Client
}

// PluginInfo entity describes a plugin.
type PluginInfo struct {
	ID       string `json:"id"`
	Version  string `json:"version"`
	IndexURL string `json:"index_url,omitempty"`
	Disabled bool   `json:"disabled,omitempty"`
}

// PluginInput entity describes a plugin that should be installed.
type PluginInput struct {
	URL string `json:"url"`
}

// PluginOptions specifies the different options for the ListPlugins call.
//
// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-plugins.html#list-plugins
type PluginOptions struct {
	// All enabled that all plugins are returned (enabled and disabled).
	All bool `url:"all,omitempty"`
}

// ListPlugins lists the plugins installed on the Gerrit server.
// Only the enabled plugins are returned unless the all option is specified.
//
// To be allowed to see the installed plugins, a user must be a member of a group that is granted the 'View Plugins' capability or the 'Administrate Server' capability.
// The entries in the map are sorted by plugin ID.
//
// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-plugins.html#list-plugins
func (s *PluginsService) ListPlugins(opt *PluginOptions) (*map[string]PluginInfo, *Response, error) {
	u := "plugins/"

	u, err := addOptions(u, opt)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	v := new(map[string]PluginInfo)
	resp, err := s.client.Do(req, v)
	if err != nil {
		return nil, resp, err
	}

	return v, resp, err
}

// GetPluginStatus retrieves the status of a plugin on the Gerrit server.
//
// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-plugins.html#get-plugin-status
func (s *PluginsService) GetPluginStatus(pluginID string) (*PluginInfo, *Response, error) {
	u := fmt.Sprintf("plugins/%s/gerrit~status", pluginID)
	return s.requestWithPluginInfoResponse("GET", u, nil)
}

// InstallPlugin installs a new plugin on the Gerrit server.
// If a plugin with the specified name already exists it is overwritten.
//
// Note: if the plugin provides its own name in the MANIFEST file, then the plugin name from the MANIFEST file has precedence over the {plugin-id} above.
//
// The plugin jar can either be sent as binary data in the request body or a URL to the plugin jar must be provided in the request body inside a PluginInput entity.
//
// As response a PluginInfo entity is returned that describes the plugin.
// If an existing plugin was overwritten the response is “200 OK”.
//
// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-projects.html#set-dashboard
func (s *PluginsService) InstallPlugin(pluginID string, input *PluginInput) (*PluginInfo, *Response, error) {
	u := fmt.Sprintf("plugins/%s", pluginID)
	return s.requestWithPluginInfoResponse("PUT", u, input)
}

// EnablePlugin enables a plugin on the Gerrit server.
//
// As response a PluginInfo entity is returned that describes the plugin.
//
// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-plugins.html#enable-plugin
func (s *PluginsService) EnablePlugin(pluginID string) (*PluginInfo, *Response, error) {
	u := fmt.Sprintf("plugins/%s/gerrit~enable", pluginID)
	return s.requestWithPluginInfoResponse("POST", u, nil)
}

// DisablePlugin disables a plugin on the Gerrit server.
//
// As response a PluginInfo entity is returned that describes the plugin.
//
// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-plugins.html#disable-plugin
func (s *PluginsService) DisablePlugin(pluginID string) (*PluginInfo, *Response, error) {
	u := fmt.Sprintf("plugins/%s/gerrit~disable", pluginID)
	return s.requestWithPluginInfoResponse("POST", u, nil)
}

// ReloadPlugin reloads a plugin on the Gerrit server.
//
// As response a PluginInfo entity is returned that describes the plugin.
//
// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-plugins.html#disable-plugin
func (s *PluginsService) ReloadPlugin(pluginID string) (*PluginInfo, *Response, error) {
	u := fmt.Sprintf("plugins/%s/gerrit~reload", pluginID)
	return s.requestWithPluginInfoResponse("POST", u, nil)
}

func (s *PluginsService) requestWithPluginInfoResponse(method, u string, input interface{}) (*PluginInfo, *Response, error) {
	req, err := s.client.NewRequest(method, u, input)
	if err != nil {
		return nil, nil, err
	}

	v := new(PluginInfo)
	resp, err := s.client.Do(req, v)
	if err != nil {
		return nil, resp, err
	}

	return v, resp, err
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"os"
	"os/exec"
	"os/signal"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
	"syscall"

	"github.com/heroku/heroku-cli/Godeps/_workspace/src/github.com/dickeyxxx/golock"
	"github.com/heroku/heroku-cli/gode"
)

// Plugin represents a javascript plugin
type Plugin struct {
	Name     string     `json:"name"`
	Version  string     `json:"version"`
	Topics   TopicSet   `json:"topics"`
	Topic    *Topic     `json:"topic"`
	Commands CommandSet `json:"commands"`
}

// SetupNode sets up node and npm in ~/.heroku
func SetupNode() {
	gode.SetRootPath(AppDir())
	setup, err := gode.IsSetup()
	PrintError(err)
	if !setup {
		setupNode()
	}
}

func setupNode() {
	Err("heroku-cli: Adding dependencies...")
	PrintError(gode.Setup())
	Errln(" done")
}

func updateNode() {
	gode.SetRootPath(AppDir())
	needsUpdate, err := gode.NeedsUpdate()
	PrintError(err)
	if needsUpdate {
		setupNode()
	}
}

// LoadPlugins loads the topics and commands from the JavaScript plugins into the CLI
func (cli *Cli) LoadPlugins(plugins map[string]*Plugin) {
	for _, plugin := range plugins {
		for _, topic := range plugin.Topics {
			cli.AddTopic(topic)
		}
		if plugin.Topic != nil {
			cli.AddTopic(plugin.Topic)
		}
		for _, command := range plugin.Commands {
			if !cli.AddCommand(command) {
				Errf("WARNING: command %s has already been defined\n", command)
			}
		}
	}
	sort.Sort(cli.Topics)
	sort.Sort(cli.Commands)
}

var pluginsTopic = &Topic{
	Name:        "plugins",
	Description: "manage plugins",
}

var pluginsInstallCmd = &Command{
	Topic:       "plugins",
	Command:     "install",
	Hidden:      true,
	Args:        []Arg{{Name: "name"}},
	Description: "Installs a plugin into the CLI",
	Help: `Install a Heroku plugin

  Example:
  $ heroku plugins:install dickeyxxx/heroku-production-status`,

	Run: func(ctx *Context) {
		name := ctx.Args.(map[string]string)["name"]
		if len(name) == 0 {
			Errln("Must specify a plugin name")
			return
		}
		Errf("Installing plugin %s... ", name)
		err := installPlugins(name)
		ExitIfError(err)
		plugin := getPlugin(name, true)
		if plugin == nil || len(plugin.Commands) == 0 {
			Err("\nThis does not appear to be a Heroku plugin, uninstalling... ")
			ExitIfError(gode.RemovePackage(name))
		}
		Errln("done")
	},
}

var pluginsLinkCmd = &Command{
	Topic:       "plugins",
	Command:     "link",
	Description: "Links a local plugin into CLI",
	Args:        []Arg{{Name: "path", Optional: true}},
	Help: `Links a local plugin into CLI.
	This is useful when developing plugins locally.
	It simply symlinks the specified path into ~/.heroku/node_modules

  Example:
	$ heroku plugins:link .`,

	Run: func(ctx *Context) {
		path := ctx.Args.(map[string]string)["path"]
		if path == "" {
			path = "."
		}
		path, err := filepath.Abs(path)
		if err != nil {
			panic(err)
		}
		if _, err := os.Stat(path); err != nil {
			panic(err)
		}
		name := filepath.Base(path)
		newPath := pluginPath(name)
		os.Remove(newPath)
		os.RemoveAll(newPath)
		err = os.Symlink(path, newPath)
		if err != nil {
			panic(err)
		}
		plugin := getPlugin(name, false)
		if plugin == nil || len(plugin.Commands) == 0 {
			Errln(name + " does not appear to be a Heroku plugin.\nDid you run " + cyan("npm install") + "?")
			if err := os.Remove(newPath); err != nil {
				panic(err)
			}
			return
		}
		if name != plugin.Name {
			path = newPath
			newPath = pluginPath(plugin.Name)
			os.Remove(newPath)
			os.RemoveAll(newPath)
			os.Rename(path, newPath)
		}
		Println("Symlinked", plugin.Name)
		AddPluginsToCache(plugin)
	},
}

var pluginsUninstallCmd = &Command{
	Topic:       "plugins",
	Command:     "uninstall",
	Hidden:      true,
	Args:        []Arg{{Name: "name"}},
	Description: "Uninstalls a plugin from the CLI",
	Help: `Uninstalls a Heroku plugin

  Example:
  $ heroku plugins:uninstall heroku-production-status`,

	Run: func(ctx *Context) {
		name := ctx.Args.(map[string]string)["name"]
		Errf("Uninstalling plugin %s... ", name)
		err := gode.RemovePackage(name)
		ExitIfError(err)
		RemovePluginFromCache(name)
		Errln("done")
	},
}

var pluginsListCmd = &Command{
	Topic:       "plugins",
	Hidden:      true,
	Description: "Lists installed plugins",
	Help: `
Example:
  $ heroku plugins`,

	Run: func(ctx *Context) {
		SetupBuiltinPlugins()
		var plugins []string
		for _, plugin := range GetPlugins() {
			if plugin != nil && len(plugin.Commands) > 0 {
				symlinked := ""
				if isPluginSymlinked(plugin.Name) {
					symlinked = " (symlinked)"
				}
				plugins = append(plugins, fmt.Sprintf("%s %s %s", plugin.Name, plugin.Version, symlinked))
			}
		}
		sort.Strings(plugins)
		for _, plugin := range plugins {
			Println(plugin)
		}
	},
}

func runFn(plugin *Plugin, topic, command string) func(ctx *Context) {
	return func(ctx *Context) {
		lockfile := updateLockPath + "." + plugin.Name
		if exists, _ := fileExists(lockfile); exists {
			golock.Lock(lockfile)
			golock.Unlock(lockfile)
		}
		ctx.Dev = isPluginSymlinked(plugin.Name)
		ctxJSON, err := json.Marshal(ctx)
		if err != nil {
			panic(err)
		}
		title, _ := json.Marshal(processTitle(ctx))
		script := fmt.Sprintf(`
		'use strict';
		var moduleName = '%s';
		var moduleVersion = '%s';
		var topic = '%s';
		var command = '%s';
		process.title = %s;
		var ctx = %s;
		ctx.version = ctx.version + ' ' + moduleName + '/' + moduleVersion + ' node-' + process.version;
		var logPath = %s;
		process.chdir(ctx.cwd);
		function repair (name) {
			console.error('Attempting to repair ' + name + '...');
			require('child_process')
			.spawnSync('heroku', ['plugins:install', name],
			{stdio: [0,1,2]});
			console.error('Repair complete. Try running your command again.');
		}
		if (!ctx.dev) {
			process.on('uncaughtException', function (err) {
				console.error(' !   Error in ' + moduleName + ':')
				if (err.message) {
					console.error(' !   ' + err.message);
					if (err.message.indexOf('Cannot find module') != -1) {
						repair(moduleName);
						process.exit(1);
					}
				} else {
					console.error(' !   ' + err);
				}
				if (err.stack) {
					var fs = require('fs');
					var log = function (line) {
						var d = new Date().toISOString()
						.replace(/T/, ' ')
						.replace(/-/g, '/')
						.replace(/\..+/, '');
						fs.appendFileSync(logPath, d + ' ' + line + '\n');
					}
					log('Error during ' + topic + ':' + command);
					log(err.stack);
					console.error(' !   See ' + logPath + ' for more info.');
				}
				process.exit(1);
			});
		}
		if (command === '') { command = null }
		var module = require(moduleName);
		var cmd = module.commands.filter(function (c) {
			return c.topic === topic && c.command == command;
		})[0];
		cmd.run(ctx);`, plugin.Name, plugin.Version, topic, command, string(title), ctxJSON, strconv.Quote(ErrLogPath))

		// swallow sigint since the plugin will handle it
		swallowSignal(os.Interrupt)

		cmd := gode.RunScript(script)
		cmd.Stdin = os.Stdin
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		if ctx.Flags["debugger"] == true {
			cmd = gode.DebugScript(script)
		}
		if err := cmd.Run(); err != nil {
			os.Exit(getExitCode(err))
		}
	}
}

func swallowSignal(s os.Signal) {
	c := make(chan os.Signal, 1)
	signal.Notify(c, s)
	go func() {
		<-c
	}()
}

func getExitCode(err error) int {
	switch e := err.(type) {
	case nil:
		return 0
	case *exec.ExitError:
		status, ok := e.Sys().(syscall.WaitStatus)
		if !ok {
			panic(err)
		}
		return status.ExitStatus()
	default:
		panic(err)
	}
}

func getPlugin(name string, attemptReinstall bool) *Plugin {
	script := `
	var plugin = require('` + name + `');
	if (!plugin.commands) plugin = {}; // not a real plugin
	var pjson  = require('` + name + `/package.json');

	plugin.name    = pjson.name;
	plugin.version = pjson.version;

	console.log(JSON.stringify(plugin))`
	cmd := gode.RunScript(script)
	output, err := cmd.CombinedOutput()
	if err != nil {
		if attemptReinstall && strings.Contains(string(output), "Error: Cannot find module") {
			Errf("Error reading plugin %s. Reinstalling... ", name)
			if err := installPlugins(name); err != nil {
				panic(errors.New(name + ": " + string(output)))
			}
			Errln("done")
			return getPlugin(name, false)
		}
		Errf("Error reading plugin: %s. See %s for more information.\n", name, ErrLogPath)
		Logln(err, "\n", string(output))
		return nil
	}
	var plugin Plugin
	json.Unmarshal([]byte(output), &plugin)
	for _, command := range plugin.Commands {
		command.Plugin = plugin.Name
		command.Help = strings.TrimSpace(command.Help)
	}
	return &plugin
}

// GetPlugins goes through all the node plugins and returns them in Go stucts
func GetPlugins() map[string]*Plugin {
	plugins := FetchPluginCache()
	for name, plugin := range plugins {
		if plugin == nil || !pluginExists(name) {
			delete(plugins, name)
		} else {
			for _, command := range plugin.Commands {
				command.Run = runFn(plugin, command.Topic, command.Command)
			}
		}
	}
	return plugins
}

// PluginNames lists all the plugin names
func PluginNames() []string {
	plugins := FetchPluginCache()
	names := make([]string, 0, len(plugins))
	for _, plugin := range plugins {
		if plugin != nil {
			names = append(names, plugin.Name)
		}
	}
	return names
}

// PluginNamesNotSymlinked returns all the plugins that are not symlinked
func PluginNamesNotSymlinked() []string {
	a := PluginNames()
	b := make([]string, 0, len(a))
	for _, plugin := range a {
		if !isPluginSymlinked(plugin) {
			b = append(b, plugin)
		}
	}
	return b
}

func isPluginSymlinked(plugin string) bool {
	path := filepath.Join(AppDir(), "node_modules", plugin)
	fi, err := os.Lstat(path)
	if err != nil {
		return false
	}
	return fi.Mode()&os.ModeSymlink != 0
}

// SetupBuiltinPlugins ensures all the builtinPlugins are installed
func SetupBuiltinPlugins() {
	pluginNames := difference(BuiltinPlugins, PluginNames())
	if len(pluginNames) == 0 {
		return
	}
	Err("heroku-cli: Installing core plugins...")
	err := installPlugins(pluginNames...)
	if err != nil {
		Errln()
		PrintError(err)
		return
	}
	Errln(" done")
}

func difference(a, b []string) []string {
	res := make([]string, 0, len(a))
	for _, aa := range a {
		if !contains(b, aa) {
			res = append(res, aa)
		}
	}
	return res
}

func contains(arr []string, s string) bool {
	for _, a := range arr {
		if a == s {
			return true
		}
	}
	return false
}

func installPlugins(names ...string) error {
	for _, name := range names {
		lockfile := updateLockPath + "." + name
		LogIfError(golock.Lock(lockfile))
	}
	err := gode.InstallPackage(names...)
	if err != nil {
		return err
	}
	plugins := make([]*Plugin, 0, len(names))
	for _, name := range names {
		plugins = append(plugins, getPlugin(name, true))
	}
	AddPluginsToCache(plugins...)
	for _, name := range names {
		lockfile := updateLockPath + "." + name
		LogIfError(golock.Unlock(lockfile))
	}
	return nil
}

func pluginExists(plugin string) bool {
	exists, _ := fileExists(pluginPath(plugin))
	return exists
}

func pluginPath(plugin string) string {
	return filepath.Join(AppDir(), "node_modules", plugin)
}
<commit_msg>log out error from module not found error<commit_after>package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"os"
	"os/exec"
	"os/signal"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
	"syscall"

	"github.com/heroku/heroku-cli/Godeps/_workspace/src/github.com/dickeyxxx/golock"
	"github.com/heroku/heroku-cli/gode"
)

// Plugin represents a javascript plugin
type Plugin struct {
	Name     string     `json:"name"`
	Version  string     `json:"version"`
	Topics   TopicSet   `json:"topics"`
	Topic    *Topic     `json:"topic"`
	Commands CommandSet `json:"commands"`
}

// SetupNode sets up node and npm in ~/.heroku
func SetupNode() {
	gode.SetRootPath(AppDir())
	setup, err := gode.IsSetup()
	PrintError(err)
	if !setup {
		setupNode()
	}
}

func setupNode() {
	Err("heroku-cli: Adding dependencies...")
	PrintError(gode.Setup())
	Errln(" done")
}

func updateNode() {
	gode.SetRootPath(AppDir())
	needsUpdate, err := gode.NeedsUpdate()
	PrintError(err)
	if needsUpdate {
		setupNode()
	}
}

// LoadPlugins loads the topics and commands from the JavaScript plugins into the CLI
func (cli *Cli) LoadPlugins(plugins map[string]*Plugin) {
	for _, plugin := range plugins {
		for _, topic := range plugin.Topics {
			cli.AddTopic(topic)
		}
		if plugin.Topic != nil {
			cli.AddTopic(plugin.Topic)
		}
		for _, command := range plugin.Commands {
			if !cli.AddCommand(command) {
				Errf("WARNING: command %s has already been defined\n", command)
			}
		}
	}
	sort.Sort(cli.Topics)
	sort.Sort(cli.Commands)
}

var pluginsTopic = &Topic{
	Name:        "plugins",
	Description: "manage plugins",
}

var pluginsInstallCmd = &Command{
	Topic:       "plugins",
	Command:     "install",
	Hidden:      true,
	Args:        []Arg{{Name: "name"}},
	Description: "Installs a plugin into the CLI",
	Help: `Install a Heroku plugin

  Example:
  $ heroku plugins:install dickeyxxx/heroku-production-status`,

	Run: func(ctx *Context) {
		name := ctx.Args.(map[string]string)["name"]
		if len(name) == 0 {
			Errln("Must specify a plugin name")
			return
		}
		Errf("Installing plugin %s... ", name)
		err := installPlugins(name)
		ExitIfError(err)
		plugin := getPlugin(name, true)
		if plugin == nil || len(plugin.Commands) == 0 {
			Err("\nThis does not appear to be a Heroku plugin, uninstalling... ")
			ExitIfError(gode.RemovePackage(name))
		}
		Errln("done")
	},
}

var pluginsLinkCmd = &Command{
	Topic:       "plugins",
	Command:     "link",
	Description: "Links a local plugin into CLI",
	Args:        []Arg{{Name: "path", Optional: true}},
	Help: `Links a local plugin into CLI.
	This is useful when developing plugins locally.
	It simply symlinks the specified path into ~/.heroku/node_modules

  Example:
	$ heroku plugins:link .`,

	Run: func(ctx *Context) {
		path := ctx.Args.(map[string]string)["path"]
		if path == "" {
			path = "."
		}
		path, err := filepath.Abs(path)
		if err != nil {
			panic(err)
		}
		if _, err := os.Stat(path); err != nil {
			panic(err)
		}
		name := filepath.Base(path)
		newPath := pluginPath(name)
		os.Remove(newPath)
		os.RemoveAll(newPath)
		err = os.Symlink(path, newPath)
		if err != nil {
			panic(err)
		}
		plugin := getPlugin(name, false)
		if plugin == nil || len(plugin.Commands) == 0 {
			Errln(name + " does not appear to be a Heroku plugin.\nDid you run " + cyan("npm install") + "?")
			if err := os.Remove(newPath); err != nil {
				panic(err)
			}
			return
		}
		if name != plugin.Name {
			path = newPath
			newPath = pluginPath(plugin.Name)
			os.Remove(newPath)
			os.RemoveAll(newPath)
			os.Rename(path, newPath)
		}
		Println("Symlinked", plugin.Name)
		AddPluginsToCache(plugin)
	},
}

var pluginsUninstallCmd = &Command{
	Topic:       "plugins",
	Command:     "uninstall",
	Hidden:      true,
	Args:        []Arg{{Name: "name"}},
	Description: "Uninstalls a plugin from the CLI",
	Help: `Uninstalls a Heroku plugin

  Example:
  $ heroku plugins:uninstall heroku-production-status`,

	Run: func(ctx *Context) {
		name := ctx.Args.(map[string]string)["name"]
		Errf("Uninstalling plugin %s... ", name)
		err := gode.RemovePackage(name)
		ExitIfError(err)
		RemovePluginFromCache(name)
		Errln("done")
	},
}

var pluginsListCmd = &Command{
	Topic:       "plugins",
	Hidden:      true,
	Description: "Lists installed plugins",
	Help: `
Example:
  $ heroku plugins`,

	Run: func(ctx *Context) {
		SetupBuiltinPlugins()
		var plugins []string
		for _, plugin := range GetPlugins() {
			if plugin != nil && len(plugin.Commands) > 0 {
				symlinked := ""
				if isPluginSymlinked(plugin.Name) {
					symlinked = " (symlinked)"
				}
				plugins = append(plugins, fmt.Sprintf("%s %s %s", plugin.Name, plugin.Version, symlinked))
			}
		}
		sort.Strings(plugins)
		for _, plugin := range plugins {
			Println(plugin)
		}
	},
}

func runFn(plugin *Plugin, topic, command string) func(ctx *Context) {
	return func(ctx *Context) {
		lockfile := updateLockPath + "." + plugin.Name
		if exists, _ := fileExists(lockfile); exists {
			golock.Lock(lockfile)
			golock.Unlock(lockfile)
		}
		ctx.Dev = isPluginSymlinked(plugin.Name)
		ctxJSON, err := json.Marshal(ctx)
		if err != nil {
			panic(err)
		}
		title, _ := json.Marshal(processTitle(ctx))
		script := fmt.Sprintf(`
		'use strict';
		var moduleName = '%s';
		var moduleVersion = '%s';
		var topic = '%s';
		var command = '%s';
		process.title = %s;
		var ctx = %s;
		ctx.version = ctx.version + ' ' + moduleName + '/' + moduleVersion + ' node-' + process.version;
		var logPath = %s;
		process.chdir(ctx.cwd);
		function repair (name) {
			console.error('Attempting to repair ' + name + '...');
			require('child_process')
			.spawnSync('heroku', ['plugins:install', name],
			{stdio: [0,1,2]});
			console.error('Repair complete. Try running your command again.');
		}
		if (!ctx.dev) {
			process.on('uncaughtException', function (err) {
				console.error(' !   Error in ' + moduleName + ':')
				if (err.message) {
					console.error(' !   ' + err.message);
					if (err.message.indexOf('Cannot find module') != -1) {
						repair(moduleName);
						process.exit(1);
					}
				} else {
					console.error(' !   ' + err);
				}
				if (err.stack) {
					var fs = require('fs');
					var log = function (line) {
						var d = new Date().toISOString()
						.replace(/T/, ' ')
						.replace(/-/g, '/')
						.replace(/\..+/, '');
						fs.appendFileSync(logPath, d + ' ' + line + '\n');
					}
					log('Error during ' + topic + ':' + command);
					log(err.stack);
					console.error(' !   See ' + logPath + ' for more info.');
				}
				process.exit(1);
			});
		}
		if (command === '') { command = null }
		var module = require(moduleName);
		var cmd = module.commands.filter(function (c) {
			return c.topic === topic && c.command == command;
		})[0];
		cmd.run(ctx);`, plugin.Name, plugin.Version, topic, command, string(title), ctxJSON, strconv.Quote(ErrLogPath))

		// swallow sigint since the plugin will handle it
		swallowSignal(os.Interrupt)

		cmd := gode.RunScript(script)
		cmd.Stdin = os.Stdin
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		if ctx.Flags["debugger"] == true {
			cmd = gode.DebugScript(script)
		}
		if err := cmd.Run(); err != nil {
			os.Exit(getExitCode(err))
		}
	}
}

func swallowSignal(s os.Signal) {
	c := make(chan os.Signal, 1)
	signal.Notify(c, s)
	go func() {
		<-c
	}()
}

func getExitCode(err error) int {
	switch e := err.(type) {
	case nil:
		return 0
	case *exec.ExitError:
		status, ok := e.Sys().(syscall.WaitStatus)
		if !ok {
			panic(err)
		}
		return status.ExitStatus()
	default:
		panic(err)
	}
}

func getPlugin(name string, attemptReinstall bool) *Plugin {
	script := `
	var plugin = require('` + name + `');
	if (!plugin.commands) plugin = {}; // not a real plugin
	var pjson  = require('` + name + `/package.json');

	plugin.name    = pjson.name;
	plugin.version = pjson.version;

	console.log(JSON.stringify(plugin))`
	cmd := gode.RunScript(script)
	output, err := cmd.CombinedOutput()
	if err != nil {
		if attemptReinstall && strings.Contains(string(output), "Error: Cannot find module") {
			Logln(string(output))
			Errf("Error reading plugin %s. Reinstalling... ", name)
			if err := installPlugins(name); err != nil {
				panic(errors.New(name + ": " + string(output)))
			}
			Errln("done")
			return getPlugin(name, false)
		}
		Errf("Error reading plugin: %s. See %s for more information.\n", name, ErrLogPath)
		Logln(err, "\n", string(output))
		return nil
	}
	var plugin Plugin
	json.Unmarshal([]byte(output), &plugin)
	for _, command := range plugin.Commands {
		command.Plugin = plugin.Name
		command.Help = strings.TrimSpace(command.Help)
	}
	return &plugin
}

// GetPlugins goes through all the node plugins and returns them in Go stucts
func GetPlugins() map[string]*Plugin {
	plugins := FetchPluginCache()
	for name, plugin := range plugins {
		if plugin == nil || !pluginExists(name) {
			delete(plugins, name)
		} else {
			for _, command := range plugin.Commands {
				command.Run = runFn(plugin, command.Topic, command.Command)
			}
		}
	}
	return plugins
}

// PluginNames lists all the plugin names
func PluginNames() []string {
	plugins := FetchPluginCache()
	names := make([]string, 0, len(plugins))
	for _, plugin := range plugins {
		if plugin != nil {
			names = append(names, plugin.Name)
		}
	}
	return names
}

// PluginNamesNotSymlinked returns all the plugins that are not symlinked
func PluginNamesNotSymlinked() []string {
	a := PluginNames()
	b := make([]string, 0, len(a))
	for _, plugin := range a {
		if !isPluginSymlinked(plugin) {
			b = append(b, plugin)
		}
	}
	return b
}

func isPluginSymlinked(plugin string) bool {
	path := filepath.Join(AppDir(), "node_modules", plugin)
	fi, err := os.Lstat(path)
	if err != nil {
		return false
	}
	return fi.Mode()&os.ModeSymlink != 0
}

// SetupBuiltinPlugins ensures all the builtinPlugins are installed
func SetupBuiltinPlugins() {
	pluginNames := difference(BuiltinPlugins, PluginNames())
	if len(pluginNames) == 0 {
		return
	}
	Err("heroku-cli: Installing core plugins...")
	err := installPlugins(pluginNames...)
	if err != nil {
		Errln()
		PrintError(err)
		return
	}
	Errln(" done")
}

func difference(a, b []string) []string {
	res := make([]string, 0, len(a))
	for _, aa := range a {
		if !contains(b, aa) {
			res = append(res, aa)
		}
	}
	return res
}

func contains(arr []string, s string) bool {
	for _, a := range arr {
		if a == s {
			return true
		}
	}
	return false
}

func installPlugins(names ...string) error {
	for _, name := range names {
		lockfile := updateLockPath + "." + name
		LogIfError(golock.Lock(lockfile))
	}
	err := gode.InstallPackage(names...)
	if err != nil {
		return err
	}
	plugins := make([]*Plugin, 0, len(names))
	for _, name := range names {
		plugins = append(plugins, getPlugin(name, true))
	}
	AddPluginsToCache(plugins...)
	for _, name := range names {
		lockfile := updateLockPath + "." + name
		LogIfError(golock.Unlock(lockfile))
	}
	return nil
}

func pluginExists(plugin string) bool {
	exists, _ := fileExists(pluginPath(plugin))
	return exists
}

func pluginPath(plugin string) string {
	return filepath.Join(AppDir(), "node_modules", plugin)
}
<|endoftext|>


<commit_before>package jsonpointer

import (
	"errors"
	"sort"
	"strconv"
	"strings"

	"github.com/dustin/gojson"
)

var unparsable = errors.New("I can't parse this")

func arreq(a, b []string) bool {
	if len(a) == len(b) {
		for i := range a {
			if a[i] != b[i] {
				return false
			}
		}
		return true
	}

	return false
}

var decoder = strings.NewReplacer("~1", "/", "~0", "~")

func parsePointer(s string) []string {
	a := strings.Split(s[1:], "/")

	for i := range a {
		if strings.Contains(a[i], "~") {
			a[i] = decoder.Replace(a[i])
		}
	}
	return a
}

func encodePointer(p []string) string {
	totalLen := 1
	for _, s := range p {
		totalLen += len(s) + 1
	}
	out := make([]rune, 0, totalLen)

	for _, s := range p {
		out = append(out, '/')
		for _, c := range s {
			switch c {
			case '/':
				out = append(out, '~', '1')
			case '~':
				out = append(out, '~', '0')
			default:
				out = append(out, c)
			}
		}
	}
	return string(out)
}

func grokLiteral(b []byte) string {
	s, ok := json.UnquoteBytes(b)
	if !ok {
		panic("could not grok literal " + string(b))
	}
	return string(s)
}

// Find a section of raw JSON by specifying a JSONPointer.
func Find(data []byte, path string) ([]byte, error) {
	if path == "" {
		return data, nil
	}

	needle := parsePointer(path)

	scanner := &json.Scanner{}
	scanner.Reset()

	offset := 0
	beganLiteral := 0
	current := []string{}
	for {
		var newOp int
		if offset >= len(data) {
			newOp = scanner.EOF()
			break
			offset = len(data) + 1 // mark processed EOF with len+1
		} else {
			c := int(data[offset])
			offset++
			newOp = scanner.Step(scanner, c)
		}

		switch newOp {
		case json.ScanBeginArray:
			current = append(current, "0")
		case json.ScanObjectKey:
			current = append(current, grokLiteral(data[beganLiteral-1:offset-1]))
		case json.ScanBeginLiteral:
			beganLiteral = offset
		case json.ScanArrayValue:
			n, err := strconv.Atoi(current[len(current)-1])
			if err != nil {
				return nil, err
			}
			current[len(current)-1] = strconv.Itoa(n + 1)
		case json.ScanObjectValue:
			current = current[:len(current)-1]
		case json.ScanEndArray:
			current = current[:len(current)-1]
		}

		if (newOp == json.ScanBeginArray || newOp == json.ScanArrayValue ||
			newOp == json.ScanObjectKey) && arreq(needle, current) {
			val, _, err := json.NextValue(data[offset:], scanner)
			return val, err
		}
	}

	return nil, nil
}

// Find a section of raw JSON by specifying a JSONPointer.
func FindMany(data []byte, paths []string) (map[string][]byte, error) {
	tpaths := make([]string, 0, len(paths))
	m := map[string][]byte{}
	for _, p := range paths {
		if p == "" {
			m[p] = data
		} else {
			tpaths = append(tpaths, p)
		}
	}
	sort.Strings(tpaths)

	scan := &json.Scanner{}
	scan.Reset()

	offset := 0
	todo := len(tpaths)
	beganLiteral := 0
	matchedAt := 0
	var current []string
	for todo > 0 {
		var newOp int
		if offset >= len(data) {
			newOp = scan.EOF()
			break
			offset = len(data) + 1 // mark processed EOF with len+1
		} else {
			c := int(data[offset])
			offset++
			newOp = scan.Step(scan, c)
		}

		switch newOp {
		case json.ScanBeginArray:
			current = append(current, "0")
		case json.ScanObjectKey:
			current = append(current, grokLiteral(data[beganLiteral-1:offset-1]))
		case json.ScanBeginLiteral:
			beganLiteral = offset
		case json.ScanArrayValue:
			n, err := strconv.Atoi(current[len(current)-1])
			if err != nil {
				return nil, err
			}
			current[len(current)-1] = strconv.Itoa(n + 1)
		case json.ScanObjectValue, json.ScanEndArray, json.ScanEndObject:
			current = current[:len(current)-1]
		}

		if newOp == json.ScanBeginArray || newOp == json.ScanArrayValue ||
			newOp == json.ScanObjectKey {

			if matchedAt < len(current)-1 {
				continue
			}
			if matchedAt > len(current) {
				matchedAt = len(current)
			}

			currentStr := encodePointer(current)
			off := sort.SearchStrings(tpaths, currentStr)
			if off < len(tpaths) {
				// Check to see if the path we're
				// going down could even lead to a
				// possible match.
				if strings.HasPrefix(tpaths[off], currentStr) {
					matchedAt++
				}
				// And if it's not an exact match, keep parsing.
				if tpaths[off] != currentStr {
					continue
				}
			} else {
				// Fell of the end of the list, no possible match
				continue
			}

			// At this point, we have an exact match, so grab it.
			stmp := &json.Scanner{}
			val, _, err := json.NextValue(data[offset:], stmp)
			if err != nil {
				return m, err
			}
			m[currentStr] = val
			todo--
		}
	}

	return m, nil
}
<commit_msg>Speed up the pointer encoder by skipping a pass.<commit_after>package jsonpointer

import (
	"errors"
	"sort"
	"strconv"
	"strings"

	"github.com/dustin/gojson"
)

var unparsable = errors.New("I can't parse this")

func arreq(a, b []string) bool {
	if len(a) == len(b) {
		for i := range a {
			if a[i] != b[i] {
				return false
			}
		}
		return true
	}

	return false
}

var decoder = strings.NewReplacer("~1", "/", "~0", "~")

func parsePointer(s string) []string {
	a := strings.Split(s[1:], "/")

	for i := range a {
		if strings.Contains(a[i], "~") {
			a[i] = decoder.Replace(a[i])
		}
	}
	return a
}

func encodePointer(p []string) string {
	out := make([]rune, 0, 64)

	for _, s := range p {
		out = append(out, '/')
		for _, c := range s {
			switch c {
			case '/':
				out = append(out, '~', '1')
			case '~':
				out = append(out, '~', '0')
			default:
				out = append(out, c)
			}
		}
	}
	return string(out)
}

func grokLiteral(b []byte) string {
	s, ok := json.UnquoteBytes(b)
	if !ok {
		panic("could not grok literal " + string(b))
	}
	return string(s)
}

// Find a section of raw JSON by specifying a JSONPointer.
func Find(data []byte, path string) ([]byte, error) {
	if path == "" {
		return data, nil
	}

	needle := parsePointer(path)

	scanner := &json.Scanner{}
	scanner.Reset()

	offset := 0
	beganLiteral := 0
	current := []string{}
	for {
		var newOp int
		if offset >= len(data) {
			newOp = scanner.EOF()
			break
			offset = len(data) + 1 // mark processed EOF with len+1
		} else {
			c := int(data[offset])
			offset++
			newOp = scanner.Step(scanner, c)
		}

		switch newOp {
		case json.ScanBeginArray:
			current = append(current, "0")
		case json.ScanObjectKey:
			current = append(current, grokLiteral(data[beganLiteral-1:offset-1]))
		case json.ScanBeginLiteral:
			beganLiteral = offset
		case json.ScanArrayValue:
			n, err := strconv.Atoi(current[len(current)-1])
			if err != nil {
				return nil, err
			}
			current[len(current)-1] = strconv.Itoa(n + 1)
		case json.ScanObjectValue:
			current = current[:len(current)-1]
		case json.ScanEndArray:
			current = current[:len(current)-1]
		}

		if (newOp == json.ScanBeginArray || newOp == json.ScanArrayValue ||
			newOp == json.ScanObjectKey) && arreq(needle, current) {
			val, _, err := json.NextValue(data[offset:], scanner)
			return val, err
		}
	}

	return nil, nil
}

// Find a section of raw JSON by specifying a JSONPointer.
func FindMany(data []byte, paths []string) (map[string][]byte, error) {
	tpaths := make([]string, 0, len(paths))
	m := map[string][]byte{}
	for _, p := range paths {
		if p == "" {
			m[p] = data
		} else {
			tpaths = append(tpaths, p)
		}
	}
	sort.Strings(tpaths)

	scan := &json.Scanner{}
	scan.Reset()

	offset := 0
	todo := len(tpaths)
	beganLiteral := 0
	matchedAt := 0
	var current []string
	for todo > 0 {
		var newOp int
		if offset >= len(data) {
			newOp = scan.EOF()
			break
			offset = len(data) + 1 // mark processed EOF with len+1
		} else {
			c := int(data[offset])
			offset++
			newOp = scan.Step(scan, c)
		}

		switch newOp {
		case json.ScanBeginArray:
			current = append(current, "0")
		case json.ScanObjectKey:
			current = append(current, grokLiteral(data[beganLiteral-1:offset-1]))
		case json.ScanBeginLiteral:
			beganLiteral = offset
		case json.ScanArrayValue:
			n, err := strconv.Atoi(current[len(current)-1])
			if err != nil {
				return nil, err
			}
			current[len(current)-1] = strconv.Itoa(n + 1)
		case json.ScanObjectValue, json.ScanEndArray, json.ScanEndObject:
			current = current[:len(current)-1]
		}

		if newOp == json.ScanBeginArray || newOp == json.ScanArrayValue ||
			newOp == json.ScanObjectKey {

			if matchedAt < len(current)-1 {
				continue
			}
			if matchedAt > len(current) {
				matchedAt = len(current)
			}

			currentStr := encodePointer(current)
			off := sort.SearchStrings(tpaths, currentStr)
			if off < len(tpaths) {
				// Check to see if the path we're
				// going down could even lead to a
				// possible match.
				if strings.HasPrefix(tpaths[off], currentStr) {
					matchedAt++
				}
				// And if it's not an exact match, keep parsing.
				if tpaths[off] != currentStr {
					continue
				}
			} else {
				// Fell of the end of the list, no possible match
				continue
			}

			// At this point, we have an exact match, so grab it.
			stmp := &json.Scanner{}
			val, _, err := json.NextValue(data[offset:], stmp)
			if err != nil {
				return m, err
			}
			m[currentStr] = val
			todo--
		}
	}

	return m, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"strings"
	"time"
)

func Usage() {
	fmt.Fprintf(os.Stderr, "Usage: %s [STOP|START] [STOPFILE]\n", os.Args[0])
	os.Exit(1)
}

func main() {
	if len(os.Args) != 3 {
		Usage()
	}
	mode := strings.ToLower(os.Args[1])
	filename := os.Args[2]
	switch mode {
	case "start":
		if _, err := os.Stat(filename); os.IsNotExist(err) {
			f, err := os.Create(filename)
			if err != nil {
				fmt.Fprintln(os.Stderr, "Error:", err)
				os.Exit(1)
			}
			f.Close()
		}
		tick := time.NewTicker(time.Second)
		for _ = range tick.C {
			if _, err := os.Stat(filename); os.IsNotExist(err) {
				fmt.Println("Exiting now...")
				return
			}
			fmt.Println("Hello")
		}
	case "stop":
		os.Remove(filename)
	default:
		Usage()
	}
}
<commit_msg>Update for to be for range.<commit_after>package main

import (
	"fmt"
	"os"
	"strings"
	"time"
)

func Usage() {
	fmt.Fprintf(os.Stderr, "Usage: %s [STOP|START] [STOPFILE]\n", os.Args[0])
	os.Exit(1)
}

func main() {
	if len(os.Args) != 3 {
		Usage()
	}
	mode := strings.ToLower(os.Args[1])
	filename := os.Args[2]
	switch mode {
	case "start":
		if _, err := os.Stat(filename); os.IsNotExist(err) {
			f, err := os.Create(filename)
			if err != nil {
				fmt.Fprintln(os.Stderr, "Error:", err)
				os.Exit(1)
			}
			f.Close()
		}
		tick := time.NewTicker(time.Second)
		for range tick.C {
			if _, err := os.Stat(filename); os.IsNotExist(err) {
				fmt.Println("Exiting now...")
				return
			}
			fmt.Println("Hello")
		}
	case "stop":
		os.Remove(filename)
	default:
		Usage()
	}
}
<|endoftext|>


<commit_before>package commander

import (
	"errors"
	"flag"
	"fmt"
	"os"
	"strings"
)

var ErrUnrecognizedCommand = errors.New("No command executed")

// Command wraps together the short command name, the description
// for a command, the commands Flags and the function that will handle
// the command.
type Command struct {
	Command     string
	Description string
	FlagSet     *flag.FlagSet
	F           func(args []string) error
}

// NewCommand creates a new comandeer Command struct with the given parameters.
func NewCommand(cmd, description string, flagset *flag.FlagSet, f func(args []string) error) *Command {
	return &Command{cmd, description, flagset, f}
}

// CommandFunction returns a command
type CommandFunction func() *Command

// MightExecute returns a boolean indicating if the command executed, and the error if it did
// (which can be nil if no error occurred)
// This is useful in a situation where you might execute a command, but don't mind if no command
// is executed, but want to catch an error if a command fails. This is coded as:
//
// if did,err=commander.MightExecute(...); did&&nil!=err {
//   panic(err)
// }
func MightExecute(args []string, commandFns ...CommandFunction) (bool, error) {
	err := Execute(args, commandFns...)
	return ErrUnrecognizedCommand != err, err
}

// MightExecuteWithErrorHandler might execute any command,
// and has an associated error handler if an error occurs.
// It returns true if a command was executed, false otherwise.
func MightExecuteWithErrorHandler(errHandler func(err error), args []string, commandFns ...CommandFunction) bool {
	b, err := MightExecute(args, commandFns...)
	if b && nil != err && ErrUnrecognizedCommand != err {
		errHandler(err)
	}
	return b
}

// Execute takes an args array, and executes the appropriate command from the
// array of commandFunctions. If nil is passed as the args array, os.Args is used
// by default.
func Execute(args []string, commandFns ...CommandFunction) error {
	if nil == args {
		args = os.Args[1:]
	}
	commands := make(map[string]*Command, len(commandFns))
	for _, c := range commandFns {
		cmd := c()
		commands[strings.ToLower(cmd.Command)] = cmd
	}

	if 0 == len(args) {
		// We return UnrecognizedCommand if no command exists
		return ErrUnrecognizedCommand
	}

	if strings.ToLower(args[0]) == "help" {
		if 1 < len(args) {
			for _, c := range args[1:] {
				cmd, ok := commands[strings.ToLower(c)]
				if !ok {
					fmt.Println("Unrecognized sub-command: ", cmd)
					continue
				}
				if nil != cmd.FlagSet {
					cmd.FlagSet.PrintDefaults()
				} else {
					fmt.Printf("%s takes no arguments: %s", cmd.Command, cmd.Description)
				}
			}
			return nil
		}
		fmt.Println(`Commands are:`)
		for _, c := range commands {
			fmt.Printf("%s\t\t%s\n", c.Command, c.Description)
		}
		return nil
	}

	c, ok := commands[strings.ToLower(args[0])]
	if !ok {
		return ErrUnrecognizedCommand
	}
	args = args[1:]
	if nil != c.FlagSet {
		c.FlagSet.Parse(args)
		args = c.FlagSet.Args()
	}
	return c.F(args)
}
<commit_msg>help sorts sub-commands alphabetically<commit_after>package commander

import (
	"errors"
	"flag"
	"fmt"
	"os"
	"strings"
	"sort"
)

var ErrUnrecognizedCommand = errors.New("No command executed")

// Command wraps together the short command name, the description
// for a command, the commands Flags and the function that will handle
// the command.
type Command struct {
	Command     string
	Description string
	FlagSet     *flag.FlagSet
	F           func(args []string) error
}

type CommandList []*Command

func (cl CommandList) Len() int {
	return len(cl)
}
func (cl CommandList) Less(i, j int) bool {
	clp := []*Command(cl)
	return clp[i].Command < clp[j].Command
}
func (cl CommandList) Swap(i,j int) {
	clp := []*Command(cl)
	clp[i], clp[j] = clp[j], clp[i]
}

// NewCommand creates a new comandeer Command struct with the given parameters.
func NewCommand(cmd, description string, flagset *flag.FlagSet, f func(args []string) error) *Command {
	return &Command{cmd, description, flagset, f}
}

// CommandFunction returns a command
type CommandFunction func() *Command

// MightExecute returns a boolean indicating if the command executed, and the error if it did
// (which can be nil if no error occurred)
// This is useful in a situation where you might execute a command, but don't mind if no command
// is executed, but want to catch an error if a command fails. This is coded as:
//
// if did,err=commander.MightExecute(...); did&&nil!=err {
//   panic(err)
// }
func MightExecute(args []string, commandFns ...CommandFunction) (bool, error) {
	err := Execute(args, commandFns...)
	return ErrUnrecognizedCommand != err, err
}

// MightExecuteWithErrorHandler might execute any command,
// and has an associated error handler if an error occurs.
// It returns true if a command was executed, false otherwise.
func MightExecuteWithErrorHandler(errHandler func(err error), args []string, commandFns ...CommandFunction) bool {
	b, err := MightExecute(args, commandFns...)
	if b && nil != err && ErrUnrecognizedCommand != err {
		errHandler(err)
	}
	return b
}

// Execute takes an args array, and executes the appropriate command from the
// array of commandFunctions. If nil is passed as the args array, os.Args is used
// by default.
func Execute(args []string, commandFns ...CommandFunction) error {
	if nil == args {
		args = os.Args[1:]
	}
	commands := make(map[string]*Command, len(commandFns))
	for _, c := range commandFns {
		cmd := c()
		commands[strings.ToLower(cmd.Command)] = cmd
	}

	if 0 == len(args) {
		// We return UnrecognizedCommand if no command exists
		return ErrUnrecognizedCommand
	}

	if strings.ToLower(args[0]) == "help" {
		if 1 < len(args) {
			for _, c := range args[1:] {
				cmd, ok := commands[strings.ToLower(c)]
				if !ok {
					fmt.Println("Unrecognized sub-command: ", cmd)
					continue
				}
				if nil != cmd.FlagSet {
					cmd.FlagSet.PrintDefaults()
				} else {
					fmt.Printf("%s takes no arguments: %s", cmd.Command, cmd.Description)
				}
			}
			return nil
		}
		fmt.Println(`Commands are:`)
		clp := make([]*Command, len(commands))
		i := 0
		for _, c := range commands {
			clp[i] = c
			i++
		}
		sort.Sort(CommandList(clp))
		for _, c := range clp {
			fmt.Printf("%s\t\t%s\n", c.Command, c.Description)
		}
		return nil
	}

	c, ok := commands[strings.ToLower(args[0])]
	if !ok {
		return ErrUnrecognizedCommand
	}
	args = args[1:]
	if nil != c.FlagSet {
		c.FlagSet.Parse(args)
		args = c.FlagSet.Args()
	}
	return c.F(args)
}
<|endoftext|>


<commit_before>package dropsonde_unmarshaller

import (
	"github.com/cloudfoundry/dropsonde/events"
	"github.com/cloudfoundry/gosteno"
	"github.com/cloudfoundry/loggregatorlib/cfcomponent/instrumentation"
	"sync"
)

// A DropsondeUnmarshallerCollection is a collection of DropsondeUnmarshaller instances.
type DropsondeUnmarshallerCollection interface {
	instrumentation.Instrumentable
	Run(inputChan <-chan []byte, outputChan chan<- *events.Envelope, waitGroup *sync.WaitGroup)
	Size() int
}

// NewDropsondeUnmarshallerCollection instantiates a DropsondeUnmarshallerCollection,
// creates the specified number of DropsondeUnmarshaller instances and logs to the
// provided logger.
func NewDropsondeUnmarshallerCollection(logger *gosteno.Logger, size int) DropsondeUnmarshallerCollection {
	var unmarshallers []DropsondeUnmarshaller
	for i := 0; i < size; i++ {
		unmarshallers = append(unmarshallers, NewDropsondeUnmarshaller(logger))
	}

	logger.Debugf("dropsondeUnmarshallerCollection: created %v unmarshallers", size)

	return &dropsondeUnmarshallerCollection{
		logger:        logger,
		unmarshallers: unmarshallers,
	}
}

type dropsondeUnmarshallerCollection struct {
	unmarshallers []DropsondeUnmarshaller
	logger        *gosteno.Logger
}

// Returns the number of unmarshallers in its collection.
func (u *dropsondeUnmarshallerCollection) Size() int {
	return len(u.unmarshallers)
}

// Run calls Run on each marshaller in its collection.
// This is done in separate go routines.
func (u *dropsondeUnmarshallerCollection) Run(inputChan <-chan []byte, outputChan chan<- *events.Envelope, waitGroup *sync.WaitGroup) {
	for _, unmarshaller := range u.unmarshallers {
		go func() {
			defer waitGroup.Done()
			unmarshaller.Run(inputChan, outputChan)
		}()
	}
}

// Emit returns the current metrics the DropsondeMarshallerCollection keeps about itself.
func (u *dropsondeUnmarshallerCollection) Emit() instrumentation.Context {
	return instrumentation.Context{
		Name:    "dropsondeUnmarshaller",
		Metrics: u.metrics(),
	}
}

func (u *dropsondeUnmarshallerCollection) metrics() []instrumentation.Metric {
	var internalMetrics []instrumentation.Metric
	var metrics []instrumentation.Metric

	for _, u := range u.unmarshallers {
		internalMetrics = append(internalMetrics, u.Emit().Metrics...)
	}

	metricsByName := make(map[string][]instrumentation.Metric)
	for _, metric := range internalMetrics {
		metricsEntry := metricsByName[metric.Name]
		metricsByName[metric.Name] = append(metricsEntry, metric)
	}

	concatTotalLogMessages(&metricsByName, &metrics)
	concatLogMessagesReceivedPerApp(&metricsByName, &metrics)
	concatOtherEventTypes(&metricsByName, &metrics)

	return metrics
}

func concatTotalLogMessages(metricsByName *map[string][]instrumentation.Metric, metrics *[]instrumentation.Metric) {
	totalLogs := uint64(0)
	for _, metric := range (*metricsByName)["logMessageTotal"] {
		totalLogs += metric.Value.(uint64)
	}

	*metrics = append(*metrics, instrumentation.Metric{Name: "logMessageTotal", Value: totalLogs})
}

func concatLogMessagesReceivedPerApp(metricsByName *map[string][]instrumentation.Metric, metrics *[]instrumentation.Metric) {
	logsReceivedPerApp := make(map[string]uint64)
	for _, metric := range (*metricsByName)["logMessageReceived"] {
		appId := metric.Tags["appId"].(string)
		logsReceivedPerApp[appId] += metric.Value.(uint64)
	}

	for appId, count := range logsReceivedPerApp {
		tags := make(map[string]interface{})
		tags["appId"] = appId
		*metrics = append(*metrics, instrumentation.Metric{Name: "logMessageReceived", Value: count, Tags: tags})
	}
}

func concatOtherEventTypes(metricsByName *map[string][]instrumentation.Metric, metrics *[]instrumentation.Metric) {
	metricsByEventType := make(map[string]uint64)

	for eventType, eventTypeMetrics := range *metricsByName {
		if eventType == "logMessageTotal" || eventType == "logMessageReceived" {
			continue
		}

		for _, metric := range eventTypeMetrics {
			metricsByEventType[eventType] += metric.Value.(uint64)
		}
	}

	for eventType, count := range metricsByEventType {
		*metrics = append(*metrics, instrumentation.Metric{Name: eventType, Value: count})
	}
}
<commit_msg>Fix go vet issue<commit_after>package dropsonde_unmarshaller

import (
	"github.com/cloudfoundry/dropsonde/events"
	"github.com/cloudfoundry/gosteno"
	"github.com/cloudfoundry/loggregatorlib/cfcomponent/instrumentation"
	"sync"
)

// A DropsondeUnmarshallerCollection is a collection of DropsondeUnmarshaller instances.
type DropsondeUnmarshallerCollection interface {
	instrumentation.Instrumentable
	Run(inputChan <-chan []byte, outputChan chan<- *events.Envelope, waitGroup *sync.WaitGroup)
	Size() int
}

// NewDropsondeUnmarshallerCollection instantiates a DropsondeUnmarshallerCollection,
// creates the specified number of DropsondeUnmarshaller instances and logs to the
// provided logger.
func NewDropsondeUnmarshallerCollection(logger *gosteno.Logger, size int) DropsondeUnmarshallerCollection {
	var unmarshallers []DropsondeUnmarshaller
	for i := 0; i < size; i++ {
		unmarshallers = append(unmarshallers, NewDropsondeUnmarshaller(logger))
	}

	logger.Debugf("dropsondeUnmarshallerCollection: created %v unmarshallers", size)

	return &dropsondeUnmarshallerCollection{
		logger:        logger,
		unmarshallers: unmarshallers,
	}
}

type dropsondeUnmarshallerCollection struct {
	unmarshallers []DropsondeUnmarshaller
	logger        *gosteno.Logger
}

// Returns the number of unmarshallers in its collection.
func (u *dropsondeUnmarshallerCollection) Size() int {
	return len(u.unmarshallers)
}

// Run calls Run on each marshaller in its collection.
// This is done in separate go routines.
func (u *dropsondeUnmarshallerCollection) Run(inputChan <-chan []byte, outputChan chan<- *events.Envelope, waitGroup *sync.WaitGroup) {
	for _, unmarshaller := range u.unmarshallers {
		go func(um DropsondeUnmarshaller) {
			defer waitGroup.Done()
			um.Run(inputChan, outputChan)
		}(unmarshaller)
	}
}

// Emit returns the current metrics the DropsondeMarshallerCollection keeps about itself.
func (u *dropsondeUnmarshallerCollection) Emit() instrumentation.Context {
	return instrumentation.Context{
		Name:    "dropsondeUnmarshaller",
		Metrics: u.metrics(),
	}
}

func (u *dropsondeUnmarshallerCollection) metrics() []instrumentation.Metric {
	var internalMetrics []instrumentation.Metric
	var metrics []instrumentation.Metric

	for _, u := range u.unmarshallers {
		internalMetrics = append(internalMetrics, u.Emit().Metrics...)
	}

	metricsByName := make(map[string][]instrumentation.Metric)
	for _, metric := range internalMetrics {
		metricsEntry := metricsByName[metric.Name]
		metricsByName[metric.Name] = append(metricsEntry, metric)
	}

	concatTotalLogMessages(&metricsByName, &metrics)
	concatLogMessagesReceivedPerApp(&metricsByName, &metrics)
	concatOtherEventTypes(&metricsByName, &metrics)

	return metrics
}

func concatTotalLogMessages(metricsByName *map[string][]instrumentation.Metric, metrics *[]instrumentation.Metric) {
	totalLogs := uint64(0)
	for _, metric := range (*metricsByName)["logMessageTotal"] {
		totalLogs += metric.Value.(uint64)
	}

	*metrics = append(*metrics, instrumentation.Metric{Name: "logMessageTotal", Value: totalLogs})
}

func concatLogMessagesReceivedPerApp(metricsByName *map[string][]instrumentation.Metric, metrics *[]instrumentation.Metric) {
	logsReceivedPerApp := make(map[string]uint64)
	for _, metric := range (*metricsByName)["logMessageReceived"] {
		appId := metric.Tags["appId"].(string)
		logsReceivedPerApp[appId] += metric.Value.(uint64)
	}

	for appId, count := range logsReceivedPerApp {
		tags := make(map[string]interface{})
		tags["appId"] = appId
		*metrics = append(*metrics, instrumentation.Metric{Name: "logMessageReceived", Value: count, Tags: tags})
	}
}

func concatOtherEventTypes(metricsByName *map[string][]instrumentation.Metric, metrics *[]instrumentation.Metric) {
	metricsByEventType := make(map[string]uint64)

	for eventType, eventTypeMetrics := range *metricsByName {
		if eventType == "logMessageTotal" || eventType == "logMessageReceived" {
			continue
		}

		for _, metric := range eventTypeMetrics {
			metricsByEventType[eventType] += metric.Value.(uint64)
		}
	}

	for eventType, count := range metricsByEventType {
		*metrics = append(*metrics, instrumentation.Metric{Name: eventType, Value: count})
	}
}
<|endoftext|>


<commit_before>//  Copyright (c) 2018 Cisco and/or its affiliates.
//
//  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 kvdbsync

import (
	"fmt"

	"github.com/ligato/cn-infra/infra"
	"github.com/ligato/cn-infra/logging"
	"github.com/ligato/cn-infra/servicelabel"
)

// NewPlugin creates a new Plugin with the provided Options.
func NewPlugin(opts ...Option) *Plugin {
	p := &Plugin{}

	p.PluginName = "kvdb"
	p.ServiceLabel = &servicelabel.DefaultPlugin

	for _, o := range opts {
		o(p)
	}

	prefix := p.String()
	if p.Deps.KvPlugin != nil {
		if kvdb, ok := p.Deps.KvPlugin.(fmt.Stringer); ok {
			prefix = kvdb.String()
		}
	}
	p.Deps.PluginName = infra.PluginName(prefix + "-datasync")

	if p.Deps.Log == nil {
		p.Deps.Log = logging.ForPlugin(p.String())
	}

	return p
}

// Option is a function that can be used in NewPlugin to customize Plugin.
type Option func(*Plugin)

// UseDeps returns Option that can inject custom dependencies.
func UseDeps(cb func(*Deps)) Option {
	return func(p *Plugin) {
		cb(&p.Deps)
	}
}
<commit_msg>Concatenate name for kvdbsync plugin<commit_after>//  Copyright (c) 2018 Cisco and/or its affiliates.
//
//  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 kvdbsync

import (
	"fmt"

	"github.com/ligato/cn-infra/logging"
	"github.com/ligato/cn-infra/servicelabel"
)

// NewPlugin creates a new Plugin with the provided Options.
func NewPlugin(opts ...Option) *Plugin {
	p := &Plugin{}

	p.PluginName = "kvdb"
	p.ServiceLabel = &servicelabel.DefaultPlugin

	for _, o := range opts {
		o(p)
	}

	name := p.String()
	if p.Deps.KvPlugin != nil {
		name = fmt.Sprintf("%s-%s", name, p.Deps.KvPlugin.String())
	}
	p.Deps.SetName(name + "-datasync")

	if p.Deps.Log == nil {
		p.Deps.Log = logging.ForPlugin(p.String())
	}

	return p
}

// Option is a function that can be used in NewPlugin to customize Plugin.
type Option func(*Plugin)

// UseDeps returns Option that can inject custom dependencies.
func UseDeps(cb func(*Deps)) Option {
	return func(p *Plugin) {
		cb(&p.Deps)
	}
}
<|endoftext|>


<commit_before>// Copyright 2017-18 Daniel Swarbrick. All rights reserved.
// Copyright 2021 Christian Svensson. 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 sgio

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"strings"
)

const (
	ATA_PASSTHROUGH     = 0xa1
	ATA_TRUSTED_RCV     = 0x5c
	ATA_TRUSTED_SND     = 0x5e
	ATA_IDENTIFY_DEVICE = 0xec

	SCSI_INQUIRY          = 0x12
	SCSI_MODE_SENSE_6     = 0x1a
	SCSI_READ_CAPACITY_10 = 0x25
	SCSI_ATA_PASSTHRU_16  = 0x85
	SCSI_SECURITY_IN      = 0xa2
	SCSI_SECURITY_OUT     = 0xb5
)

// SCSI INQUIRY response
type InquiryResponse struct {
	Peripheral   byte // peripheral qualifier, device type
	_            byte
	Version      byte
	_            [5]byte
	VendorIdent  [8]byte
	ProductIdent [16]byte
	ProductRev   [4]byte
}

func (inq InquiryResponse) String() string {
	return fmt.Sprintf("Type=0x%x, Vendor=%s, Product=%s, Revision=%s",
		inq.Peripheral,
		strings.TrimSpace(string(inq.VendorIdent[:])),
		strings.TrimSpace(string(inq.ProductIdent[:])),
		strings.TrimSpace(string(inq.ProductRev[:])))
}

// ATA IDENTFY DEVICE response
type IdentifyDeviceResponse struct {
	_        [20]byte
	Serial   [20]byte
	_        [6]byte
	Firmware [8]byte
	Model    [40]byte
	_        [418]byte
}

func ATAString(b []byte) string {
	out := make([]byte, len(b))
	for i := 0; i < len(b)/2; i++ {
		out[i*2] = b[i*2+1]
		out[i*2+1] = b[i*2]
	}
	return string(out)
}

func (id IdentifyDeviceResponse) String() string {
	return fmt.Sprintf("Serial=%s, Firmware=%s, Model=%s",
		strings.TrimSpace(ATAString(id.Serial[:])),
		strings.TrimSpace(ATAString(id.Firmware[:])),
		strings.TrimSpace(ATAString(id.Model[:])))
}

// INQUIRY - Returns parsed inquiry data.
func SCSIInquiry(fd uintptr) (InquiryResponse, error) {
	var resp InquiryResponse

	respBuf := make([]byte, 36)

	cdb := CDB6{SCSI_INQUIRY}
	binary.BigEndian.PutUint16(cdb[3:], uint16(len(respBuf)))

	if err := SendCDB(fd, cdb[:], CDBFromDevice, &respBuf); err != nil {
		return resp, err
	}

	binary.Read(bytes.NewBuffer(respBuf), nativeEndian, &resp)

	return resp, nil
}

// ATA Passthrough via SCSI (which is what Linux uses for all ATA these days)
func ATAIdentify(fd uintptr) (IdentifyDeviceResponse, error) {
	var resp IdentifyDeviceResponse

	respBuf := make([]byte, 512)

	cdb := CDB12{ATA_PASSTHROUGH}
	cdb[1] = PIO_DATA_IN << 1
	cdb[2] = 0x0E
	cdb[4] = 1
	cdb[9] = ATA_IDENTIFY_DEVICE

	if err := SendCDB(fd, cdb[:], CDBFromDevice, &respBuf); err != nil {
		return resp, err
	}

	binary.Read(bytes.NewBuffer(respBuf), nativeEndian, &resp)

	return resp, nil
}

// SCSI MODE SENSE(6) - Returns the raw response
func SCSIModeSense(fd uintptr, pageNum, subPageNum, pageControl uint8) ([]byte, error) {
	respBuf := make([]byte, 64)

	cdb := CDB6{SCSI_MODE_SENSE_6}
	cdb[2] = (pageControl << 6) | (pageNum & 0x3f)
	cdb[3] = subPageNum
	cdb[4] = uint8(len(respBuf))

	if err := SendCDB(fd, cdb[:], CDBFromDevice, &respBuf); err != nil {
		return respBuf, err
	}

	return respBuf, nil
}

// SCSI READ CAPACITY(10) - Returns the capacity in bytes
func SCSIReadCapacity(fd uintptr) (uint64, error) {
	respBuf := make([]byte, 8)
	cdb := CDB10{SCSI_READ_CAPACITY_10}

	if err := SendCDB(fd, cdb[:], CDBFromDevice, &respBuf); err != nil {
		return 0, err
	}

	lastLBA := binary.BigEndian.Uint32(respBuf[0:]) // max. addressable LBA
	LBsize := binary.BigEndian.Uint32(respBuf[4:])  // logical block (i.e., sector) size
	capacity := (uint64(lastLBA) + 1) * uint64(LBsize)

	return capacity, nil
}

// ATA TRUSTED RECEIVE
func ATATrustedReceive(fd uintptr, proto uint8, comID uint16, resp *[]byte) error {
	cdb := CDB12{ATA_PASSTHROUGH}
	cdb[1] = PIO_DATA_IN << 1
	cdb[2] = 0x0E
	cdb[3] = proto
	cdb[4] = uint8(len(*resp) / 512)
	cdb[6] = uint8(comID & 0xff)
	cdb[7] = uint8((comID & 0xff00) >> 8)
	cdb[9] = ATA_TRUSTED_RCV
	if err := SendCDB(fd, cdb[:], CDBFromDevice, resp); err != nil {
		return err
	}
	return nil
}

// ATA TRUSTED SEND
func ATATrustedSend(fd uintptr, proto uint8, comID uint16, in []byte) error {
	cdb := CDB12{ATA_PASSTHROUGH}
	cdb[1] = PIO_DATA_OUT << 1
	cdb[2] = 0x06
	cdb[3] = proto
	cdb[4] = uint8(len(in) / 512)
	cdb[6] = uint8(comID & 0xff)
	cdb[7] = uint8((comID & 0xff00) >> 8)
	cdb[9] = ATA_TRUSTED_RCV
	if err := SendCDB(fd, cdb[:], CDBToDevice, &in); err != nil {
		return err
	}
	return nil
}

// SCSI SECURITY IN
func SCSISecurityIn(fd uintptr, proto uint8, sps uint16, resp *[]byte) error {
	if len(*resp) & 0x1ff > 0 {
		return fmt.Errorf("SCSISecurityIn only supports 512-byte aligned buffers")
	}
	cdb := CDB12{SCSI_SECURITY_IN}
	cdb[1] = proto
	cdb[2] = uint8((sps & 0xff00) >> 8)
	cdb[3] = uint8(sps & 0xff)
	//
	// Seagate 7E200 series seems to require INC_512 to be set, and all other
	// drives tested seem to be fine with it, so we only support 512 byte aligned
	cdb[4] = 1 << 7 // INC_512 = 1
	binary.BigEndian.PutUint32(cdb[6:], uint32(len(*resp)/512))

	if err := SendCDB(fd, cdb[:], CDBFromDevice, resp); err != nil {
		return err
	}
	return nil
}

// SCSI SECURITY OUT
func SCSISecurityOut(fd uintptr, proto uint8, sps uint16, in []byte) error {
	if len(in) & 0x1ff > 0 {
		return fmt.Errorf("SCSISecurityOut only supports 512-byte aligned buffers")
	}
	cdb := CDB12{SCSI_SECURITY_OUT}
	cdb[1] = proto
	cdb[2] = uint8((sps & 0xff00) >> 8)
	cdb[3] = uint8(sps & 0xff)
	//
	// Seagate 7E200 series seems to require INC_512 to be set, and all other
	// drives tested seem to be fine with it, so we only support 512 byte aligned
	// buffers.
	cdb[4] = 1 << 7 // INC_512 = 1
	binary.BigEndian.PutUint32(cdb[6:], uint32(len(in)/512))

	if err := SendCDB(fd, cdb[:], CDBToDevice, &in); err != nil {
		return err
	}
	return nil
}
<commit_msg>chore(fmt): fix formating<commit_after>// Copyright 2017-18 Daniel Swarbrick. All rights reserved.
// Copyright 2021 Christian Svensson. 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 sgio

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"strings"
)

const (
	ATA_PASSTHROUGH     = 0xa1
	ATA_TRUSTED_RCV     = 0x5c
	ATA_TRUSTED_SND     = 0x5e
	ATA_IDENTIFY_DEVICE = 0xec

	SCSI_INQUIRY          = 0x12
	SCSI_MODE_SENSE_6     = 0x1a
	SCSI_READ_CAPACITY_10 = 0x25
	SCSI_ATA_PASSTHRU_16  = 0x85
	SCSI_SECURITY_IN      = 0xa2
	SCSI_SECURITY_OUT     = 0xb5
)

// SCSI INQUIRY response
type InquiryResponse struct {
	Peripheral   byte // peripheral qualifier, device type
	_            byte
	Version      byte
	_            [5]byte
	VendorIdent  [8]byte
	ProductIdent [16]byte
	ProductRev   [4]byte
}

func (inq InquiryResponse) String() string {
	return fmt.Sprintf("Type=0x%x, Vendor=%s, Product=%s, Revision=%s",
		inq.Peripheral,
		strings.TrimSpace(string(inq.VendorIdent[:])),
		strings.TrimSpace(string(inq.ProductIdent[:])),
		strings.TrimSpace(string(inq.ProductRev[:])))
}

// ATA IDENTFY DEVICE response
type IdentifyDeviceResponse struct {
	_        [20]byte
	Serial   [20]byte
	_        [6]byte
	Firmware [8]byte
	Model    [40]byte
	_        [418]byte
}

func ATAString(b []byte) string {
	out := make([]byte, len(b))
	for i := 0; i < len(b)/2; i++ {
		out[i*2] = b[i*2+1]
		out[i*2+1] = b[i*2]
	}
	return string(out)
}

func (id IdentifyDeviceResponse) String() string {
	return fmt.Sprintf("Serial=%s, Firmware=%s, Model=%s",
		strings.TrimSpace(ATAString(id.Serial[:])),
		strings.TrimSpace(ATAString(id.Firmware[:])),
		strings.TrimSpace(ATAString(id.Model[:])))
}

// INQUIRY - Returns parsed inquiry data.
func SCSIInquiry(fd uintptr) (InquiryResponse, error) {
	var resp InquiryResponse

	respBuf := make([]byte, 36)

	cdb := CDB6{SCSI_INQUIRY}
	binary.BigEndian.PutUint16(cdb[3:], uint16(len(respBuf)))

	if err := SendCDB(fd, cdb[:], CDBFromDevice, &respBuf); err != nil {
		return resp, err
	}

	binary.Read(bytes.NewBuffer(respBuf), nativeEndian, &resp)

	return resp, nil
}

// ATA Passthrough via SCSI (which is what Linux uses for all ATA these days)
func ATAIdentify(fd uintptr) (IdentifyDeviceResponse, error) {
	var resp IdentifyDeviceResponse

	respBuf := make([]byte, 512)

	cdb := CDB12{ATA_PASSTHROUGH}
	cdb[1] = PIO_DATA_IN << 1
	cdb[2] = 0x0E
	cdb[4] = 1
	cdb[9] = ATA_IDENTIFY_DEVICE

	if err := SendCDB(fd, cdb[:], CDBFromDevice, &respBuf); err != nil {
		return resp, err
	}

	binary.Read(bytes.NewBuffer(respBuf), nativeEndian, &resp)

	return resp, nil
}

// SCSI MODE SENSE(6) - Returns the raw response
func SCSIModeSense(fd uintptr, pageNum, subPageNum, pageControl uint8) ([]byte, error) {
	respBuf := make([]byte, 64)

	cdb := CDB6{SCSI_MODE_SENSE_6}
	cdb[2] = (pageControl << 6) | (pageNum & 0x3f)
	cdb[3] = subPageNum
	cdb[4] = uint8(len(respBuf))

	if err := SendCDB(fd, cdb[:], CDBFromDevice, &respBuf); err != nil {
		return respBuf, err
	}

	return respBuf, nil
}

// SCSI READ CAPACITY(10) - Returns the capacity in bytes
func SCSIReadCapacity(fd uintptr) (uint64, error) {
	respBuf := make([]byte, 8)
	cdb := CDB10{SCSI_READ_CAPACITY_10}

	if err := SendCDB(fd, cdb[:], CDBFromDevice, &respBuf); err != nil {
		return 0, err
	}

	lastLBA := binary.BigEndian.Uint32(respBuf[0:]) // max. addressable LBA
	LBsize := binary.BigEndian.Uint32(respBuf[4:])  // logical block (i.e., sector) size
	capacity := (uint64(lastLBA) + 1) * uint64(LBsize)

	return capacity, nil
}

// ATA TRUSTED RECEIVE
func ATATrustedReceive(fd uintptr, proto uint8, comID uint16, resp *[]byte) error {
	cdb := CDB12{ATA_PASSTHROUGH}
	cdb[1] = PIO_DATA_IN << 1
	cdb[2] = 0x0E
	cdb[3] = proto
	cdb[4] = uint8(len(*resp) / 512)
	cdb[6] = uint8(comID & 0xff)
	cdb[7] = uint8((comID & 0xff00) >> 8)
	cdb[9] = ATA_TRUSTED_RCV
	if err := SendCDB(fd, cdb[:], CDBFromDevice, resp); err != nil {
		return err
	}
	return nil
}

// ATA TRUSTED SEND
func ATATrustedSend(fd uintptr, proto uint8, comID uint16, in []byte) error {
	cdb := CDB12{ATA_PASSTHROUGH}
	cdb[1] = PIO_DATA_OUT << 1
	cdb[2] = 0x06
	cdb[3] = proto
	cdb[4] = uint8(len(in) / 512)
	cdb[6] = uint8(comID & 0xff)
	cdb[7] = uint8((comID & 0xff00) >> 8)
	cdb[9] = ATA_TRUSTED_RCV
	if err := SendCDB(fd, cdb[:], CDBToDevice, &in); err != nil {
		return err
	}
	return nil
}

// SCSI SECURITY IN
func SCSISecurityIn(fd uintptr, proto uint8, sps uint16, resp *[]byte) error {
	if len(*resp)&0x1ff > 0 {
		return fmt.Errorf("SCSISecurityIn only supports 512-byte aligned buffers")
	}
	cdb := CDB12{SCSI_SECURITY_IN}
	cdb[1] = proto
	cdb[2] = uint8((sps & 0xff00) >> 8)
	cdb[3] = uint8(sps & 0xff)
	//
	// Seagate 7E200 series seems to require INC_512 to be set, and all other
	// drives tested seem to be fine with it, so we only support 512 byte aligned
	cdb[4] = 1 << 7 // INC_512 = 1
	binary.BigEndian.PutUint32(cdb[6:], uint32(len(*resp)/512))

	if err := SendCDB(fd, cdb[:], CDBFromDevice, resp); err != nil {
		return err
	}
	return nil
}

// SCSI SECURITY OUT
func SCSISecurityOut(fd uintptr, proto uint8, sps uint16, in []byte) error {
	if len(in)&0x1ff > 0 {
		return fmt.Errorf("SCSISecurityOut only supports 512-byte aligned buffers")
	}
	cdb := CDB12{SCSI_SECURITY_OUT}
	cdb[1] = proto
	cdb[2] = uint8((sps & 0xff00) >> 8)
	cdb[3] = uint8(sps & 0xff)
	//
	// Seagate 7E200 series seems to require INC_512 to be set, and all other
	// drives tested seem to be fine with it, so we only support 512 byte aligned
	// buffers.
	cdb[4] = 1 << 7 // INC_512 = 1
	binary.BigEndian.PutUint32(cdb[6:], uint32(len(in)/512))

	if err := SendCDB(fd, cdb[:], CDBToDevice, &in); err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>/*
Copyright The Helm Authors.

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

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

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

package kube // import "helm.sh/helm/v3/pkg/kube"

import (
	apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
	apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
	"k8s.io/apimachinery/pkg/api/meta"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
	"k8s.io/cli-runtime/pkg/resource"
	"k8s.io/client-go/kubernetes/scheme"
)

// AsVersioned converts the given info into a runtime.Object with the correct
// group and version set
func AsVersioned(info *resource.Info) runtime.Object {
	return convertWithMapper(info.Object, info.Mapping)
}

// convertWithMapper converts the given object with the optional provided
// RESTMapping. If no mapping is provided, the default schema versioner is used
func convertWithMapper(obj runtime.Object, mapping *meta.RESTMapping) runtime.Object {
	s := kubernetesNativeScheme()
	var gv = runtime.GroupVersioner(schema.GroupVersions(s.PrioritizedVersionsAllGroups()))
	if mapping != nil {
		gv = mapping.GroupVersionKind.GroupVersion()
	}
	if obj, err := runtime.ObjectConvertor(s).ConvertToVersion(obj, gv); err == nil {
		return obj
	}
	return obj
}

// kubernetesNativeScheme returns a clean *runtime.Scheme with _only_ Kubernetes
// native resources added to it. This is required to break free of custom resources
// that may have been added to scheme.Scheme due to Helm being used as a package in
// combination with e.g. a versioned kube client. If we would not do this, the client
// may attempt to perform e.g. a 3-way-merge strategy patch for custom resources.
func kubernetesNativeScheme() *runtime.Scheme {
	s := runtime.NewScheme()
	utilruntime.Must(scheme.AddToScheme(s))
	// API extensions are not in the above scheme set,
	// and must thus be added separately.
	utilruntime.Must(apiextensionsv1beta1.AddToScheme(s))
	utilruntime.Must(apiextensionsv1.AddToScheme(s))
	return s
}
<commit_msg>fix(kube): generate k8s native scheme only once<commit_after>/*
Copyright The Helm Authors.

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

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

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

package kube // import "helm.sh/helm/v3/pkg/kube"

import (
	"sync"

	apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
	apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
	"k8s.io/apimachinery/pkg/api/meta"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/cli-runtime/pkg/resource"
	"k8s.io/client-go/kubernetes/scheme"
)

var k8sNativeScheme *runtime.Scheme
var k8sNativeSchemeOnce sync.Once

// AsVersioned converts the given info into a runtime.Object with the correct
// group and version set
func AsVersioned(info *resource.Info) runtime.Object {
	return convertWithMapper(info.Object, info.Mapping)
}

// convertWithMapper converts the given object with the optional provided
// RESTMapping. If no mapping is provided, the default schema versioner is used
func convertWithMapper(obj runtime.Object, mapping *meta.RESTMapping) runtime.Object {
	s := kubernetesNativeScheme()
	var gv = runtime.GroupVersioner(schema.GroupVersions(s.PrioritizedVersionsAllGroups()))
	if mapping != nil {
		gv = mapping.GroupVersionKind.GroupVersion()
	}
	if obj, err := runtime.ObjectConvertor(s).ConvertToVersion(obj, gv); err == nil {
		return obj
	}
	return obj
}

// kubernetesNativeScheme returns a clean *runtime.Scheme with _only_ Kubernetes
// native resources added to it. This is required to break free of custom resources
// that may have been added to scheme.Scheme due to Helm being used as a package in
// combination with e.g. a versioned kube client. If we would not do this, the client
// may attempt to perform e.g. a 3-way-merge strategy patch for custom resources.
func kubernetesNativeScheme() *runtime.Scheme {
	k8sNativeSchemeOnce.Do(func() {
		k8sNativeScheme = runtime.NewScheme()
		scheme.AddToScheme(k8sNativeScheme)
		// API extensions are not in the above scheme set,
		// and must thus be added separately.
		apiextensionsv1beta1.AddToScheme(k8sNativeScheme)
		apiextensionsv1.AddToScheme(k8sNativeScheme)
	})
	return k8sNativeScheme
}
<|endoftext|>