How to specify order of dependent tasks? - sbt

I have a task that must call other tasks in sequence.
val taskA = taskDef[Unit]("....")
val taskB = taskDef[Unit]("....")
val taskC = taskDef[Unit]("....")
val taskD = taskDef[Unit]("....")
taskA := {
taskB.value
taskC.value
taskD.value
}
taskB := {
...
}
taskC := {
...
}
taskD := {
...
}
The result is that although taskB, taskC and taskD are indeed called before taskA, I can't seem to find a way to control their order, i.e. taskD can be called before taskC.
How can I specify the running order?

The solution is to use dependsOn method of a setting combined with <<=:
val taskA = taskDef[Unit]("....")
val taskB = taskDef[Unit]("....")
val taskC = taskDef[Unit]("....")
val taskD = taskDef[Unit]("....")
taskA := {},
taskB := {
...
},
taskC := {
...
},
taskD := {
...
},
taskA <<= taskA.dependsOn(taskD),
taskD <<= taskA.dependsOn(taskC),
taskC <<= taskA.dependsOn(taskB),

Related

How to assign key,value to map[interface{}]interface{}?

var cache atomic.Value
func setResToCache(res *utils.InterfaceMap) error {
resMap := res.ToInterfaceMap()
val := resMap[constant.key] // constant.key is a constant string
val, ok := val.(string)
if !ok {
return errors.New("type assertion failed")
}
someRes := model.someRes{
Title: val,
}
Cache.Store(someRes)
return nil
}
about utils.InterfaceMap
type InterfaceMap sync.Map
//ToInterfaceMap
func (im *InterfaceMap) ToInterfaceMap() map[interface{}]interface{} {
iim := make(map[interface{}]interface{})
m := (*sync.Map)(im)
m.Range(func(k, v interface{}) bool {
iim[k] = v
return true
})
return iim
}
I have some code similar to the above, and I have a problem when I want to write a unit test.
{
name: "test",
args: args{
res: &utils.InterfaceMap{
// How to assign k,v here
},
},
wantErr: false,
},
How to how to assign key,value to map[interface{}]interface{}?
It is actually map[string]string, so I use assert, but the parameter passed in is map[interface{}]interface{}.
I want to add some string: string to map so that I can successfully test the code.
Create simple function in your test file to input map[string]string and inside the function, write those values to sync.Map and cast it to InterfaceMap type and return the reference. Example is as below.
func createMockInterfaceMap(in map[string]string) *utils.InterfaceMap{
mockMap := sync.Map{}
for key, value := range in {
mockMap.Store(key, value)
}
iMap := utils.InterfaceMap(mockMap)
return &iMap
}
{
name: "test",
args: args{
res: createMockInterfaceMap(map[string]string{
`key1`:`value1`,
`key2`:`value2`,
}),
},
wantErr: false,
},
To pass in a map[interface{}]interface{}, it will need to be defined as such.
You can convert a map[string]string to a map[interface{}]interface{} using something like the following:
func MapConvert(mss map[string]string) map[interface{}]interface{} {
ifaceMap := map[interface{}]interface{}{}
for k, v := range mss {
ifaceMap[k] = v
}
return ifaceMap
}
Here's an example using a type definition:
type InterfaceMap map[interface{}]interface{}
func MapConvert(mss map[string]string) *InterfaceMap {
ifaceMap := InterfaceMap{}
for k, v := range mss {
ifaceMap[k] = v
}
return &ifaceMap
}
Here's a full running example:
https://play.golang.org/p/UPKqqZnFis-

How to deref a pointer dynamically in Golang

