<commit_before>package lua

import (
	"errors"
	"unsafe"
)

var lua_tointegerx = luaDLL.NewProc("lua_tointegerx")

func (this Lua) ToInteger(index int) (int, error) {
	var issucceeded uintptr
	value, _, _ := lua_tointegerx.Call(this.State(), uintptr(index),
		uintptr(unsafe.Pointer(&issucceeded)))
	if issucceeded != 0 {
		return int(value), nil
	} else {
		return 0, errors.New("ToInteger: the value in not integer on the stack")
	}
}

var lua_tolstring = luaDLL.NewProc("lua_tolstring")

func (this Lua) ToAnsiString(index int) []byte {
	var length uintptr
	p, _, _ := lua_tolstring.Call(this.State(),
		uintptr(index),
		uintptr(unsafe.Pointer(&length)))
	if length <= 0 {
		return []byte{}
	} else {
		return CGoBytes(p, length)
	}
}

func (this Lua) ToString(index int) (string, error) {
	var length uintptr
	p, _, _ := lua_tolstring.Call(this.State(),
		uintptr(index),
		uintptr(unsafe.Pointer(&length)))
	return CGoStringN(p, length), nil
}

var lua_touserdata = luaDLL.NewProc("lua_touserdata")

func (this Lua) ToUserData(index int) unsafe.Pointer {
	rv, _, _ := lua_touserdata.Call(this.State(), uintptr(index))
	return unsafe.Pointer(rv)
}

var lua_toboolean = luaDLL.NewProc("lua_toboolean")

func (this Lua) ToBool(index int) bool {
	rv, _, _ := lua_toboolean.Call(this.State(), uintptr(index))
	return rv != 0
}

type TString struct {
	Value []byte
}

func (this *TString) String() (string, error) {
	if len(this.Value) <= 0 {
		return "", nil
	} else {
		return string(this.Value), nil
	}
}

func (this *TString) Push(L Lua) int {
	L.PushAnsiString(this.Value)
	return 1
}

type TFunction struct {
	Chank []byte
}

func (this *TFunction) Push(L Lua) int {
	err := L.LoadBufferX("(anonymous)", this.Chank, "b")
	if err == nil {
		return 1
	} else {
		return 0
	}
}

func (this Lua) ToSomething(index int) (interface{}, error) {
	switch this.GetType(index) {
	case LUA_TBOOLEAN:
		return this.ToBool(index), nil
	case LUA_TFUNCTION:
		return TFunction{Chank: this.Dump()}, nil
	case LUA_TLIGHTUSERDATA:
		return nil, errors.New("lua.ToAnything: LUA_TLIGHTUSERDATA not supported.")
	case LUA_TNIL:
		return nil, nil
	case LUA_TNUMBER:
		return this.ToInteger(index)
	case LUA_TSTRING:
		return TString{this.ToAnsiString(index)}, nil
	case LUA_TTABLE:
		return nil, errors.New("lua.ToAnything: LUA_TTABLE not supported.")
	case LUA_TUSERDATA:
		return nil, errors.New("lua.ToAnything: LUA_TUSERDATA not supported.")
	default:
		return nil, errors.New("lua.ToAnything: Not supported type found.")
	}
}
<commit_msg>lua.ToSomething support LUA_TTABLE (not test)<commit_after>package lua

import (
	"errors"
	"fmt"
	"unsafe"
)

var lua_tointegerx = luaDLL.NewProc("lua_tointegerx")

func (this Lua) ToInteger(index int) (int, error) {
	var issucceeded uintptr
	value, _, _ := lua_tointegerx.Call(this.State(), uintptr(index),
		uintptr(unsafe.Pointer(&issucceeded)))
	if issucceeded != 0 {
		return int(value), nil
	} else {
		return 0, errors.New("ToInteger: the value in not integer on the stack")
	}
}

var lua_tolstring = luaDLL.NewProc("lua_tolstring")

func (this Lua) ToAnsiString(index int) []byte {
	var length uintptr
	p, _, _ := lua_tolstring.Call(this.State(),
		uintptr(index),
		uintptr(unsafe.Pointer(&length)))
	if length <= 0 {
		return []byte{}
	} else {
		return CGoBytes(p, length)
	}
}

func (this Lua) ToString(index int) (string, error) {
	var length uintptr
	p, _, _ := lua_tolstring.Call(this.State(),
		uintptr(index),
		uintptr(unsafe.Pointer(&length)))
	return CGoStringN(p, length), nil
}

var lua_touserdata = luaDLL.NewProc("lua_touserdata")

func (this Lua) ToUserData(index int) unsafe.Pointer {
	rv, _, _ := lua_touserdata.Call(this.State(), uintptr(index))
	return unsafe.Pointer(rv)
}

var lua_toboolean = luaDLL.NewProc("lua_toboolean")

func (this Lua) ToBool(index int) bool {
	rv, _, _ := lua_toboolean.Call(this.State(), uintptr(index))
	return rv != 0
}

type TString struct {
	Value []byte
}

func (this *TString) String() (string, error) {
	if len(this.Value) <= 0 {
		return "", nil
	} else {
		return string(this.Value), nil
	}
}

func (this *TString) Push(L Lua) int {
	L.PushAnsiString(this.Value)
	return 1
}

type TFunction struct {
	Chank []byte
}

func (this *TFunction) Push(L Lua) int {
	err := L.LoadBufferX("(anonymous)", this.Chank, "b")
	if err == nil {
		return 1
	} else {
		return 0
	}
}

var lua_next = luaDLL.NewProc("lua_next")

func (this Lua) Next(index int) int {
	rc, _, _ := lua_next.Call(this.State(), uintptr(index))
	return int(rc)
}

func (this Lua) ToSomething(index int) (interface{}, error) {
	switch this.GetType(index) {
	case LUA_TBOOLEAN:
		return this.ToBool(index), nil
	case LUA_TFUNCTION:
		return TFunction{Chank: this.Dump()}, nil
	case LUA_TLIGHTUSERDATA:
		return nil, errors.New("lua.ToAnything: LUA_TLIGHTUSERDATA not supported.")
	case LUA_TNIL:
		return nil, nil
	case LUA_TNUMBER:
		return this.ToInteger(index)
	case LUA_TSTRING:
		return TString{this.ToAnsiString(index)}, nil
	case LUA_TTABLE:
		top := this.GetTop()
		defer this.SetTop(top)
		table := map[string]interface{}{}
		this.PushNil()
		if index < 0 {
			index--
		}
		for this.Next(index) != 0 {
			key, keyErr := this.ToSomething(-2)
			if keyErr == nil {
				val, valErr := this.ToSomething(-1)
				if valErr == nil {
					switch t := key.(type) {
					case string:
						table[t] = val
					case int:
						table[fmt.Sprintf("%d", t)] = val
					case nil:
						table[""] = val
					}
				}
			}
			this.Pop(1)
		}
		return table, nil
	case LUA_TUSERDATA:
		return nil, errors.New("lua.ToAnything: LUA_TUSERDATA not supported.")
	default:
		return nil, errors.New("lua.ToAnything: Not supported type found.")
	}
}
<|endoftext|>


<commit_before>package main

import(
  "fmt"
  "os"
  "io"
  "io/ioutil"
  "path/filepath"
  "os/exec"
  "strings"
)

const(
  LUNCHY_VERSION = "0.1.1"
)

func fileExists(path string) bool {
  _, err := os.Stat(path)
  return err == nil
}

func fileCopy(src string, dst string) error {
  s, err := os.Open(src)
  if err != nil {
    return err
  }

  defer s.Close()

  d, err := os.Create(dst)
  if err != nil {
    return err
  }

  if _, err := io.Copy(d, s); err != nil {
    d.Close()
    return err
  }

  return d.Close()
}

func findPlists(path string) []string {
  result := []string{}
  files, err := ioutil.ReadDir(path)

  if err != nil {
    return result
  }

  for _, file := range files {
    if !file.IsDir() {
      if (filepath.Ext(file.Name())) == ".plist" {
        name := strings.Replace(file.Name(), ".plist", "", -1)
        result = append(result, name)
      }
    }
  }

  return result
}

func getPlists() []string {
  path := fmt.Sprintf("%s/Library/LaunchAgents", os.Getenv("HOME"))
  files := findPlists(path)

  return files
}

func sliceIncludes(slice []string, match string) bool {
  for _, val := range slice {
    if val == match {
      return true
    }
  }

  return false
}

func printUsage() {
  fmt.Printf("Lunchy %s, the friendly launchctl wrapper\n", LUNCHY_VERSION)
  fmt.Println("Usage: lunchy [start|stop|restart|list|status|install|show|edit|remove] [options]")
}

func printList() {
  for _, file := range getPlists() {
    fmt.Println(file)
  }
}

func printStatus(args []string) {
  out, err := exec.Command("launchctl", "list").Output()

  if err != nil {
    fatal("failed to get process list")
  }

  pattern := ""

  if len(args) == 3 {
    pattern = args[2]
  }

  installed := getPlists()
  lines := strings.Split(strings.TrimSpace(string(out)), "\n")

  for _, line := range lines {
    chunks := strings.Split(line, "\t")
    clean_line := strings.Replace(line, "\t", " ", -1)

    if len(pattern) > 0 {
      if strings.Index(chunks[2], pattern) != -1 {
        if sliceIncludes(installed, chunks[2]) {
          fmt.Println(clean_line)
        }
      }
    } else {
      if sliceIncludes(installed, chunks[2]) {
        fmt.Println(clean_line)
      }
    }
  }
}

func startDaemons(args []string) {
  if len(args) < 3 {
    fmt.Println("name required")
    os.Exit(1)
  }

  name := args[2]

  for _, plist := range getPlists() {
    if strings.Index(plist, name) != -1 {
      startDaemon(plist)
    }
  }
}

func startDaemon(name string) {
  path := fmt.Sprintf("%s/Library/LaunchAgents/%s.plist", os.Getenv("HOME"), name)
  _, err := exec.Command("launchctl", "load", path).Output()

  if err != nil {
    fmt.Println("failed to start", name)
    return
  }

  fmt.Println("started", name)
}

func stopDaemons(args []string) {
  if len(args) < 3 {
    fatal("name required")
  }

  name := args[2]

  for _, plist := range getPlists() {
    if strings.Index(plist, name) != -1 {
      stopDaemon(plist)
    }
  }
}

func stopDaemon(name string) {
  path := fmt.Sprintf("%s/Library/LaunchAgents/%s.plist", os.Getenv("HOME"), name)
  _, err := exec.Command("launchctl", "unload", path).Output()

  if err != nil {
    fmt.Println("failed to stop", name)
    return
  }

  fmt.Println("stopped", name)
}

func restartDaemons(args []string) {
  if len(args) < 3 {
    fatal("name required")
  }

  name := args[2]

  for _, plist := range getPlists() {
    if strings.Index(plist, name) != -1 {
      stopDaemon(plist)
      startDaemon(plist)
    }
  }
}

func showPlist(args []string) {
  if len(args) < 3 {
    fatal("name required")
  }

  name := args[2]

  for _, plist := range getPlists() {
    if strings.Index(plist, name) != -1 {
      printPlistContent(plist)
      return
    }
  }
}

func printPlistContent(name string) {
  path := fmt.Sprintf("%s/Library/LaunchAgents/%s.plist", os.Getenv("HOME"), name)
  contents, err := ioutil.ReadFile(path)

  if err != nil {
    fatal("unable to read plist")
  }

  fmt.Printf(string(contents))
}

func editPlist(args []string) {
  if len(args) < 3 {
    fatal("name required")
  }

  name := args[2]

  for _, plist := range getPlists() {
    if strings.Index(plist, name) != -1 {
      editPlistContent(plist)
      return
    }
  }
}

func editPlistContent(name string) {
  path := fmt.Sprintf("%s/Library/LaunchAgents/%s.plist", os.Getenv("HOME"), name)
  editor := os.Getenv("EDITOR")

  if len(editor) == 0 {
    fatal("EDITOR environment variable is not set")
  }

  cmd := exec.Command(editor, path)

  cmd.Stdin = os.Stdin
  cmd.Stdout = os.Stdout

  cmd.Start()
  cmd.Wait()
}

func installPlist(args []string) {
  if len(args) < 3 {
    fatal("path required")
  }

  path := args[2]

  if !fileExists(path) {
    fatal("source file does not exist")
  }

  info, _ := os.Stat(path)
  base_path := fmt.Sprintf("%s/%s", os.Getenv("HOME"), "Library/LaunchAgents")
  new_path := fmt.Sprintf("%s/%s", base_path, info.Name())

  if fileExists(new_path) && os.Remove(new_path) != nil {
    fatal("unable to delete existing plist")
  }

  if fileCopy(path, new_path) != nil {
    fatal("failed to copy file")
  }

  fmt.Println(path, "installed to", base_path)
}

func removePlist(args []string) {
  if len(args) < 3 {
    fatal("name required")
  }

  name := args[2]
  base_path := fmt.Sprintf("%s/%s", os.Getenv("HOME"), "Library/LaunchAgents")

  for _, plist := range getPlists() {
    if strings.Index(plist, name) != -1 {
      path := fmt.Sprintf("%s/%s.plist", base_path, plist)

      if os.Remove(path) == nil {
        fmt.Println("removed", path)
      } else {
        fmt.Println("failed to remove", path)
      }
    }
  }
}

func fatal(message string) {
  fmt.Println(message)
  os.Exit(1)
}

func main() {
  args := os.Args

  if (len(args) == 1) {
    printUsage()
    os.Exit(1)
  }

  switch args[1] {
  default:
    printUsage()
    os.Exit(1)
  case "help":
    printUsage()
    return
  case "list", "ls":
    printList()
    return
  case "status":
    printStatus(args)
    return
  case "start":
    startDaemons(args)
    return
  case "stop":
    stopDaemons(args)
    return
  case "restart":
    restartDaemons(args)
    return
  case "show":
    showPlist(args)
    return
  case "edit":
    editPlist(args)
    return
  case "install":
    installPlist(args)
    return
  case "remove":
    removePlist(args)
    return
  }
}<commit_msg>Version bump: 0.1.2<commit_after>package main

import(
  "fmt"
  "os"
  "io"
  "io/ioutil"
  "path/filepath"
  "os/exec"
  "strings"
)

const(
  LUNCHY_VERSION = "0.1.2"
)

func fileExists(path string) bool {
  _, err := os.Stat(path)
  return err == nil
}

func fileCopy(src string, dst string) error {
  s, err := os.Open(src)
  if err != nil {
    return err
  }

  defer s.Close()

  d, err := os.Create(dst)
  if err != nil {
    return err
  }

  if _, err := io.Copy(d, s); err != nil {
    d.Close()
    return err
  }

  return d.Close()
}

func findPlists(path string) []string {
  result := []string{}
  files, err := ioutil.ReadDir(path)

  if err != nil {
    return result
  }

  for _, file := range files {
    if !file.IsDir() {
      if (filepath.Ext(file.Name())) == ".plist" {
        name := strings.Replace(file.Name(), ".plist", "", -1)
        result = append(result, name)
      }
    }
  }

  return result
}

func getPlists() []string {
  path := fmt.Sprintf("%s/Library/LaunchAgents", os.Getenv("HOME"))
  files := findPlists(path)

  return files
}

func sliceIncludes(slice []string, match string) bool {
  for _, val := range slice {
    if val == match {
      return true
    }
  }

  return false
}

func printUsage() {
  fmt.Printf("Lunchy %s, the friendly launchctl wrapper\n", LUNCHY_VERSION)
  fmt.Println("Usage: lunchy [start|stop|restart|list|status|install|show|edit|remove] [options]")
}

func printList() {
  for _, file := range getPlists() {
    fmt.Println(file)
  }
}

func printStatus(args []string) {
  out, err := exec.Command("launchctl", "list").Output()

  if err != nil {
    fatal("failed to get process list")
  }

  pattern := ""

  if len(args) == 3 {
    pattern = args[2]
  }

  installed := getPlists()
  lines := strings.Split(strings.TrimSpace(string(out)), "\n")

  for _, line := range lines {
    chunks := strings.Split(line, "\t")
    clean_line := strings.Replace(line, "\t", " ", -1)

    if len(pattern) > 0 {
      if strings.Index(chunks[2], pattern) != -1 {
        if sliceIncludes(installed, chunks[2]) {
          fmt.Println(clean_line)
        }
      }
    } else {
      if sliceIncludes(installed, chunks[2]) {
        fmt.Println(clean_line)
      }
    }
  }
}

func startDaemons(args []string) {
  if len(args) < 3 {
    fmt.Println("name required")
    os.Exit(1)
  }

  name := args[2]

  for _, plist := range getPlists() {
    if strings.Index(plist, name) != -1 {
      startDaemon(plist)
    }
  }
}

func startDaemon(name string) {
  path := fmt.Sprintf("%s/Library/LaunchAgents/%s.plist", os.Getenv("HOME"), name)
  _, err := exec.Command("launchctl", "load", path).Output()

  if err != nil {
    fmt.Println("failed to start", name)
    return
  }

  fmt.Println("started", name)
}

func stopDaemons(args []string) {
  if len(args) < 3 {
    fatal("name required")
  }

  name := args[2]

  for _, plist := range getPlists() {
    if strings.Index(plist, name) != -1 {
      stopDaemon(plist)
    }
  }
}

func stopDaemon(name string) {
  path := fmt.Sprintf("%s/Library/LaunchAgents/%s.plist", os.Getenv("HOME"), name)
  _, err := exec.Command("launchctl", "unload", path).Output()

  if err != nil {
    fmt.Println("failed to stop", name)
    return
  }

  fmt.Println("stopped", name)
}

func restartDaemons(args []string) {
  if len(args) < 3 {
    fatal("name required")
  }

  name := args[2]

  for _, plist := range getPlists() {
    if strings.Index(plist, name) != -1 {
      stopDaemon(plist)
      startDaemon(plist)
    }
  }
}

func showPlist(args []string) {
  if len(args) < 3 {
    fatal("name required")
  }

  name := args[2]

  for _, plist := range getPlists() {
    if strings.Index(plist, name) != -1 {
      printPlistContent(plist)
      return
    }
  }
}

func printPlistContent(name string) {
  path := fmt.Sprintf("%s/Library/LaunchAgents/%s.plist", os.Getenv("HOME"), name)
  contents, err := ioutil.ReadFile(path)

  if err != nil {
    fatal("unable to read plist")
  }

  fmt.Printf(string(contents))
}

func editPlist(args []string) {
  if len(args) < 3 {
    fatal("name required")
  }

  name := args[2]

  for _, plist := range getPlists() {
    if strings.Index(plist, name) != -1 {
      editPlistContent(plist)
      return
    }
  }
}

func editPlistContent(name string) {
  path := fmt.Sprintf("%s/Library/LaunchAgents/%s.plist", os.Getenv("HOME"), name)
  editor := os.Getenv("EDITOR")

  if len(editor) == 0 {
    fatal("EDITOR environment variable is not set")
  }

  cmd := exec.Command(editor, path)

  cmd.Stdin = os.Stdin
  cmd.Stdout = os.Stdout

  cmd.Start()
  cmd.Wait()
}

func installPlist(args []string) {
  if len(args) < 3 {
    fatal("path required")
  }

  path := args[2]

  if !fileExists(path) {
    fatal("source file does not exist")
  }

  info, _ := os.Stat(path)
  base_path := fmt.Sprintf("%s/%s", os.Getenv("HOME"), "Library/LaunchAgents")
  new_path := fmt.Sprintf("%s/%s", base_path, info.Name())

  if fileExists(new_path) && os.Remove(new_path) != nil {
    fatal("unable to delete existing plist")
  }

  if fileCopy(path, new_path) != nil {
    fatal("failed to copy file")
  }

  fmt.Println(path, "installed to", base_path)
}

func removePlist(args []string) {
  if len(args) < 3 {
    fatal("name required")
  }

  name := args[2]
  base_path := fmt.Sprintf("%s/%s", os.Getenv("HOME"), "Library/LaunchAgents")

  for _, plist := range getPlists() {
    if strings.Index(plist, name) != -1 {
      path := fmt.Sprintf("%s/%s.plist", base_path, plist)

      if os.Remove(path) == nil {
        fmt.Println("removed", path)
      } else {
        fmt.Println("failed to remove", path)
      }
    }
  }
}

func fatal(message string) {
  fmt.Println(message)
  os.Exit(1)
}

func main() {
  args := os.Args

  if (len(args) == 1) {
    printUsage()
    os.Exit(1)
  }

  switch args[1] {
  default:
    printUsage()
    os.Exit(1)
  case "help":
    printUsage()
    return
  case "list", "ls":
    printList()
    return
  case "status":
    printStatus(args)
    return
  case "start":
    startDaemons(args)
    return
  case "stop":
    stopDaemons(args)
    return
  case "restart":
    restartDaemons(args)
    return
  case "show":
    showPlist(args)
    return
  case "edit":
    editPlist(args)
    return
  case "install":
    installPlist(args)
    return
  case "remove":
    removePlist(args)
    return
  }
}<|endoftext|>


<commit_before>package throttler

import (
	"bufio"
	"errors"
	"fmt"
	"os"
	"os/exec"
	"runtime"
)

const (
	linux           = "linux"
	darwin          = "darwin"
	freebsd         = "freebsd"
	windows         = "windows"
	checkOSXVersion = "sw_vers -productVersion"
	ipfw            = "ipfw"
	pfctl           = "pfctl"
)

// Config specifies options for configuring packet filter rules.
type Config struct {
	Device           string
	Stop             bool
	Latency          int
	TargetBandwidth  int
	DefaultBandwidth int
	PacketLoss       float64
	TargetIps        []string
	TargetIps6       []string
	TargetPorts      []string
	TargetProtos     []string
	DryRun           bool
}

type throttler interface {
	setup(*Config) error
	teardown(*Config) error
	exists() bool
	check() string
}

type commander interface {
	execute(string) error
	executeGetLines(string) ([]string, error)
	commandExists(string) bool
}

type dryRunCommander struct{}

type shellCommander struct{}

var dry bool

func setup(t throttler, cfg *Config) {
	if t.exists() {
		fmt.Println("It looks like the packet rules are already setup")
		os.Exit(1)
	}

	if err := t.setup(cfg); err != nil {
		fmt.Println("I couldn't setup the packet rules:", err.Error())
		os.Exit(1)
	}

	fmt.Println("Packet rules setup...")
	fmt.Printf("Run `%s` to double check\n", t.check())
	fmt.Printf("Run `%s --stop` to reset\n", os.Args[0])
}

func teardown(t throttler, cfg *Config) {
	if !t.exists() {
		fmt.Println("It looks like the packet rules aren't setup")
		os.Exit(1)
	}

	if err := t.teardown(cfg); err != nil {
		fmt.Println("Failed to stop packet controls")
		os.Exit(1)
	}

	fmt.Println("Packet rules stopped...")
	fmt.Printf("Run `%s` to double check\n", t.check())
	fmt.Printf("Run `%s` to start\n", os.Args[0])
}

// Run executes the packet filter operation, either setting it up or tearing
// it down.
func Run(cfg *Config) {
	dry = cfg.DryRun
	var t throttler
	var c commander

	if cfg.DryRun {
		c = &dryRunCommander{}
	} else {
		c = &shellCommander{}
	}

	switch runtime.GOOS {
	case freebsd:
		if cfg.Device == "" {
			fmt.Println("Device not specified, unable to default to eth0 on FreeBSD.")
			os.Exit(1)
		}

		t = &ipfwThrottler{c}
	case darwin:
		// Avoid OS version pinning and choose based on what's available
		if c.commandExists(pfctl) {
			t = &pfctlThrottler{c}
		} else if c.commandExists(ipfw) {
			t = &ipfwThrottler{c}
		} else {
			fmt.Println("Could not determine an appropriate firewall tool for OSX (tried pfctl, ipfw), exiting")
			os.Exit(1)
		}

		if cfg.Device == "" {
			cfg.Device = "eth0"
		}

	case linux:
		if cfg.Device == "" {
			cfg.Device = "eth0"
		}

		t = &tcThrottler{c}
	default:
		fmt.Println("I don't support your OS: %s\n", runtime.GOOS)
		os.Exit(1)
	}

	if !cfg.Stop {
		setup(t, cfg)
	} else {
		teardown(t, cfg)
	}
}

func (c *dryRunCommander) execute(cmd string) error {
	fmt.Println(cmd)
	return nil
}

func (c *dryRunCommander) executeGetLines(cmd string) ([]string, error) {
	fmt.Println(cmd)
	return []string{}, nil
}

func (c *dryRunCommander) commandExists(cmd string) bool {
	return true
}

func (c *shellCommander) execute(cmd string) error {
	fmt.Println(cmd)
	return exec.Command("/bin/sh", "-c", cmd).Run()
}

func (c *shellCommander) executeGetLines(cmd string) ([]string, error) {
	lines := []string{}
	child := exec.Command("/bin/sh", "-c", cmd)

	out, err := child.StdoutPipe()
	if err != nil {
		return []string{}, err
	}

	err = child.Start()
	if err != nil {
		return []string{}, err
	}

	scanner := bufio.NewScanner(out)

	for scanner.Scan() {
		lines = append(lines, scanner.Text())
	}
	if err := scanner.Err(); err != nil {
		return []string{}, errors.New(fmt.Sprint("Error reading standard input:", err))
	}

	err = child.Wait()
	if err != nil {
		return []string{}, err
	}

	return lines, nil
}

func (c *shellCommander) commandExists(cmd string) bool {
	_, err := exec.LookPath(cmd)
	return err == nil
}
<commit_msg>Fix #37<commit_after>package throttler

import (
	"bufio"
	"errors"
	"fmt"
	"os"
	"os/exec"
	"runtime"
)

const (
	linux           = "linux"
	darwin          = "darwin"
	freebsd         = "freebsd"
	windows         = "windows"
	checkOSXVersion = "sw_vers -productVersion"
	ipfw            = "ipfw"
	pfctl           = "pfctl"
)

// Config specifies options for configuring packet filter rules.
type Config struct {
	Device           string
	Stop             bool
	Latency          int
	TargetBandwidth  int
	DefaultBandwidth int
	PacketLoss       float64
	TargetIps        []string
	TargetIps6       []string
	TargetPorts      []string
	TargetProtos     []string
	DryRun           bool
}

type throttler interface {
	setup(*Config) error
	teardown(*Config) error
	exists() bool
	check() string
}

type commander interface {
	execute(string) error
	executeGetLines(string) ([]string, error)
	commandExists(string) bool
}

type dryRunCommander struct{}

type shellCommander struct{}

var dry bool