I have this func:
func getStringRepresentation(v interface{}, size int, brk bool, depth int) string {
val := reflect.ValueOf(v)
if val.Kind() == reflect.Ptr {
v = *v.(types.Pointer) // does not work
val = reflect.ValueOf(v)
}
// ...
}
how can I dereference the pointer to get the value of it? When I use:
v = *v.(types.Pointer)
The error says:
Invalid indirect of 'v.(types.Pointer)' (type 'types.Pointer')
I tried this:
val := reflect.ValueOf(v)
if val.Kind() == reflect.Ptr {
v = v.(types.Pointer).Underlying()
val = reflect.ValueOf(v)
}
and I tried this too:
val := reflect.ValueOf(v)
if val.Kind() == reflect.Ptr {
v = val.Elem()
val = reflect.ValueOf(v)
}
I need to get the value of the interface{} from the pointer.
You can dereference pointers using reflect using Elem:
val := reflect.ValueOf(v)
if val.Kind() == reflect.Ptr {
val = val.Elem()
}
After the if statement, val is a reflect.Value representing the value passed in by the interface. If the value passed in is a pointer, val now has the dereferenced value of that pointer.
You have to use 'Elem' for access value referenced by Pointer.
package main
import (
"fmt"
"reflect"
)
func main() {
p := &struct{Hello string}{"world"}
v := reflect.ValueOf(p)
ps := v.Interface().(*struct{Hello string})
fmt.Println(ps)
s := v.Elem().Interface().(struct{Hello string})
fmt.Println(s)
}
Looks like this accomplished what I was trying to do:
func getStringRepresentation(v interface{}, size int, brk bool, depth int) string {
val := reflect.ValueOf(v)
if val.Kind() == reflect.Ptr {
v = val.Elem().Interface() // gets the actual interface from the pointer
val = reflect.ValueOf(v) // gets the value of the actual interface
}
// ...
}
thanks to the other answers which I stole the eventual solution from.

Reflection on slice of pointers

I am trying to reflect a slice of pointers on a struct stored in an interface{}
I think I am doing ok until it's time to introspect the content on the pointed struct.
See the below example
package main
import (
"fmt"
"reflect"
)
type teststruct struct {
prop1 string
prop2 string
}
func main() {
test := teststruct{"test", "12"}
var container interface{}
var testcontainer []*teststruct
testcontainer = append(testcontainer, &test)
container = testcontainer
rcontainer := reflect.ValueOf(container)
fmt.Println(rcontainer.Kind())
rtest := rcontainer.Index(0).Elem()
fmt.Println(rtest)
rteststruct := reflect.ValueOf(rtest)
fmt.Println(rteststruct.Kind())
typeOfT := rteststruct.Type()
for i := 0; i < rteststruct.NumField(); i++ {
f := rteststruct.Field(i)
fmt.Printf("%d: %s %s = %v\n", i, typeOfT.Field(i).Name, f.Type(), f.String())
}
}
Which results
slice
{test 12}
struct
0: typ *reflect.rtype = <*reflect.rtype Value>
1: ptr unsafe.Pointer = <unsafe.Pointer Value>
2: flag reflect.flag = <reflect.flag Value>
I am definitely missing something here, someone would be able to explain me what ?
rtest := rcontainer.Index(0).Elem() is already the value, so when you do this: rteststruct := reflect.ValueOf(rtest), you are actually getting a reflect.Value which is of course a struct.
Replace the end of your code with this:
typeOfT := rtest.Type()
for i := 0; i < rtest.NumField(); i++ {
f := rtest.Field(i)
fmt.Printf("%d: %s %s = %v\n", i, typeOfT.Field(i).Name, f.Type(), f.String())
}
Playground

How to cast reflect.Value to its type?