func setup(t throttler, cfg *Config) {
	if t.exists() {
		fmt.Println("It looks like the packet rules are already setup")
		os.Exit(1)
	}

	if err := t.setup(cfg); err != nil {
		fmt.Println("I couldn't setup the packet rules:", err.Error())
		os.Exit(1)
	}

	fmt.Println("Packet rules setup...")
	fmt.Printf("Run `%s` to double check\n", t.check())
	fmt.Printf("Run `%s --device %s --stop` to reset\n", os.Args[0], cfg.Device)
}

func teardown(t throttler, cfg *Config) {
	if !t.exists() {
		fmt.Println("It looks like the packet rules aren't setup")
		os.Exit(1)
	}

	if err := t.teardown(cfg); err != nil {
		fmt.Println("Failed to stop packet controls")
		os.Exit(1)
	}

	fmt.Println("Packet rules stopped...")
	fmt.Printf("Run `%s` to double check\n", t.check())
	fmt.Printf("Run `%s` to start\n", os.Args[0])
}

// Run executes the packet filter operation, either setting it up or tearing
// it down.
func Run(cfg *Config) {
	dry = cfg.DryRun
	var t throttler
	var c commander

	if cfg.DryRun {
		c = &dryRunCommander{}
	} else {
		c = &shellCommander{}
	}

	switch runtime.GOOS {
	case freebsd:
		if cfg.Device == "" {
			fmt.Println("Device not specified, unable to default to eth0 on FreeBSD.")
			os.Exit(1)
		}

		t = &ipfwThrottler{c}
	case darwin:
		// Avoid OS version pinning and choose based on what's available
		if c.commandExists(pfctl) {
			t = &pfctlThrottler{c}
		} else if c.commandExists(ipfw) {
			t = &ipfwThrottler{c}
		} else {
			fmt.Println("Could not determine an appropriate firewall tool for OSX (tried pfctl, ipfw), exiting")
			os.Exit(1)
		}

		if cfg.Device == "" {
			cfg.Device = "eth0"
		}

	case linux:
		if cfg.Device == "" {
			cfg.Device = "eth0"
		}

		t = &tcThrottler{c}
	default:
		fmt.Println("I don't support your OS: %s\n", runtime.GOOS)
		os.Exit(1)
	}

	if !cfg.Stop {
		setup(t, cfg)
	} else {
		teardown(t, cfg)
	}
}

func (c *dryRunCommander) execute(cmd string) error {
	fmt.Println(cmd)
	return nil
}

func (c *dryRunCommander) executeGetLines(cmd string) ([]string, error) {
	fmt.Println(cmd)
	return []string{}, nil
}

func (c *dryRunCommander) commandExists(cmd string) bool {
	return true
}

func (c *shellCommander) execute(cmd string) error {
	fmt.Println(cmd)
	return exec.Command("/bin/sh", "-c", cmd).Run()
}

func (c *shellCommander) executeGetLines(cmd string) ([]string, error) {
	lines := []string{}
	child := exec.Command("/bin/sh", "-c", cmd)

	out, err := child.StdoutPipe()
	if err != nil {
		return []string{}, err
	}

	err = child.Start()
	if err != nil {
		return []string{}, err
	}

	scanner := bufio.NewScanner(out)

	for scanner.Scan() {
		lines = append(lines, scanner.Text())
	}
	if err := scanner.Err(); err != nil {
		return []string{}, errors.New(fmt.Sprint("Error reading standard input:", err))
	}

	err = child.Wait()
	if err != nil {
		return []string{}, err
	}

	return lines, nil
}

func (c *shellCommander) commandExists(cmd string) bool {
	_, err := exec.LookPath(cmd)
	return err == nil
}
<|endoftext|>


<commit_before>package titleservice

import "context"

type Series struct {
	SeriesCode   string
	Title        string
	SeasonNumber int
	Description  string
	GenreText    string
}

func (c *client) RegisterSeries(ctx context.Context, series Series) {}
<commit_msg>Series struct comment<commit_after>package titleservice

import "context"

// Series is a title linked to a series/season
type Series struct {
	SeriesCode   string
	Title        string
	SeasonNumber int
	Description  string
	GenreText    string
}

func (c *client) RegisterSeries(ctx context.Context, series Series) {}
<|endoftext|>


<commit_before>package filer

import (
	"bytes"
	"fmt"
	"github.com/chrislusf/seaweedfs/weed/wdclient"
	"math"
	"sort"
	"sync"

	"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
	"github.com/chrislusf/seaweedfs/weed/util"
)

func TotalSize(chunks []*filer_pb.FileChunk) (size uint64) {
	for _, c := range chunks {
		t := uint64(c.Offset + int64(c.Size))
		if size < t {
			size = t
		}
	}
	return
}

func FileSize(entry *filer_pb.Entry) (size uint64) {
	fileSize := entry.Attributes.FileSize
	if entry.RemoteEntry != nil {
		if entry.RemoteEntry.RemoteMtime > entry.Attributes.Mtime {
			fileSize = maxUint64(fileSize, uint64(entry.RemoteEntry.RemoteSize))
		}
	}
	return maxUint64(TotalSize(entry.Chunks), fileSize)
}

func ETag(entry *filer_pb.Entry) (etag string) {
	if entry.Attributes == nil || entry.Attributes.Md5 == nil {
		return ETagChunks(entry.Chunks)
	}
	return fmt.Sprintf("%x", entry.Attributes.Md5)
}

func ETagEntry(entry *Entry) (etag string) {
	if entry.Attr.Md5 == nil {
		return ETagChunks(entry.Chunks)
	}
	return fmt.Sprintf("%x", entry.Attr.Md5)
}

func ETagChunks(chunks []*filer_pb.FileChunk) (etag string) {
	if len(chunks) == 1 {
		return fmt.Sprintf("%x", util.Base64Md5ToBytes(chunks[0].ETag))
	}
	md5_digests := [][]byte{}
	for _, c := range chunks {
		md5_digests = append(md5_digests, util.Base64Md5ToBytes(c.ETag))
	}
	return fmt.Sprintf("%x-%d", util.Md5(bytes.Join(md5_digests, nil)), len(chunks))
}

func CompactFileChunks(lookupFileIdFn wdclient.LookupFileIdFunctionType, chunks []*filer_pb.FileChunk) (compacted, garbage []*filer_pb.FileChunk) {

	visibles, _ := NonOverlappingVisibleIntervals(lookupFileIdFn, chunks, 0, math.MaxInt64)

	fileIds := make(map[string]bool)
	for _, interval := range visibles {
		fileIds[interval.fileId] = true
	}
	for _, chunk := range chunks {
		if _, found := fileIds[chunk.GetFileIdString()]; found {
			compacted = append(compacted, chunk)
		} else {
			garbage = append(garbage, chunk)
		}
	}

	return
}

func MinusChunks(lookupFileIdFn wdclient.LookupFileIdFunctionType, as, bs []*filer_pb.FileChunk) (delta []*filer_pb.FileChunk, err error) {

	aData, aMeta, aErr := ResolveChunkManifest(lookupFileIdFn, as, 0, math.MaxInt64)
	if aErr != nil {
		return nil, aErr
	}
	bData, bMeta, bErr := ResolveChunkManifest(lookupFileIdFn, bs, 0, math.MaxInt64)
	if bErr != nil {
		return nil, bErr
	}

	delta = append(delta, DoMinusChunks(aData, bData)...)
	delta = append(delta, DoMinusChunks(aMeta, bMeta)...)
	return
}

func DoMinusChunks(as, bs []*filer_pb.FileChunk) (delta []*filer_pb.FileChunk) {

	fileIds := make(map[string]bool)
	for _, interval := range bs {
		fileIds[interval.GetFileIdString()] = true
	}
	for _, chunk := range as {
		if _, found := fileIds[chunk.GetFileIdString()]; !found {
			delta = append(delta, chunk)
		}
	}

	return
}

func DoMinusChunksBySourceFileId(as, bs []*filer_pb.FileChunk) (delta []*filer_pb.FileChunk) {

	fileIds := make(map[string]bool)
	for _, interval := range bs {
		fileIds[interval.GetFileIdString()] = true
	}
	for _, chunk := range as {
		if _, found := fileIds[chunk.GetSourceFileId()]; !found {
			delta = append(delta, chunk)
		}
	}

	return
}

type ChunkView struct {
	FileId      string
	Offset      int64
	Size        uint64
	LogicOffset int64 // actual offset in the file, for the data specified via [offset, offset+size) in current chunk
	ChunkSize   uint64
	CipherKey   []byte
	IsGzipped   bool
}

func (cv *ChunkView) IsFullChunk() bool {
	return cv.Size == cv.ChunkSize
}

func ViewFromChunks(lookupFileIdFn wdclient.LookupFileIdFunctionType, chunks []*filer_pb.FileChunk, offset int64, size int64) (views []*ChunkView) {

	visibles, _ := NonOverlappingVisibleIntervals(lookupFileIdFn, chunks, offset, offset+size)

	return ViewFromVisibleIntervals(visibles, offset, size)

}

func ViewFromVisibleIntervals(visibles []VisibleInterval, offset int64, size int64) (views []*ChunkView) {

	stop := offset + size
	if size == math.MaxInt64 {
		stop = math.MaxInt64
	}
	if stop < offset {
		stop = math.MaxInt64
	}

	for _, chunk := range visibles {

		chunkStart, chunkStop := max(offset, chunk.start), min(stop, chunk.stop)

		if chunkStart < chunkStop {
			views = append(views, &ChunkView{
				FileId:      chunk.fileId,
				Offset:      chunkStart - chunk.start + chunk.chunkOffset,
				Size:        uint64(chunkStop - chunkStart),
				LogicOffset: chunkStart,
				ChunkSize:   chunk.chunkSize,
				CipherKey:   chunk.cipherKey,
				IsGzipped:   chunk.isGzipped,
			})
		}
	}

	return views

}

func logPrintf(name string, visibles []VisibleInterval) {

	/*
		glog.V(0).Infof("%s len %d", name, len(visibles))
		for _, v := range visibles {
			glog.V(0).Infof("%s:  [%d,%d) %s %d", name, v.start, v.stop, v.fileId, v.chunkOffset)
		}
	*/
}

var bufPool = sync.Pool{
	New: func() interface{} {
		return new(VisibleInterval)
	},
}

func MergeIntoVisibles(visibles []VisibleInterval, chunk *filer_pb.FileChunk) (newVisibles []VisibleInterval) {

	newV := newVisibleInterval(chunk.Offset, chunk.Offset+int64(chunk.Size), chunk.GetFileIdString(), chunk.Mtime, 0, chunk.Size, chunk.CipherKey, chunk.IsCompressed)

	length := len(visibles)
	if length == 0 {
		return append(visibles, newV)
	}
	last := visibles[length-1]
	if last.stop <= chunk.Offset {
		return append(visibles, newV)
	}

	logPrintf("  before", visibles)
	// glog.V(0).Infof("newVisibles %d adding chunk [%d,%d) %s size:%d", len(newVisibles), chunk.Offset, chunk.Offset+int64(chunk.Size), chunk.GetFileIdString(), chunk.Size)
	chunkStop := chunk.Offset + int64(chunk.Size)
	for _, v := range visibles {
		if v.start < chunk.Offset && chunk.Offset < v.stop {
			t := newVisibleInterval(v.start, chunk.Offset, v.fileId, v.modifiedTime, v.chunkOffset, v.chunkSize, v.cipherKey, v.isGzipped)
			newVisibles = append(newVisibles, t)
			// glog.V(0).Infof("visible %d [%d,%d) =1> [%d,%d)", i, v.start, v.stop, t.start, t.stop)
		}
		if v.start < chunkStop && chunkStop < v.stop {
			t := newVisibleInterval(chunkStop, v.stop, v.fileId, v.modifiedTime, v.chunkOffset+(chunkStop-v.start), v.chunkSize, v.cipherKey, v.isGzipped)
			newVisibles = append(newVisibles, t)
			// glog.V(0).Infof("visible %d [%d,%d) =2> [%d,%d)", i, v.start, v.stop, t.start, t.stop)
		}
		if chunkStop <= v.start || v.stop <= chunk.Offset {
			newVisibles = append(newVisibles, v)
			// glog.V(0).Infof("visible %d [%d,%d) =3> [%d,%d)", i, v.start, v.stop, v.start, v.stop)
		}
	}
	newVisibles = append(newVisibles, newV)

	logPrintf("  append", newVisibles)

	for i := len(newVisibles) - 1; i >= 0; i-- {
		if i > 0 && newV.start < newVisibles[i-1].start {
			newVisibles[i] = newVisibles[i-1]
		} else {
			newVisibles[i] = newV
			break
		}
	}
	logPrintf("  sorted", newVisibles)

	return newVisibles
}

// NonOverlappingVisibleIntervals translates the file chunk into VisibleInterval in memory
// If the file chunk content is a chunk manifest
func NonOverlappingVisibleIntervals(lookupFileIdFn wdclient.LookupFileIdFunctionType, chunks []*filer_pb.FileChunk, startOffset int64, stopOffset int64) (visibles []VisibleInterval, err error) {

	chunks, _, err = ResolveChunkManifest(lookupFileIdFn, chunks, startOffset, stopOffset)

	visibles2 := readResolvedChunks(chunks)

	if true {
		return visibles2, err
	}

	sort.Slice(chunks, func(i, j int) bool {
		if chunks[i].Mtime == chunks[j].Mtime {
			filer_pb.EnsureFid(chunks[i])
			filer_pb.EnsureFid(chunks[j])
			if chunks[i].Fid == nil || chunks[j].Fid == nil {
				return true
			}
			return chunks[i].Fid.FileKey < chunks[j].Fid.FileKey
		}
		return chunks[i].Mtime < chunks[j].Mtime // keep this to make tests run
	})

	for _, chunk := range chunks {

		// glog.V(0).Infof("merge [%d,%d)", chunk.Offset, chunk.Offset+int64(chunk.Size))
		visibles = MergeIntoVisibles(visibles, chunk)

		logPrintf("add", visibles)

	}

	if len(visibles) != len(visibles2) {
		fmt.Printf("different visibles size %d : %d\n", len(visibles), len(visibles2))
	} else {
		for i := 0; i < len(visibles); i++ {
			checkDifference(visibles[i], visibles2[i])
		}
	}

	return
}

func checkDifference(x, y VisibleInterval) {
	if x.start != y.start ||
		x.stop != y.stop ||
		x.fileId != y.fileId ||
		x.modifiedTime != y.modifiedTime {
		fmt.Printf("different visible %+v : %+v\n", x, y)
	}
}

// find non-overlapping visible intervals
// visible interval map to one file chunk

type VisibleInterval struct {
	start        int64
	stop         int64
	modifiedTime int64
	fileId       string
	chunkOffset  int64
	chunkSize    uint64
	cipherKey    []byte
	isGzipped    bool
}

func newVisibleInterval(start, stop int64, fileId string, modifiedTime int64, chunkOffset int64, chunkSize uint64, cipherKey []byte, isGzipped bool) VisibleInterval {
	return VisibleInterval{
		start:        start,
		stop:         stop,
		fileId:       fileId,
		modifiedTime: modifiedTime,
		chunkOffset:  chunkOffset, // the starting position in the chunk
		chunkSize:    chunkSize,
		cipherKey:    cipherKey,
		isGzipped:    isGzipped,
	}
}

func min(x, y int64) int64 {
	if x <= y {
		return x
	}
	return y
}
func max(x, y int64) int64 {
	if x <= y {
		return y
	}
	return x
}
<commit_msg>prevent nil<commit_after>package filer

import (
	"bytes"
	"fmt"
	"github.com/chrislusf/seaweedfs/weed/wdclient"
	"math"
	"sort"
	"sync"

	"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
	"github.com/chrislusf/seaweedfs/weed/util"
)

func TotalSize(chunks []*filer_pb.FileChunk) (size uint64) {
	for _, c := range chunks {
		t := uint64(c.Offset + int64(c.Size))
		if size < t {
			size = t
		}
	}
	return
}

func FileSize(entry *filer_pb.Entry) (size uint64) {
	if entry == nil || entry.Attributes == nil {
		return 0
	}
	fileSize := entry.Attributes.FileSize
	if entry.RemoteEntry != nil {
		if entry.RemoteEntry.RemoteMtime > entry.Attributes.Mtime {
			fileSize = maxUint64(fileSize, uint64(entry.RemoteEntry.RemoteSize))
		}
	}
	return maxUint64(TotalSize(entry.Chunks), fileSize)
}

func ETag(entry *filer_pb.Entry) (etag string) {
	if entry.Attributes == nil || entry.Attributes.Md5 == nil {
		return ETagChunks(entry.Chunks)
	}
	return fmt.Sprintf("%x", entry.Attributes.Md5)
}

func ETagEntry(entry *Entry) (etag string) {
	if entry.Attr.Md5 == nil {
		return ETagChunks(entry.Chunks)
	}
	return fmt.Sprintf("%x", entry.Attr.Md5)
}

func ETagChunks(chunks []*filer_pb.FileChunk) (etag string) {
	if len(chunks) == 1 {
		return fmt.Sprintf("%x", util.Base64Md5ToBytes(chunks[0].ETag))
	}
	md5_digests := [][]byte{}
	for _, c := range chunks {
		md5_digests = append(md5_digests, util.Base64Md5ToBytes(c.ETag))
	}
	return fmt.Sprintf("%x-%d", util.Md5(bytes.Join(md5_digests, nil)), len(chunks))
}

func CompactFileChunks(lookupFileIdFn wdclient.LookupFileIdFunctionType, chunks []*filer_pb.FileChunk) (compacted, garbage []*filer_pb.FileChunk) {

	visibles, _ := NonOverlappingVisibleIntervals(lookupFileIdFn, chunks, 0, math.MaxInt64)

	fileIds := make(map[string]bool)
	for _, interval := range visibles {
		fileIds[interval.fileId] = true
	}
	for _, chunk := range chunks {
		if _, found := fileIds[chunk.GetFileIdString()]; found {
			compacted = append(compacted, chunk)
		} else {
			garbage = append(garbage, chunk)
		}
	}

	return
}

func MinusChunks(lookupFileIdFn wdclient.LookupFileIdFunctionType, as, bs []*filer_pb.FileChunk) (delta []*filer_pb.FileChunk, err error) {

	aData, aMeta, aErr := ResolveChunkManifest(lookupFileIdFn, as, 0, math.MaxInt64)
	if aErr != nil {
		return nil, aErr
	}
	bData, bMeta, bErr := ResolveChunkManifest(lookupFileIdFn, bs, 0, math.MaxInt64)
	if bErr != nil {
		return nil, bErr
	}

	delta = append(delta, DoMinusChunks(aData, bData)...)
	delta = append(delta, DoMinusChunks(aMeta, bMeta)...)
	return
}

func DoMinusChunks(as, bs []*filer_pb.FileChunk) (delta []*filer_pb.FileChunk) {

	fileIds := make(map[string]bool)
	for _, interval := range bs {
		fileIds[interval.GetFileIdString()] = true
	}
	for _, chunk := range as {
		if _, found := fileIds[chunk.GetFileIdString()]; !found {
			delta = append(delta, chunk)
		}
	}

	return
}

func DoMinusChunksBySourceFileId(as, bs []*filer_pb.FileChunk) (delta []*filer_pb.FileChunk) {

	fileIds := make(map[string]bool)
	for _, interval := range bs {
		fileIds[interval.GetFileIdString()] = true
	}
	for _, chunk := range as {
		if _, found := fileIds[chunk.GetSourceFileId()]; !found {
			delta = append(delta, chunk)
		}
	}

	return
}

type ChunkView struct {
	FileId      string
	Offset      int64
	Size        uint64
	LogicOffset int64 // actual offset in the file, for the data specified via [offset, offset+size) in current chunk
	ChunkSize   uint64
	CipherKey   []byte
	IsGzipped   bool
}

func (cv *ChunkView) IsFullChunk() bool {
	return cv.Size == cv.ChunkSize
}

func ViewFromChunks(lookupFileIdFn wdclient.LookupFileIdFunctionType, chunks []*filer_pb.FileChunk, offset int64, size int64) (views []*ChunkView) {

	visibles, _ := NonOverlappingVisibleIntervals(lookupFileIdFn, chunks, offset, offset+size)

	return ViewFromVisibleIntervals(visibles, offset, size)

}

func ViewFromVisibleIntervals(visibles []VisibleInterval, offset int64, size int64) (views []*ChunkView) {

	stop := offset + size
	if size == math.MaxInt64 {
		stop = math.MaxInt64
	}
	if stop < offset {
		stop = math.MaxInt64
	}

	for _, chunk := range visibles {

		chunkStart, chunkStop := max(offset, chunk.start), min(stop, chunk.stop)

		if chunkStart < chunkStop {
			views = append(views, &ChunkView{
				FileId:      chunk.fileId,
				Offset:      chunkStart - chunk.start + chunk.chunkOffset,
				Size:        uint64(chunkStop - chunkStart),
				LogicOffset: chunkStart,
				ChunkSize:   chunk.chunkSize,
				CipherKey:   chunk.cipherKey,
				IsGzipped:   chunk.isGzipped,
			})
		}
	}

	return views

}

func logPrintf(name string, visibles []VisibleInterval) {

	/*
		glog.V(0).Infof("%s len %d", name, len(visibles))
		for _, v := range visibles {
			glog.V(0).Infof("%s:  [%d,%d) %s %d", name, v.start, v.stop, v.fileId, v.chunkOffset)
		}
	*/
}

var bufPool = sync.Pool{
	New: func() interface{} {
		return new(VisibleInterval)
	},
}

func MergeIntoVisibles(visibles []VisibleInterval, chunk *filer_pb.FileChunk) (newVisibles []VisibleInterval) {

	newV := newVisibleInterval(chunk.Offset, chunk.Offset+int64(chunk.Size), chunk.GetFileIdString(), chunk.Mtime, 0, chunk.Size, chunk.CipherKey, chunk.IsCompressed)

	length := len(visibles)
	if length == 0 {
		return append(visibles, newV)
	}
	last := visibles[length-1]
	if last.stop <= chunk.Offset {
		return append(visibles, newV)
	}

	logPrintf("  before", visibles)
	// glog.V(0).Infof("newVisibles %d adding chunk [%d,%d) %s size:%d", len(newVisibles), chunk.Offset, chunk.Offset+int64(chunk.Size), chunk.GetFileIdString(), chunk.Size)
	chunkStop := chunk.Offset + int64(chunk.Size)
	for _, v := range visibles {
		if v.start < chunk.Offset && chunk.Offset < v.stop {
			t := newVisibleInterval(v.start, chunk.Offset, v.fileId, v.modifiedTime, v.chunkOffset, v.chunkSize, v.cipherKey, v.isGzipped)
			newVisibles = append(newVisibles, t)
			// glog.V(0).Infof("visible %d [%d,%d) =1> [%d,%d)", i, v.start, v.stop, t.start, t.stop)
		}
		if v.start < chunkStop && chunkStop < v.stop {
			t := newVisibleInterval(chunkStop, v.stop, v.fileId, v.modifiedTime, v.chunkOffset+(chunkStop-v.start), v.chunkSize, v.cipherKey, v.isGzipped)
			newVisibles = append(newVisibles, t)
			// glog.V(0).Infof("visible %d [%d,%d) =2> [%d,%d)", i, v.start, v.stop, t.start, t.stop)
		}
		if chunkStop <= v.start || v.stop <= chunk.Offset {
			newVisibles = append(newVisibles, v)
			// glog.V(0).Infof("visible %d [%d,%d) =3> [%d,%d)", i, v.start, v.stop, v.start, v.stop)
		}
	}
	newVisibles = append(newVisibles, newV)

	logPrintf("  append", newVisibles)

	for i := len(newVisibles) - 1; i >= 0; i-- {
		if i > 0 && newV.start < newVisibles[i-1].start {
			newVisibles[i] = newVisibles[i-1]
		} else {
			newVisibles[i] = newV
			break
		}
	}
	logPrintf("  sorted", newVisibles)

	return newVisibles
}

// NonOverlappingVisibleIntervals translates the file chunk into VisibleInterval in memory
// If the file chunk content is a chunk manifest
func NonOverlappingVisibleIntervals(lookupFileIdFn wdclient.LookupFileIdFunctionType, chunks []*filer_pb.FileChunk, startOffset int64, stopOffset int64) (visibles []VisibleInterval, err error) {

	chunks, _, err = ResolveChunkManifest(lookupFileIdFn, chunks, startOffset, stopOffset)

	visibles2 := readResolvedChunks(chunks)

	if true {
		return visibles2, err
	}

	sort.Slice(chunks, func(i, j int) bool {
		if chunks[i].Mtime == chunks[j].Mtime {
			filer_pb.EnsureFid(chunks[i])
			filer_pb.EnsureFid(chunks[j])
			if chunks[i].Fid == nil || chunks[j].Fid == nil {
				return true
			}
			return chunks[i].Fid.FileKey < chunks[j].Fid.FileKey
		}
		return chunks[i].Mtime < chunks[j].Mtime // keep this to make tests run
	})

	for _, chunk := range chunks {

		// glog.V(0).Infof("merge [%d,%d)", chunk.Offset, chunk.Offset+int64(chunk.Size))
		visibles = MergeIntoVisibles(visibles, chunk)

		logPrintf("add", visibles)

	}

	if len(visibles) != len(visibles2) {
		fmt.Printf("different visibles size %d : %d\n", len(visibles), len(visibles2))
	} else {
		for i := 0; i < len(visibles); i++ {
			checkDifference(visibles[i], visibles2[i])
		}
	}

	return
}

func checkDifference(x, y VisibleInterval) {
	if x.start != y.start ||
		x.stop != y.stop ||
		x.fileId != y.fileId ||
		x.modifiedTime != y.modifiedTime {
		fmt.Printf("different visible %+v : %+v\n", x, y)
	}
}

// find non-overlapping visible intervals
// visible interval map to one file chunk

type VisibleInterval struct {
	start        int64
	stop         int64
	modifiedTime int64
	fileId       string
	chunkOffset  int64
	chunkSize    uint64
	cipherKey    []byte
	isGzipped    bool
}

func newVisibleInterval(start, stop int64, fileId string, modifiedTime int64, chunkOffset int64, chunkSize uint64, cipherKey []byte, isGzipped bool) VisibleInterval {
	return VisibleInterval{
		start:        start,
		stop:         stop,
		fileId:       fileId,
		modifiedTime: modifiedTime,
		chunkOffset:  chunkOffset, // the starting position in the chunk
		chunkSize:    chunkSize,
		cipherKey:    cipherKey,
		isGzipped:    isGzipped,
	}
}

func min(x, y int64) int64 {
	if x <= y {
		return x
	}
	return y
}
func max(x, y int64) int64 {
	if x <= y {
		return y
	}
	return x
}
<|endoftext|>


<commit_before>// Binary init downloads the necessary files to perform an integration test between this WebDriver client and multiple versions of Selenium and browsers.
package main