How to cast reflect.Value to its type?
type Cat struct {
Age int
}
cat := reflect.ValueOf(obj)
fmt.Println(cat.Type()) // Cat
fmt.Println(Cat(cat).Age) // doesn't compile
fmt.Println((cat.(Cat)).Age) // same
Thanks!
concreteCat,_ := reflect.ValueOf(cat).Interface().(Cat)
see http://golang.org/doc/articles/laws_of_reflection.html
fox example
type MyInt int
var x MyInt = 7
v := reflect.ValueOf(x)
y := v.Interface().(float64) // y will have type float64.
fmt.Println(y)
Ok, I found it
reflect.Value has a function Interface() that converts it to interface{}
This func auto-converts types as needed. It loads a config file values into a simple struct based on struct name and fields:
import (
"fmt"
toml "github.com/pelletier/go-toml"
"log"
"os"
"reflect"
)
func LoadConfig(configFileName string, configStruct interface{}) {
defer func() {
if r := recover(); r != nil {
fmt.Println("LoadConfig.Recovered: ", r)
}
}()
conf, err := toml.LoadFile(configFileName)
if err == nil {
v := reflect.ValueOf(configStruct)
typeOfS := v.Elem().Type()
sectionName := getTypeName(configStruct)
for i := 0; i < v.Elem().NumField(); i++ {
if v.Elem().Field(i).CanInterface() {
kName := conf.Get(sectionName + "." + typeOfS.Field(i).Name)
kValue := reflect.ValueOf(kName)
if (kValue.IsValid()) {
v.Elem().Field(i).Set(kValue.Convert(typeOfS.Field(i).Type))
}
}
}
} else {
fmt.Println("LoadConfig.Error: " + err.Error())
}
}
Seems the only way would be to do a switch statement similar to (code below) (also, something like the commented line would've-been nice though doesn't work (:()):
func valuesFromStruct (rawV interface{}) []interface{} {
v := reflect.ValueOf(rawV)
out := make([]interface{}, 0)
for i := 0; i < v.NumField(); i += 1 {
field := v.Field(i)
fieldType := field.Type()
// out = append(out, field.Interface().(reflect.PtrTo(fieldType)))
switch (fieldType.Name()) {
case "int64":
out = append(out, field.Interface().(int64))
break`enter code here`
case "float64":
out = append(out, field.Interface().(float64))
break
case "string":
out = append(out, field.Interface().(string))
break
// And all your other types (here) ...
default:
out = append(out, field.Interface())
break
}
}
return out
}
Cheers!

How to make task depend on another in sbt 0.12?

I'm using SBT 0.12.0.
I've two tasks in my project/Build.scala - helloTask and u2 defined as follows:
val hello = TaskKey[Unit]("hello", "Prints 'Hello World'")
val helloTask = hello := {
println("Hello World")
}
val u2Task = TaskKey[Unit]("u2") := { println("u2") }
How to make u2 task depend on hellotask? I used <<= following the sample as described in Tasks (in the original version of the question it was https://github.com/harrah/xsbt/wiki/Tasks, but the doc has since moved and changed).
u2Task <<= u2Task dependsOn helloTask
But I got reassignment to val error. Apparently, I cannot get anything with <<= to work. What am I doing wrong?
I don't see you following the sample very closely - this works for me:
val helloTask = TaskKey[String]("hello")
val u2Task = TaskKey[Unit]("u2")
helloTask := {
println("Hello World")
"Hello World"
}
u2Task := {println("u2")}
u2Task <<= u2Task.dependsOn (helloTask)
The precise reason is that your definition of u2Task has a different type, you can see in the REPL:
scala> val u2Task = TaskKey[Unit]("u2")
u2Task: sbt.TaskKey[Unit] = sbt.TaskKey$$anon$3#101ecc2
scala> val u2Task = TaskKey[Unit]("u2") := {println("u2")}
u2Task: sbt.Project.Setting[sbt.Task[Unit]] = setting(ScopedKey(Scope(This,This,This,This),u2))
I got it to work. I misunderstood the <<= and := operators as assignment operators.
val hello = TaskKey[Unit]("hello", "Prints 'Hello World'")
val helloTask = hello := {
println("Hello World")
}
val u2 = TaskKey[Unit]("u2", "print u2")
val u2Task = u2 <<= hello map {_ => println("u2")}
and the result
> u2
Hello World
u2

Resources