import (
	"context"
	"crypto/md5"
	"crypto/sha256"
	"encoding/hex"
	"flag"
	"fmt"
	"hash"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"path"
	"strings"
	"sync"

	"cloud.google.com/go/storage"
	"github.com/golang/glog"
	"google.golang.org/api/option"
)

var downloadBrowsers = flag.Bool("download_browsers", true, "If true, download the Firefox and Chrome browsers.")

type file struct {
	url      string
	name     string
	hash     string
	hashType string // default is sha256
	rename   []string
	browser  bool
}

var files = []file{
	{
		url:  "http://selenium-release.storage.googleapis.com/3.4/selenium-server-standalone-3.4.0.jar",
		name: "selenium-server-standalone-3.4.jar",
		hash: "21cbbd775678821b6b72c208b8d59664a4c7381b3c50b008b331914d2834ec8d",
	},
	{
		url:    "https://chromedriver.storage.googleapis.com/2.31/chromedriver_linux64.zip",
		name:   "chromedriver_2.31_linux64.zip",
		hash:   "3e372ef676beb3a03aba72089ec0624bb9d3b52597635f907d4c23390fb485a0",
		rename: []string{"chromedriver", "chromedriver-linux64-2.31"},
	},
	{
		url:    "https://github.com/mozilla/geckodriver/releases/download/v0.18.0/geckodriver-v0.18.0-linux64.tar.gz",
		name:   "geckodriver-v0.18.0-linux64.tar.gz",
		hash:   "b78a0c5d2e249312d266d846e803e88a26477de20f33bfd635e164d27e59ae20",
		rename: []string{"geckodriver", "geckodriver-v0.18.0-linux64"},
	},
	{
		// This is a recent nightly. Update this path periodically.
		url:     "https://archive.mozilla.org/pub/firefox/nightly/2017/08/2017-08-21-10-03-50-mozilla-central/firefox-57.0a1.en-US.linux-x86_64.tar.bz2",
		name:    "firefox-57.0a1.en-US.linux-x86_64.tar.bz2",
		hash:    "77c57356935f66a5a59b1b2cffeaa53b70204195e6a7b15ee828fd3308561e46",
		browser: true,
		rename:  []string{"firefox", "firefox-nightly"},
	},
	{
		url:    "https://saucelabs.com/downloads/sc-4.4.9-linux.tar.gz",
		name:   "sauce-connect-4.4.9-linux.tar.gz",
		hash:   "b1bedccc2690b48d6708ac71f23189c85b0da62c56ee943a1b20d8f17fa8bbde",
		rename: []string{"sc-4.4.9-linux", "sauce-connect"},
	},
}

func addChrome(ctx context.Context) error {
	const (
		// Bucket URL: https://console.cloud.google.com/storage/browser/chromium-browser-continuous/?pli=1
		storageBktName = "chromium-browser-snapshots"
		prefixLinux64  = "Linux_x64"
		lastChangeFile = "Linux_x64/LAST_CHANGE"
		chromeFilename = "chrome-linux.zip"
	)
	gcsPath := fmt.Sprintf("gs://%s/", storageBktName)
	client, err := storage.NewClient(ctx, option.WithHTTPClient(http.DefaultClient))
	if err != nil {
		return fmt.Errorf("cannot create a storage client for downloading the chrome browser: %v", err)
	}
	bkt := client.Bucket(storageBktName)
	r, err := bkt.Object(lastChangeFile).NewReader(ctx)
	if err != nil {
		return fmt.Errorf("cannot create a reader for %s%s file: %v", gcsPath, lastChangeFile, err)
	}
	defer r.Close()
	// Read the last change file content for the latest build directory name
	data, err := ioutil.ReadAll(r)
	if err != nil {
		return fmt.Errorf("cannot read from %s%s file: %v", gcsPath, lastChangeFile, err)
	}
	latestChromeBuild := string(data)
	latestChromePackage := path.Join(prefixLinux64, latestChromeBuild, chromeFilename)
	cpAttrs, err := bkt.Object(latestChromePackage).Attrs(ctx)
	if err != nil {
		return fmt.Errorf("cannot get the chrome package %s%s attrs: %v", gcsPath, latestChromePackage, err)
	}
	files = append(files, file{
		name:     chromeFilename,
		browser:  true,
		hash:     hex.EncodeToString(cpAttrs.MD5),
		hashType: "md5",
		url:      cpAttrs.MediaLink,
	})
	return nil
}

func main() {
	flag.Parse()
	ctx := context.Background()
	wg := sync.WaitGroup{}
	if *downloadBrowsers {
		wg.Add(1)
		go func() {
			if err := addChrome(ctx); err != nil {
				glog.Errorf("unable to Download Google Chrome browser: %v", err)
			}
			wg.Done()
		}()
	}
	for _, file := range files {
		wg.Add(1)
		file := file
		go func() {
			if err := handleFile(file); err != nil {
				glog.Exitf("Error handling %s: %s", file.name, err)
			}
			wg.Done()
		}()
	}
	wg.Wait()
}

func handleFile(file file) error {
	if file.browser && !*downloadBrowsers {
		glog.Infof("Skipping %q because --download_browser is not set.", file.name)
		return nil
	}
	if !fileSameHash(file) {
		glog.Infof("Downloading %q from %q", file.name, file.url)
		if err := downloadFile(file); err != nil {
			return err
		}
	} else {
		glog.Infof("Skipping file %q which has already been downloaded.", file.name)
	}

	switch path.Ext(file.name) {
	case ".zip":
		glog.Infof("Unzipping %q", file.name)
		if err := exec.Command("unzip", "-o", file.name).Run(); err != nil {
			return fmt.Errorf("Error unzipping %q: %v", file.name, err)
		}
	case ".gz":
		glog.Infof("Unzipping %q", file.name)
		if err := exec.Command("tar", "-xzf", file.name).Run(); err != nil {
			return fmt.Errorf("Error unzipping %q: %v", file.name, err)
		}
	case ".bz2":
		glog.Infof("Unzipping %q", file.name)
		if err := exec.Command("tar", "-xjf", file.name).Run(); err != nil {
			return fmt.Errorf("Error unzipping %q: %v", file.name, err)
		}
	}
	if rename := file.rename; len(rename) == 2 {
		glog.Infof("Renaming %q to %q", rename[0], rename[1])
		os.RemoveAll(rename[1]) // Ignore error.
		if err := os.Rename(rename[0], rename[1]); err != nil {
			glog.Warningf("Error renaming %q to %q: %v", rename[0], rename[1], err)
		}
	}
	return nil
}

func downloadFile(file file) (err error) {
	f, err := os.Create(file.name)
	if err != nil {
		return fmt.Errorf("error creating %q: %v", file.name, err)
	}
	defer func() {
		if closeErr := f.Close(); closeErr != nil && err == nil {
			err = fmt.Errorf("error closing %q: %v", file.name, err)
		}
	}()

	resp, err := http.Get(file.url)
	if err != nil {
		return fmt.Errorf("%s: error downloading %q: %v", file.name, file.url, err)
	}
	defer resp.Body.Close()
	var h hash.Hash
	switch strings.ToLower(file.hashType) {
	case "md5":
		h = md5.New()
	default:
		h = sha256.New()
	}
	if _, err := io.Copy(io.MultiWriter(f, h), resp.Body); err != nil {
		return fmt.Errorf("%s: error downloading %q: %v", file.name, file.url, err)
	}
	if h := hex.EncodeToString(h.Sum(nil)); h != file.hash {
		return fmt.Errorf("%s: got %s hash %q, want %q", file.name, file.hashType, h, file.hash)
	}
	return nil
}

func fileSameHash(file file) bool {
	if _, err := os.Stat(file.name); err != nil {
		return false
	}
	var h hash.Hash
	switch strings.ToLower(file.hashType) {
	case "md5":
		h = md5.New()
	default:
		h = sha256.New()
	}
	f, err := os.Open(file.name)
	if err != nil {
		return false
	}
	defer f.Close()

	if _, err := io.Copy(h, f); err != nil {
		return false
	}

	sum := hex.EncodeToString(h.Sum(nil))
	if sum != file.hash {
		glog.Warningf("File %q: got hash %q, expect hash %q", file.name, sum, file.hash)
		return false
	}
	return true
}
<commit_msg>Fix race condition in vendor/init.go (#105)<commit_after>// Binary init downloads the necessary files to perform an integration test between this WebDriver client and multiple versions of Selenium and browsers.
package main

import (
	"context"
	"crypto/md5"
	"crypto/sha256"
	"encoding/hex"
	"flag"
	"fmt"
	"hash"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"path"
	"strings"
	"sync"

	"cloud.google.com/go/storage"
	"github.com/golang/glog"
	"google.golang.org/api/option"
)

var downloadBrowsers = flag.Bool("download_browsers", true, "If true, download the Firefox and Chrome browsers.")

type file struct {
	url      string
	name     string
	hash     string
	hashType string // default is sha256
	rename   []string
	browser  bool
}

var files = []file{
	{
		url:  "http://selenium-release.storage.googleapis.com/3.4/selenium-server-standalone-3.4.0.jar",
		name: "selenium-server-standalone-3.4.jar",
		hash: "21cbbd775678821b6b72c208b8d59664a4c7381b3c50b008b331914d2834ec8d",
	},
	{
		url:    "https://chromedriver.storage.googleapis.com/2.31/chromedriver_linux64.zip",
		name:   "chromedriver_2.31_linux64.zip",
		hash:   "3e372ef676beb3a03aba72089ec0624bb9d3b52597635f907d4c23390fb485a0",
		rename: []string{"chromedriver", "chromedriver-linux64-2.31"},
	},
	{
		url:    "https://github.com/mozilla/geckodriver/releases/download/v0.18.0/geckodriver-v0.18.0-linux64.tar.gz",
		name:   "geckodriver-v0.18.0-linux64.tar.gz",
		hash:   "b78a0c5d2e249312d266d846e803e88a26477de20f33bfd635e164d27e59ae20",
		rename: []string{"geckodriver", "geckodriver-v0.18.0-linux64"},
	},
	{
		// This is a recent nightly. Update this path periodically.
		url:     "https://archive.mozilla.org/pub/firefox/nightly/2017/08/2017-08-21-10-03-50-mozilla-central/firefox-57.0a1.en-US.linux-x86_64.tar.bz2",
		name:    "firefox-57.0a1.en-US.linux-x86_64.tar.bz2",
		hash:    "77c57356935f66a5a59b1b2cffeaa53b70204195e6a7b15ee828fd3308561e46",
		browser: true,
		rename:  []string{"firefox", "firefox-nightly"},
	},
	{
		url:    "https://saucelabs.com/downloads/sc-4.4.9-linux.tar.gz",
		name:   "sauce-connect-4.4.9-linux.tar.gz",
		hash:   "b1bedccc2690b48d6708ac71f23189c85b0da62c56ee943a1b20d8f17fa8bbde",
		rename: []string{"sc-4.4.9-linux", "sauce-connect"},
	},
}

func addChrome(ctx context.Context) error {
	const (
		// Bucket URL: https://console.cloud.google.com/storage/browser/chromium-browser-continuous/?pli=1
		storageBktName = "chromium-browser-snapshots"
		prefixLinux64  = "Linux_x64"
		lastChangeFile = "Linux_x64/LAST_CHANGE"
		chromeFilename = "chrome-linux.zip"
	)
	gcsPath := fmt.Sprintf("gs://%s/", storageBktName)
	client, err := storage.NewClient(ctx, option.WithHTTPClient(http.DefaultClient))
	if err != nil {
		return fmt.Errorf("cannot create a storage client for downloading the chrome browser: %v", err)
	}
	bkt := client.Bucket(storageBktName)
	r, err := bkt.Object(lastChangeFile).NewReader(ctx)
	if err != nil {
		return fmt.Errorf("cannot create a reader for %s%s file: %v", gcsPath, lastChangeFile, err)
	}
	defer r.Close()
	// Read the last change file content for the latest build directory name
	data, err := ioutil.ReadAll(r)
	if err != nil {
		return fmt.Errorf("cannot read from %s%s file: %v", gcsPath, lastChangeFile, err)
	}
	latestChromeBuild := string(data)
	latestChromePackage := path.Join(prefixLinux64, latestChromeBuild, chromeFilename)
	cpAttrs, err := bkt.Object(latestChromePackage).Attrs(ctx)
	if err != nil {
		return fmt.Errorf("cannot get the chrome package %s%s attrs: %v", gcsPath, latestChromePackage, err)
	}
	files = append(files, file{
		name:     chromeFilename,
		browser:  true,
		hash:     hex.EncodeToString(cpAttrs.MD5),
		hashType: "md5",
		url:      cpAttrs.MediaLink,
	})
	return nil
}

func main() {
	flag.Parse()
	ctx := context.Background()
	if *downloadBrowsers {
		if err := addChrome(ctx); err != nil {
			glog.Errorf("unable to Download Google Chrome browser: %v", err)
		}
	}
	var wg sync.WaitGroup
	for _, file := range files {
		wg.Add(1)
		file := file
		go func() {
			if err := handleFile(file); err != nil {
				glog.Exitf("Error handling %s: %s", file.name, err)
			}
			wg.Done()
		}()
	}
	wg.Wait()
}

func handleFile(file file) error {
	if file.browser && !*downloadBrowsers {
		glog.Infof("Skipping %q because --download_browser is not set.", file.name)
		return nil
	}
	if !fileSameHash(file) {
		glog.Infof("Downloading %q from %q", file.name, file.url)
		if err := downloadFile(file); err != nil {
			return err
		}
	} else {
		glog.Infof("Skipping file %q which has already been downloaded.", file.name)
	}

	switch path.Ext(file.name) {
	case ".zip":
		glog.Infof("Unzipping %q", file.name)
		if err := exec.Command("unzip", "-o", file.name).Run(); err != nil {
			return fmt.Errorf("Error unzipping %q: %v", file.name, err)
		}
	case ".gz":
		glog.Infof("Unzipping %q", file.name)
		if err := exec.Command("tar", "-xzf", file.name).Run(); err != nil {
			return fmt.Errorf("Error unzipping %q: %v", file.name, err)
		}
	case ".bz2":
		glog.Infof("Unzipping %q", file.name)
		if err := exec.Command("tar", "-xjf", file.name).Run(); err != nil {
			return fmt.Errorf("Error unzipping %q: %v", file.name, err)
		}
	}
	if rename := file.rename; len(rename) == 2 {
		glog.Infof("Renaming %q to %q", rename[0], rename[1])
		os.RemoveAll(rename[1]) // Ignore error.
		if err := os.Rename(rename[0], rename[1]); err != nil {
			glog.Warningf("Error renaming %q to %q: %v", rename[0], rename[1], err)
		}
	}
	return nil
}

func downloadFile(file file) (err error) {
	f, err := os.Create(file.name)
	if err != nil {
		return fmt.Errorf("error creating %q: %v", file.name, err)
	}
	defer func() {
		if closeErr := f.Close(); closeErr != nil && err == nil {
			err = fmt.Errorf("error closing %q: %v", file.name, err)
		}
	}()

	resp, err := http.Get(file.url)
	if err != nil {
		return fmt.Errorf("%s: error downloading %q: %v", file.name, file.url, err)
	}
	defer resp.Body.Close()
	var h hash.Hash
	switch strings.ToLower(file.hashType) {
	case "md5":
		h = md5.New()
	default:
		h = sha256.New()
	}
	if _, err := io.Copy(io.MultiWriter(f, h), resp.Body); err != nil {
		return fmt.Errorf("%s: error downloading %q: %v", file.name, file.url, err)
	}
	if h := hex.EncodeToString(h.Sum(nil)); h != file.hash {
		return fmt.Errorf("%s: got %s hash %q, want %q", file.name, file.hashType, h, file.hash)
	}
	return nil
}

func fileSameHash(file file) bool {
	if _, err := os.Stat(file.name); err != nil {
		return false
	}
	var h hash.Hash
	switch strings.ToLower(file.hashType) {
	case "md5":
		h = md5.New()
	default:
		h = sha256.New()
	}
	f, err := os.Open(file.name)
	if err != nil {
		return false
	}
	defer f.Close()

	if _, err := io.Copy(h, f); err != nil {
		return false
	}

	sum := hex.EncodeToString(h.Sum(nil))
	if sum != file.hash {
		glog.Warningf("File %q: got hash %q, expect hash %q", file.name, sum, file.hash)
		return false
	}
	return true
}
<|endoftext|>


<commit_before>package mission

import (
	"bytes"
	"github.com/blang/gosqm/sqm"
	"io/ioutil"
	"testing"
)

func BenchmarkFullDecode(b *testing.B) {
	buf, err := ioutil.ReadFile("../sqm/mission.sqm")
	bufstr := string(buf)
	if err != nil {
		b.Errorf("Could not open mission.sqm")
		return
	}
	for n := 0; n < b.N; n++ {
		p := sqm.MakeParser(bufstr)
		// c, perr := p.Run()
		class, perr := p.Run()
		if perr != nil {
			b.Errorf("Parser returned with error %q", perr)
		}
		mp := NewParser()
		_, err := mp.Parse(class)
		if err != nil {
			b.Errorf("Can't parse class to missionfile, %q", err)
		}

	}
}

func BenchmarkFullEncode(b *testing.B) {
	buf, err := ioutil.ReadFile("../sqm/mission.sqm")
	bufstr := string(buf)
	if err != nil {
		b.Errorf("Could not open mission.sqm")
		return
	}
	p := sqm.MakeParser(bufstr)
	// c, perr := p.Run()
	class, perr := p.Run()
	if perr != nil {
		b.Errorf("Parser returned with error %q", perr)
	}
	mp := NewParser()
	missionFile, err := mp.Parse(class)
	if err != nil {
		b.Errorf("Can't parse class to missionfile, %q", err)
	}
	for n := 0; n < b.N; n++ {
		enc := NewEncoder()
		eclass := enc.Encode(missionFile)
		var buf []byte
		buffer := bytes.NewBuffer(buf)
		sqmenc := sqm.NewEncoder(buffer)
		err := sqmenc.Encode(eclass)
		if err != nil {
			b.Errorf("Can't encode class, %q", err)
		}

	}
}

func BenchmarkFullEncodeDecode(b *testing.B) {
	buf, err := ioutil.ReadFile("../sqm/mission.sqm")
	bufstr := string(buf)
	if err != nil {
		b.Errorf("Could not open mission.sqm")
		return
	}
	for n := 0; n < b.N; n++ {
		p := sqm.MakeParser(bufstr)
		// c, perr := p.Run()
		class, perr := p.Run()
		if perr != nil {
			b.Errorf("Parser returned with error %q", perr)
		}
		mp := NewParser()
		missionFile, err := mp.Parse(class)
		if err != nil {
			b.Errorf("Can't parse class to missionfile, %q", err)
		}
		enc := NewEncoder()
		eclass := enc.Encode(missionFile)
		var buf []byte
		buffer := bytes.NewBuffer(buf)
		sqmenc := sqm.NewEncoder(buffer)
		err = sqmenc.Encode(eclass)
		if err != nil {
			b.Errorf("Can't encode class, %q", err)
		}

	}
}
<commit_msg>Further tests for benchmarking<commit_after>package mission

import (
	"bytes"
	"github.com/blang/gosqm/sqm"
	"io/ioutil"
	"testing"
)

func BenchmarkFullDecode(b *testing.B) {
	buf, err := ioutil.ReadFile("../sqm/mission.sqm")
	bufstr := string(buf)
	if err != nil {
		b.Errorf("Could not open mission.sqm")
		return
	}
	for n := 0; n < b.N; n++ {
		p := sqm.MakeParser(bufstr)
		// c, perr := p.Run()
		class, perr := p.Run()
		if perr != nil {
			b.Errorf("Parser returned with error %q", perr)
		}
		mp := NewParser()
		_, err := mp.Parse(class)
		if err != nil {
			b.Errorf("Can't parse class to missionfile, %q", err)
		}

	}
}

func BenchmarkFullEncode(b *testing.B) {
	buf, err := ioutil.ReadFile("../sqm/mission.sqm")
	bufstr := string(buf)
	if err != nil {
		b.Errorf("Could not open mission.sqm")
		return
	}
	p := sqm.MakeParser(bufstr)
	// c, perr := p.Run()
	class, perr := p.Run()
	if perr != nil {
		b.Errorf("Parser returned with error %q", perr)
	}
	mp := NewParser()
	missionFile, err := mp.Parse(class)
	if err != nil {
		b.Errorf("Can't parse class to missionfile, %q", err)
	}
	for n := 0; n < b.N; n++ {
		enc := NewEncoder()
		eclass := enc.Encode(missionFile)
		var buf []byte
		buffer := bytes.NewBuffer(buf)
		sqmenc := sqm.NewEncoder(buffer)
		err := sqmenc.Encode(eclass)
		if err != nil {
			b.Errorf("Can't encode class, %q", err)
		}

	}
}

func BenchmarkMissionEncode(b *testing.B) {
	buf, err := ioutil.ReadFile("../sqm/mission.sqm")
	bufstr := string(buf)
	if err != nil {
		b.Errorf("Could not open mission.sqm")
		return
	}
	p := sqm.MakeParser(bufstr)
	// c, perr := p.Run()
	class, perr := p.Run()
	if perr != nil {
		b.Errorf("Parser returned with error %q", perr)
	}
	mp := NewParser()
	missionFile, err := mp.Parse(class)
	if err != nil {
		b.Errorf("Can't parse class to missionfile, %q", err)
	}

	for n := 0; n < b.N; n++ {
		enc := NewEncoder()
		enc.Encode(missionFile)
	}
}

func BenchmarkMissionDecode(b *testing.B) {
	buf, err := ioutil.ReadFile("../sqm/mission.sqm")
	bufstr := string(buf)
	if err != nil {
		b.Errorf("Could not open mission.sqm")
		return
	}
	p := sqm.MakeParser(bufstr)
	// c, perr := p.Run()
	class, perr := p.Run()
	if perr != nil {
		b.Errorf("Parser returned with error %q", perr)
	}
	for n := 0; n < b.N; n++ {
		mp := NewParser()
		missionFile, err := mp.Parse(class)
		if err != nil {
			b.Errorf("Can't parse class to missionfile, %q", err)
		}
		if len(missionFile.Mission.Groups) < 5 {
			b.Errorf("Error while parsing mission, %q", missionFile)
		}
	}
}

func BenchmarkFullEncodeDecode(b *testing.B) {
	buf, err := ioutil.ReadFile("../sqm/mission.sqm")
	bufstr := string(buf)
	if err != nil {
		b.Errorf("Could not open mission.sqm")
		return
	}
	for n := 0; n < b.N; n++ {
		p := sqm.MakeParser(bufstr)
		// c, perr := p.Run()
		class, perr := p.Run()
		if perr != nil {
			b.Errorf("Parser returned with error %q", perr)
		}
		mp := NewParser()
		missionFile, err := mp.Parse(class)
		if err != nil {
			b.Errorf("Can't parse class to missionfile, %q", err)
		}
		enc := NewEncoder()
		eclass := enc.Encode(missionFile)
		var ebuf []byte
		buffer := bytes.NewBuffer(ebuf)
		sqmenc := sqm.NewEncoder(buffer)
		err = sqmenc.Encode(eclass)
		if err != nil {
			b.Errorf("Can't encode class, %q", err)
		}

	}
}

func TestFullEncodeDecode(t *testing.T) {
	buf, err := ioutil.ReadFile("../sqm/mission.sqm")
	bufstr := string(buf)
	if err != nil {
		t.Errorf("Could not open mission.sqm")
		return
	}
	p := sqm.MakeParser(bufstr)
	// c, perr := p.Run()
	class, perr := p.Run()
	if perr != nil {
		t.Errorf("Parser returned with error %q", perr)
	}
	mp := NewParser()
	missionFile, err := mp.Parse(class)
	if err != nil {
		t.Errorf("Can't parse class to missionfile, %q", err)
	}
	enc := NewEncoder()
	eclass := enc.Encode(missionFile)
	var ebuf []byte
	buffer := bytes.NewBuffer(ebuf)
	sqmenc := sqm.NewEncoder(buffer)
	err = sqmenc.Encode(eclass)
	if err != nil {
		t.Errorf("Can't encode class, %q", err)
	}
}
<|endoftext|>


<commit_before>package views

import (
	"fmt"
	"html/template"
	"net/http"
	"sort"

	"github.com/gin-gonic/gin"
	"github.com/spf13/viper"

	"github.com/Depado/smallblog/models"
)

// GetRSSFeed returns the RSS feed of the blog
func GetRSSFeed(c *gin.Context) {
	rss, err := models.RSS.ToRss()
	if err != nil {
		c.String(http.StatusInternalServerError, "500 internal server error")
		return
	}
	c.Data(200, "text/xml", []byte(rss))
}

// PostsByTag searches for posts containing tag
func PostsByTag(c *gin.Context) {
	tag := c.Param("tag")
	res := []*models.Page{}
	for _, v := range models.SPages {
		for _, b := range v.Tags {
			if b == tag {
				res = append(res, v)
			}
		}
	}
	if len(res) > 0 {
		data := gin.H{
			"posts":       res,
			"title":       viper.GetString("blog.title"),
			"description": viper.GetString("blog.description"),
			"extra":       template.HTML(fmt.Sprintf(`Posts tagged with <span class="home-sm-tag">%s</span>`, tag)),
			"analytics":   gin.H{"tag": viper.GetString("analytics.tag"), "enabled": viper.GetBool("analytics.enabled")},
			"author":      models.GetGlobalAuthor(),
		}
		c.HTML(http.StatusOK, "index.tmpl", data)
	} else {
		c.String(http.StatusNotFound, "404 no posts found with this tag")
	}
}

// Post is the views for a single post.
func Post(c *gin.Context) {
	if page, ok := models.MPages[c.Param("slug")]; ok {
		data := gin.H{
			"post":        page,
			"gitalk":      models.GetGitalk(),
			"extra_style": models.GlobCSS,
			"analytics":   gin.H{"tag": viper.GetString("analytics.tag"), "enabled": viper.GetBool("analytics.enabled")},
			"share":       viper.GetBool("blog.share"),
			"share_url":   page.GetShare(),
		}
		c.HTML(http.StatusOK, "post.tmpl", data)
	} else {
		c.String(http.StatusNotFound, "404 not found")
	}
}

// RawPost is used to view the raw markdown file
func RawPost(c *gin.Context) {
	slug := c.Param("slug")
	if val, ok := models.MPages[slug]; ok {
		c.Writer.Write([]byte(val.Raw))
	} else {
		c.String(http.StatusNotFound, "404 not found")
	}
}

// Index is the view to list all posts.
func Index(c *gin.Context) {
	data := gin.H{
		"posts":       models.SPages,
		"title":       viper.GetString("blog.title"),
		"description": viper.GetString("blog.description"),
		"analytics":   gin.H{"tag": viper.GetString("analytics.tag"), "enabled": viper.GetBool("analytics.enabled")},
		"author":      models.GetGlobalAuthor(),
	}
	c.HTML(http.StatusOK, "index.tmpl", data)
}

// GetDrafts gets the unsorted drafts
func GetDrafts(c *gin.Context) {
	o := models.PageSlice{}
	for _, v := range models.MPages {
		if v.Draft {
			o = append(o, v)
		}
	}
	sort.Sort(o)
	data := gin.H{
		"posts":       o,
		"title":       viper.GetString("blog.title"),
		"description": viper.GetString("blog.description"),
		"analytics":   gin.H{"tag": viper.GetString("analytics.tag"), "enabled": viper.GetBool("analytics.enabled")},
		"author":      models.GetGlobalAuthor(),
	}
	c.HTML(http.StatusOK, "index.tmpl", data)
}
<commit_msg>Adding explanation text on draft page<commit_after>package views

import (
	"fmt"
	"html/template"
	"net/http"
	"sort"

	"github.com/gin-gonic/gin"
	"github.com/spf13/viper"

	"github.com/Depado/smallblog/models"
)

// GetRSSFeed returns the RSS feed of the blog
func GetRSSFeed(c *gin.Context) {
	rss, err := models.RSS.ToRss()
	if err != nil {
		c.String(http.StatusInternalServerError, "500 internal server error")
		return
	}
	c.Data(200, "text/xml", []byte(rss))
}

// PostsByTag searches for posts containing tag
func PostsByTag(c *gin.Context) {
	tag := c.Param("tag")
	res := []*models.Page{}
	for _, v := range models.SPages {
		for _, b := range v.Tags {
			if b == tag {
				res = append(res, v)
			}
		}
	}
	if len(res) > 0 {
		data := gin.H{
			"posts":       res,
			"title":       viper.GetString("blog.title"),
			"description": viper.GetString("blog.description"),
			"extra":       template.HTML(fmt.Sprintf(`Posts tagged with <span class="btn tag">%s</span>`, tag)),
			"analytics":   gin.H{"tag": viper.GetString("analytics.tag"), "enabled": viper.GetBool("analytics.enabled")},
			"author":      models.GetGlobalAuthor(),
		}
		c.HTML(http.StatusOK, "index.tmpl", data)
	} else {
		c.String(http.StatusNotFound, "404 no posts found with this tag")
	}
}

// Post is the views for a single post.
func Post(c *gin.Context) {
	if page, ok := models.MPages[c.Param("slug")]; ok {
		data := gin.H{
			"post":        page,
			"gitalk":      models.GetGitalk(),
			"extra_style": models.GlobCSS,
			"analytics":   gin.H{"tag": viper.GetString("analytics.tag"), "enabled": viper.GetBool("analytics.enabled")},
			"share":       viper.GetBool("blog.share"),
			"share_url":   page.GetShare(),
		}
		c.HTML(http.StatusOK, "post.tmpl", data)
	} else {
		c.String(http.StatusNotFound, "404 not found")
	}
}

// RawPost is used to view the raw markdown file
func RawPost(c *gin.Context) {
	slug := c.Param("slug")
	if val, ok := models.MPages[slug]; ok {
		c.Writer.Write([]byte(val.Raw))
	} else {
		c.String(http.StatusNotFound, "404 not found")
	}
}

// Index is the view to list all posts.
func Index(c *gin.Context) {
	data := gin.H{
		"posts":       models.SPages,
		"title":       viper.GetString("blog.title"),
		"description": viper.GetString("blog.description"),
		"analytics":   gin.H{"tag": viper.GetString("analytics.tag"), "enabled": viper.GetBool("analytics.enabled")},
		"author":      models.GetGlobalAuthor(),
	}
	c.HTML(http.StatusOK, "index.tmpl", data)
}

// GetDrafts gets the unsorted drafts
func GetDrafts(c *gin.Context) {
	o := models.PageSlice{}
	for _, v := range models.MPages {
		if v.Draft {
			o = append(o, v)
		}
	}
	sort.Sort(o)
	data := gin.H{
		"posts":       o,
		"title":       viper.GetString("blog.title"),
		"description": viper.GetString("blog.description"),
		"extra":       template.HTML(`These articles are drafts and may be incomplete`),
		"analytics":   gin.H{"tag": viper.GetString("analytics.tag"), "enabled": viper.GetBool("analytics.enabled")},
		"author":      models.GetGlobalAuthor(),
	}
	c.HTML(http.StatusOK, "index.tmpl", data)
}
<|endoftext|>


<commit_before>package main

const VERSION = "0.9.3"
<commit_msg>[nqm-agent] v0.9.5<commit_after>package main

const VERSION = "0.9.5"
<|endoftext|>


<commit_before>package wav

import (
	"encoding/binary"
	"fmt"
	"io"
	"os"

	"github.com/mattetti/audio"
	"github.com/mattetti/audio/riff"
)

// Encoder encodes LPCM data into a wav containter.
type Encoder struct {
	w          io.WriteSeeker
	SampleRate int
	BitDepth   int
	NumChans   int

	// A number indicating the WAVE format category of the file. The content of the
	// <format-specific-fields> portion of the ‘fmt’ chunk, and the interpretation of
	// the waveform data, depend on this value.
	// PCM = 1 (i.e. Linear quantization) Values other than 1 indicate some form of compression.
	WavAudioFormat int

	WrittenBytes    int
	frames          int
	pcmChunkStarted bool
	pcmChunkSizePos int
}

// NewEncoder creates a new encoder to create a new wav file.
// Don't forget to add Frames to the encoder before writing.
func NewEncoder(w io.WriteSeeker, sampleRate, bitDepth, numChans, audioFormat int) *Encoder {
	return &Encoder{
		w:              w,
		SampleRate:     sampleRate,
		BitDepth:       bitDepth,
		NumChans:       numChans,
		WavAudioFormat: audioFormat,
	}
}

// AddLE serializes and adds the passed value using little endian
func (e *Encoder) AddLE(src interface{}) error {
	e.WrittenBytes += binary.Size(src)
	return binary.Write(e.w, binary.LittleEndian, src)
}

// AddBE serializes and adds the passed value using big endian
func (e *Encoder) AddBE(src interface{}) error {
	e.WrittenBytes += binary.Size(src)
	return binary.Write(e.w, binary.BigEndian, src)
}

func (e *Encoder) addBuffer(buf *audio.PCMBuffer) error {
	if buf == nil {
		return fmt.Errorf("can't add a nil buffer")
	}

	frameCount := buf.Size()
	buf.CacheInts()
	for i := 0; i < frameCount; i++ {
		// TODO(mattetti): support float encoded wav files
		for j := 0; j < buf.Format.NumChannels; j++ {
			v := buf.Ints[i*buf.Format.NumChannels+j]
			switch e.BitDepth {
			case 8:
				if err := e.AddLE(uint8(v)); err != nil {
					return err
				}
			case 16:
				if err := e.AddLE(int16(v)); err != nil {
					return err
				}
			case 24:
				if err := e.AddLE(audio.Int32toInt24LEBytes(int32(v))); err != nil {
					return err
				}
			case 32:
				if err := e.AddLE(int32(v)); err != nil {
					return err
				}
			default:
				return fmt.Errorf("can't add frames of bit size %d", e.BitDepth)
			}
		}
		e.frames++
	}

	return nil
}

func (e *Encoder) writeHeader() error {
	if e == nil {
		return fmt.Errorf("can't write a nil encoder")
	}
	if e.w == nil {
		return fmt.Errorf("can't write to a nil writer")
	}

	if e.WrittenBytes > 0 {
		return nil
	}

	// riff ID
	if err := e.AddLE(riff.RiffID); err != nil {
		return err
	}
	// file size uint32, to update later on.
	if err := e.AddLE(uint32(42)); err != nil {
		return err
	}
	// wave headers
	if err := e.AddLE(riff.WavFormatID); err != nil {
		return err
	}
	// form
	if err := e.AddLE(riff.FmtID); err != nil {
		return err
	}
	// chunk size
	if err := e.AddLE(uint32(16)); err != nil {
		return err
	}
	// wave format
	if err := e.AddLE(uint16(e.WavAudioFormat)); err != nil {
		return err
	}
	// num channels
	if err := e.AddLE(uint16(e.NumChans)); err != nil {
		return fmt.Errorf("error encoding the number of channels - %v", err)
	}
	// samplerate
	if err := e.AddLE(uint32(e.SampleRate)); err != nil {
		return fmt.Errorf("error encoding the sample rate - %v", err)
	}
	// avg bytes per sec
	if err := e.AddLE(uint32(e.SampleRate * e.NumChans * e.BitDepth / 8)); err != nil {
		return fmt.Errorf("error encoding the avg bytes per sec - %v", err)
	}
	// block align
	if err := e.AddLE(uint16(2)); err != nil {
		return err
	}
	// bits per sample
	if err := e.AddLE(uint16(e.BitDepth)); err != nil {
		return fmt.Errorf("error encoding bits per sample - %v", err)
	}

	return nil
}

// Write encodes and writes the passed buffer to the underlying writer.
// Don't forger to Close() the encoder or the file won't be valid.
func (e *Encoder) Write(buf *audio.PCMBuffer) error {
	if err := e.writeHeader(); err != nil {
		return err
	}

	if !e.pcmChunkStarted {
		// sound header
		if err := e.AddLE(riff.DataFormatID); err != nil {
			return fmt.Errorf("error encoding sound header %v", err)
		}

		// write a temporary chunksize
		e.pcmChunkSizePos = e.WrittenBytes
		if err := e.AddLE(uint32(42)); err != nil {
			return fmt.Errorf("%v when writing wav data chunk size header", err)
		}
	}

	return e.addBuffer(buf)
}

// Close flushes the content to disk, make sure the headers are up to date
// Note that the underlying writter is NOT being closed.
func (e *Encoder) Close() error {
	if e == nil || e.w == nil {
		return nil
	}

	// go back and write total size in header
	if _, err := e.w.Seek(4, 0); err != nil {
		return err
	}
	if err := e.AddLE(uint32(e.WrittenBytes) - 8); err != nil {
		return fmt.Errorf("%v when writing the total written bytes", err)
	}

	// rewrite the audio chunk length header
	if e.pcmChunkSizePos > 0 {
		if _, err := e.w.Seek(int64(e.pcmChunkSizePos), 0); err != nil {
			return err
		}
		chunksize := uint32((int(e.BitDepth) / 8) * int(e.NumChans) * e.frames)
		if err := e.AddLE(uint32(chunksize)); err != nil {
			return fmt.Errorf("%v when writing wav data chunk size header", err)
		}
	}

	// jump back to the end of the file.
	if _, err := e.w.Seek(0, 2); err != nil {
		return err
	}
	switch e.w.(type) {
	case *os.File:
		return e.w.(*os.File).Sync()
	}
	return nil
}
<commit_msg>wav: fix bug with the chunk encoder<commit_after>package wav

import (
	"encoding/binary"
	"fmt"
	"io"
	"os"

	"github.com/mattetti/audio"
	"github.com/mattetti/audio/riff"
)

// Encoder encodes LPCM data into a wav containter.
type Encoder struct {
	w          io.WriteSeeker
	SampleRate int
	BitDepth   int
	NumChans   int

	// A number indicating the WAVE format category of the file. The content of the
	// <format-specific-fields> portion of the ‘fmt’ chunk, and the interpretation of
	// the waveform data, depend on this value.
	// PCM = 1 (i.e. Linear quantization) Values other than 1 indicate some form of compression.
	WavAudioFormat int

	WrittenBytes    int
	frames          int
	pcmChunkStarted bool
	pcmChunkSizePos int
}

// NewEncoder creates a new encoder to create a new wav file.
// Don't forget to add Frames to the encoder before writing.
func NewEncoder(w io.WriteSeeker, sampleRate, bitDepth, numChans, audioFormat int) *Encoder {
	return &Encoder{
		w:              w,
		SampleRate:     sampleRate,
		BitDepth:       bitDepth,
		NumChans:       numChans,
		WavAudioFormat: audioFormat,
	}
}

// AddLE serializes and adds the passed value using little endian
func (e *Encoder) AddLE(src interface{}) error {
	e.WrittenBytes += binary.Size(src)
	return binary.Write(e.w, binary.LittleEndian, src)
}

// AddBE serializes and adds the passed value using big endian
func (e *Encoder) AddBE(src interface{}) error {
	e.WrittenBytes += binary.Size(src)
	return binary.Write(e.w, binary.BigEndian, src)
}

func (e *Encoder) addBuffer(buf *audio.PCMBuffer) error {
	if buf == nil {
		return fmt.Errorf("can't add a nil buffer")
	}

	frameCount := buf.Size()
	buf.CacheInts()
	for i := 0; i < frameCount; i++ {
		// TODO(mattetti): support float encoded wav files
		for j := 0; j < buf.Format.NumChannels; j++ {
			v := buf.Ints[i*buf.Format.NumChannels+j]
			switch e.BitDepth {
			case 8:
				if err := e.AddLE(uint8(v)); err != nil {
					return err
				}
			case 16:
				if err := e.AddLE(int16(v)); err != nil {
					return err
				}
			case 24:
				if err := e.AddLE(audio.Int32toInt24LEBytes(int32(v))); err != nil {
					return err
				}
			case 32:
				if err := e.AddLE(int32(v)); err != nil {
					return err
				}
			default:
				return fmt.Errorf("can't add frames of bit size %d", e.BitDepth)
			}
		}
		e.frames++
	}

	return nil
}

func (e *Encoder) writeHeader() error {
	if e == nil {
		return fmt.Errorf("can't write a nil encoder")
	}
	if e.w == nil {
		return fmt.Errorf("can't write to a nil writer")
	}

	if e.WrittenBytes > 0 {
		return nil
	}

	// riff ID
	if err := e.AddLE(riff.RiffID); err != nil {
		return err
	}
	// file size uint32, to update later on.
	if err := e.AddLE(uint32(42)); err != nil {
		return err
	}
	// wave headers
	if err := e.AddLE(riff.WavFormatID); err != nil {
		return err
	}
	// form
	if err := e.AddLE(riff.FmtID); err != nil {
		return err
	}
	// chunk size
	if err := e.AddLE(uint32(16)); err != nil {
		return err
	}
	// wave format
	if err := e.AddLE(uint16(e.WavAudioFormat)); err != nil {
		return err
	}
	// num channels
	if err := e.AddLE(uint16(e.NumChans)); err != nil {
		return fmt.Errorf("error encoding the number of channels - %v", err)
	}
	// samplerate
	if err := e.AddLE(uint32(e.SampleRate)); err != nil {
		return fmt.Errorf("error encoding the sample rate - %v", err)
	}
	// avg bytes per sec
	if err := e.AddLE(uint32(e.SampleRate * e.NumChans * e.BitDepth / 8)); err != nil {
		return fmt.Errorf("error encoding the avg bytes per sec - %v", err)
	}
	// block align
	if err := e.AddLE(uint16(2)); err != nil {
		return err
	}
	// bits per sample
	if err := e.AddLE(uint16(e.BitDepth)); err != nil {
		return fmt.Errorf("error encoding bits per sample - %v", err)
	}

	return nil
}

// Write encodes and writes the passed buffer to the underlying writer.
// Don't forger to Close() the encoder or the file won't be valid.
func (e *Encoder) Write(buf *audio.PCMBuffer) error {
	if err := e.writeHeader(); err != nil {
		return err
	}

	if !e.pcmChunkStarted {
		// sound header
		if err := e.AddLE(riff.DataFormatID); err != nil {
			return fmt.Errorf("error encoding sound header %v", err)
		}
		e.pcmChunkStarted = true

		// write a temporary chunksize
		e.pcmChunkSizePos = e.WrittenBytes
		if err := e.AddLE(uint32(42)); err != nil {
			return fmt.Errorf("%v when writing wav data chunk size header", err)
		}
	}

	return e.addBuffer(buf)
}

// Close flushes the content to disk, make sure the headers are up to date
// Note that the underlying writter is NOT being closed.
func (e *Encoder) Close() error {
	if e == nil || e.w == nil {
		return nil
	}

	// go back and write total size in header
	if _, err := e.w.Seek(4, 0); err != nil {
		return err
	}
	if err := e.AddLE(uint32(e.WrittenBytes) - 8); err != nil {
		return fmt.Errorf("%v when writing the total written bytes", err)
	}

	// rewrite the audio chunk length header
	if e.pcmChunkSizePos > 0 {
		if _, err := e.w.Seek(int64(e.pcmChunkSizePos), 0); err != nil {
			return err
		}
		chunksize := uint32((int(e.BitDepth) / 8) * int(e.NumChans) * e.frames)
		if err := e.AddLE(uint32(chunksize)); err != nil {
			return fmt.Errorf("%v when writing wav data chunk size header", err)
		}
	}

	// jump back to the end of the file.
	if _, err := e.w.Seek(0, 2); err != nil {
		return err
	}
	switch e.w.(type) {
	case *os.File:
		return e.w.(*os.File).Sync()
	}
	return nil
}
<|endoftext|>


<commit_before>package weave

import (
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"

	"go/ast"
	"go/parser"
	"go/token"

	_ "golang.org/x/tools/go/gcimporter"
	"golang.org/x/tools/go/loader"
	"golang.org/x/tools/go/types"
)

// Weave is struct runner for aspect transforms
type Weave struct {
	flog    *log.Logger
	aspects []Aspect

	// warn if AST parsing warns you
	// off by default as many times we don't care
	warnAST bool

	// the pkg where we run goweave
	basePkg string

	// build location is where weave our aspects
	buildLocation string

	// verbose debugging output
	verbose bool

	// appliedGlobal is a HACK - the goal is to keep track of whether or
	// not we have kept tracked of advice in a pkg so far - this is
	// currently not working as expected as sub-pkgs are ignored
	appliedGlobal bool
}

// NewWeave instantiates and returns a new aop
func NewWeave() *Weave {

	w := &Weave{
		flog:          log.New(os.Stdout, "", log.Ldate|log.Ltime|log.Lshortfile),
		basePkg:       setBase(),
		buildLocation: tmpLocation(),
	}

	return w

}

// Run preps, grabs advice, transforms the src, and builds the code
func (w *Weave) Run() {
	w.prep()
	w.loadAspects()

	// old regex parsing
	// only used for go routines currently
	// soon to be DEPRECATED
	w.transform()

	// applys around advice && evals execution joinpoints
	filepath.Walk(w.buildLocation, w.VisitFile)

	w.build()

}

// VisitFile walks each file and transforms it's
// this is fairly heavy/expensive/pos right now
func (w *Weave) VisitFile(fp string, fi os.FileInfo, err error) error {

	if fi == nil || err != nil {
		return err
	}

	matched, err := filepath.Match("*.go", fi.Name())
	if err != nil {
		w.flog.Println(err)
		return err
	}

	if matched {

		// provides 'around' style advice
		// HACK - should be moved to call advice
		stuff := w.applyAroundAdvice(fp)
		w.writeOut(fp, stuff)

		// any global advice ? stick it in this file
		// FIXME
		stuff = w.applyGlobalAdvice(fp, stuff)
		w.writeOut(fp, stuff)

		// provides advice matching against call join points
		stuff = w.applyCallAdvice(fp, stuff)
		w.writeOut(fp, stuff)

		// provides advice matching against execution join points
		stuff = w.applyExecutionJP(fp, stuff)
		w.writeOut(fp, stuff)

		// provides advice matching against within join points
		stuff = w.applyWithinJP(fp, stuff)
		w.writeOut(fp, stuff)

		// finally re-work imports on each
		// to ensure files we didn't apply aspects to have correct
		// imports (eg: main.go)
		w.reWorkImports(fp)

	}

	return nil
}

// Parse parses the ast for this file and returns a ParsedFile
func (w *Weave) ParseAST(fname string) *ast.File {
	var err error

	fset := token.NewFileSet()
	af, err := parser.ParseFile(fset, fname, nil, 0)
	if err != nil {
		w.flog.Println(err)
	}

	loadcfg := loader.Config{}
	loadcfg.CreateFromFilenames(fname)

	info := types.Info{
		Types: make(map[ast.Expr]types.TypeAndValue),
		Defs:  make(map[*ast.Ident]types.Object),
	}

	var conf types.Config
	_, err = conf.Check(af.Name.Name, fset, []*ast.File{af}, &info)
	if err != nil {
		if w.warnAST {
			w.flog.Println(err)
		}
	}

	return af
}

// pointCutMatch returns an aspect if there is a pointcut match on this
// line or returns an empty aspect
func pointCutMatch(a []Aspect, l string) Aspect {
	for i := 0; i < len(a); i++ {

		// look for go-routines
		if strings.Contains(l, "go ") && ("go" == a[i].pointkut.def) {
			return a[i]
		}

	}

	return Aspect{}
}

// transform reads line by line over each src file and inserts advice
// where appropriate
//
// only inserts before/advice after
func (w *Weave) transform() {

	fzs := w.findGoFiles()

	rootpkg := w.rootPkg()

	for i := 0; i < len(fzs); i++ {
		out, b := w.processGoRoutines(fzs[i], rootpkg)

		// FIXME
		if b {
			w.reWriteFile(fzs[i], out, []string{})
		}
	}

}

// findGoFiles recursively finds all go files in a project
func (w *Weave) findGoFiles() []string {
	res := []string{}

	visit := func(path string, f os.FileInfo, err error) error {
		if strings.Contains(path, ".go") {
			res = append(res, path)
		}
		return nil
	}

	err := filepath.Walk(".", visit)
	if err != nil {
		w.flog.Println(err.Error())
	}

	return res
}

// findAspects finds all aspects for this project
func (w *Weave) findAspects() []string {
	aspects := []string{}

	files, _ := ioutil.ReadDir("./")
	for _, f := range files {
		if strings.Contains(f.Name(), ".weave") {
			aspects = append(aspects, f.Name())
			log.Println(f.Name())
		}
	}

	return aspects
}
<commit_msg>Fixes deferpanic/goweave#3<commit_after>package weave

import (
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"

	"go/ast"
	"go/parser"
	"go/token"

	_ "golang.org/x/tools/go/gcimporter"
	"golang.org/x/tools/go/loader"
	"golang.org/x/tools/go/types"
)

// Weave is struct runner for aspect transforms
type Weave struct {
	flog    *log.Logger
	aspects []Aspect

	// warn if AST parsing warns you
	// off by default as many times we don't care
	warnAST bool

	// the pkg where we run goweave
	basePkg string

	// build location is where weave our aspects
	buildLocation string

	// verbose debugging output
	verbose bool

	// appliedGlobal is a HACK - the goal is to keep track of whether or
	// not we have kept tracked of advice in a pkg so far - this is
	// currently not working as expected as sub-pkgs are ignored
	appliedGlobal bool
}

// NewWeave instantiates and returns a new aop
func NewWeave() *Weave {

	w := &Weave{
		flog:          log.New(os.Stdout, "", log.Ldate|log.Ltime|log.Lshortfile),
		basePkg:       setBase(),
		buildLocation: tmpLocation(),
	}

	return w

}

// Run preps, grabs advice, transforms the src, and builds the code
func (w *Weave) Run() {
	w.prep()
	w.loadAspects()

	// old regex parsing
	// only used for go routines currently
	// soon to be DEPRECATED
	w.transform()

	// applys around advice && evals execution joinpoints
	filepath.Walk(w.buildLocation, w.VisitFile)

	w.build()

}

// VisitFile walks each file and transforms it's
// this is fairly heavy/expensive/pos right now
func (w *Weave) VisitFile(fp string, fi os.FileInfo, err error) error {

	if fi == nil || err != nil {
		return err
	}

	matched, err := filepath.Match("*.go", fi.Name())
	if err != nil {
		w.flog.Println(err)
		return err
	}

	if matched {

		// provides 'around' style advice
		// HACK - should be moved to call advice
		stuff := w.applyAroundAdvice(fp)
		w.writeOut(fp, stuff)

		// any global advice ? stick it in this file
		// FIXME
		stuff = w.applyGlobalAdvice(fp, stuff)
		w.writeOut(fp, stuff)

		// provides advice matching against call join points
		stuff = w.applyCallAdvice(fp, stuff)
		w.writeOut(fp, stuff)

		// provides advice matching against execution join points
		stuff = w.applyExecutionJP(fp, stuff)
		w.writeOut(fp, stuff)

		// provides advice matching against within join points
		stuff = w.applyWithinJP(fp, stuff)
		w.writeOut(fp, stuff)

		// finally re-work imports on each
		// to ensure files we didn't apply aspects to have correct
		// imports (eg: main.go)
		w.reWorkImports(fp)

	}

	return nil
}

// Parse parses the ast for this file and returns a ParsedFile
func (w *Weave) ParseAST(fname string) *ast.File {
	var err error

	fset := token.NewFileSet()
	af, err := parser.ParseFile(fset, fname, nil, 0)
	if err != nil {
		w.flog.Println(err)
	}

	loadcfg := loader.Config{}
	loadcfg.CreateFromFilenames(fname)

	info := types.Info{
		Types: make(map[ast.Expr]types.TypeAndValue),
		Defs:  make(map[*ast.Ident]types.Object),
	}

	var conf types.Config
	_, err = conf.Check(af.Name.Name, fset, []*ast.File{af}, &info)
	if err != nil {
		if w.warnAST {
			w.flog.Println(err)
		}
	}

	return af
}

// pointCutMatch returns an aspect if there is a pointcut match on this
// line or returns an empty aspect
func pointCutMatch(a []Aspect, l string) Aspect {
	for i := 0; i < len(a); i++ {

		// look for go-routines
		if strings.Contains(l, "go ") && ("go" == a[i].pointkut.def) {
			return a[i]
		}

	}

	return Aspect{}
}

// transform reads line by line over each src file and inserts advice
// where appropriate
//
// only inserts before/advice after
func (w *Weave) transform() {

	fzs := w.findGoFiles()

	rootpkg := w.rootPkg()

	for i := 0; i < len(fzs); i++ {
		out, b := w.processGoRoutines(fzs[i], rootpkg)

		// FIXME
		if b {
			w.reWriteFile(fzs[i], out, []string{})
		}
	}

}

// findGoFiles recursively finds all go files in a project
func (w *Weave) findGoFiles() []string {
	res := []string{}

	visit := func(path string, f os.FileInfo, err error) error {
		if strings.Contains(path, ".go") {
			res = append(res, path)
		}
		return nil
	}

	err := filepath.Walk(".", visit)
	if err != nil {
		w.flog.Println(err.Error())
	}

	return res
}

// findAspects finds all aspects for this project
func (w *Weave) findAspects() []string {
	aspects := []string{}

	files, _ := ioutil.ReadDir("./")
	for _, f := range files {
		if strings.HasSuffix(f.Name(), ".weave") {
			aspects = append(aspects, f.Name())
			log.Println(f.Name())
		}
	}

	return aspects
}
<|endoftext|>