<commit_before>package main

import (
	"encoding/base64"
	"errors"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/BurntSushi/toml"
	"github.com/bgentry/pflag"
	"github.com/flynn/flynn-controller/client"
)

type Command struct {
	// args does not include the command name
	Run  func(cmd *Command, args []string, client *controller.Client) error
	Flag pflag.FlagSet

	Usage string // first word is the command name
	Short string // `flynn help` output
	Long  string // `flynn help cmd` output

	NoClient bool
}

func (c *Command) printUsage(errExit bool) {
	if c.Runnable() {
		fmt.Printf("Usage: %s %s\n\n", os.Args[0], c.Usage)
	}
	fmt.Println(strings.Trim(c.Long, "\n"))
	if errExit {
		os.Exit(2)
	}
}

func (c *Command) Name() string {
	name := c.Usage
	i := strings.Index(name, " ")
	if i >= 0 {
		name = name[:i]
	}
	return name
}

func (c *Command) Runnable() bool {
	return c.Run != nil
}

// Running `flynn help` will list commands in this order.
var commands = []*Command{
	cmdServerAdd,
	cmdCreate,
	cmdPs,
	cmdLog,
	cmdScale,
	cmdRun,
	cmdRouteAddHTTP,
	cmdKeys,
	cmdKeyAdd,
	cmdKeyRemove,
	cmdVersion,
}

var (
	flagServer = os.Getenv("FLYNN_SERVER")
	flagApp    string
	flagLong   bool
)

func main() {
	log.SetFlags(0)

	args := os.Args[1:]

	// Run the update command as early as possible to avoid the possibility of
	// installations being stranded without updates due to errors in other code
	if args[0] == cmdUpdate.Name() {
		cmdUpdate.Run(cmdUpdate, args, nil)
		return
	} else if updater != nil {
		defer updater.backgroundRun() // doesn't run if os.Exit is called
	}

	if len(args) >= 2 && "-a" == args[0] {
		flagApp = args[1]
		args = args[2:]

		if err := readConfig(); err != nil {
			log.Fatal(err)
		}

		if ra, err := appFromGitRemote(flagApp); err == nil {
			serverConf = ra.Server
			flagApp = ra.Name
		}
	}

	if len(args) < 1 {
		usage()
	}

	for _, cmd := range commands {
		if cmd.Name() == args[0] && cmd.Run != nil {
			cmd.Flag.Usage = func() {
				cmd.printUsage(false)
			}
			if err := cmd.Flag.Parse(args[1:]); err != nil {
				os.Exit(2)
			}

			var client *controller.Client
			if !cmd.NoClient {
				server, err := server()
				if err != nil {
					log.Fatal(err)
				}
				if server.TLSPin != "" {
					pin, err := base64.StdEncoding.DecodeString(server.TLSPin)
					if err != nil {
						log.Fatalln("error decoding tls pin:", err)
					}
					client, err = controller.NewClientWithPin(server.URL, server.Key, pin)
				} else {
					client, err = controller.NewClient(server.URL, server.Key)
				}
				if err != nil {
					log.Fatal(err)
				}
			}
			if err := cmd.Run(cmd, cmd.Flag.Args(), client); err != nil {
				log.Fatal(err)
			}
			return
		}
	}

	fmt.Fprintf(os.Stderr, "Unknown command: %s\n", args[0])
	usage()
}

type Config struct {
	Servers []*ServerConfig `toml:"server"`
}

type ServerConfig struct {
	Name    string `json:"name"`
	GitHost string `json:"git_host"`
	URL     string `json:"url"`
	Key     string `json:"key"`
	TLSPin  string `json:"tls_pin"`
}

var config *Config
var serverConf *ServerConfig

func configPath() string {
	p := os.Getenv("FLYNNRC")
	if p == "" {
		p = filepath.Join(homedir(), ".flynnrc")
	}
	return p
}

func readConfig() error {
	if config != nil {
		return nil
	}
	conf := &Config{}
	_, err := toml.DecodeFile(configPath(), conf)
	if err != nil && !os.IsNotExist(err) {
		return err
	}
	config = conf
	return nil
}

func homedir() string {
	if runtime.GOOS == "windows" {
		return os.Getenv("%APPDATA%")
	}
	return os.Getenv("HOME")
}

var ErrNoServers = errors.New("no servers configured")

func server() (*ServerConfig, error) {
	if serverConf != nil {
		return serverConf, nil
	}
	if err := readConfig(); err != nil {
		return nil, err
	}
	if len(config.Servers) == 0 {
		return nil, ErrNoServers
	}
	if flagServer == "" {
		serverConf = config.Servers[0]
		return serverConf, nil
	}
	for _, s := range config.Servers {
		if s.Name == flagServer {
			serverConf = s
			return s, nil
		}
	}
	return nil, fmt.Errorf("unknown server %q", flagServer)
}

var appName string

func app() (string, error) {
	if flagApp != "" {
		return flagApp, nil
	}
	if app := os.Getenv("FLYNN_APP"); app != "" {
		flagApp = app
		return app, nil
	}
	if err := readConfig(); err != nil {
		return "", err
	}

	ra, err := appFromGitRemote(remoteFromGitConfig())
	if err != nil {
		return "", err
	}
	serverConf = ra.Server
	flagApp = ra.Name
	return ra.Name, nil
}

func mustApp() string {
	name, err := app()
	if err != nil {
		log.Fatal(err)
	}
	return name
}

func listRec(w io.Writer, a ...interface{}) {
	for i, x := range a {
		fmt.Fprint(w, x)
		if i+1 < len(a) {
			w.Write([]byte{'\t'})
		} else {
			w.Write([]byte{'\n'})
		}
	}
}
<commit_msg>cli: Fix panic<commit_after>package main

import (
	"encoding/base64"
	"errors"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/BurntSushi/toml"
	"github.com/bgentry/pflag"
	"github.com/flynn/flynn-controller/client"
)

type Command struct {
	// args does not include the command name
	Run  func(cmd *Command, args []string, client *controller.Client) error
	Flag pflag.FlagSet

	Usage string // first word is the command name
	Short string // `flynn help` output
	Long  string // `flynn help cmd` output

	NoClient bool
}

func (c *Command) printUsage(errExit bool) {
	if c.Runnable() {
		fmt.Printf("Usage: %s %s\n\n", os.Args[0], c.Usage)
	}
	fmt.Println(strings.Trim(c.Long, "\n"))
	if errExit {
		os.Exit(2)
	}
}

func (c *Command) Name() string {
	name := c.Usage
	i := strings.Index(name, " ")
	if i >= 0 {
		name = name[:i]
	}
	return name
}

func (c *Command) Runnable() bool {
	return c.Run != nil
}

// Running `flynn help` will list commands in this order.
var commands = []*Command{
	cmdServerAdd,
	cmdCreate,
	cmdPs,
	cmdLog,
	cmdScale,
	cmdRun,
	cmdRouteAddHTTP,
	cmdKeys,
	cmdKeyAdd,
	cmdKeyRemove,
	cmdVersion,
}

var (
	flagServer = os.Getenv("FLYNN_SERVER")
	flagApp    string
	flagLong   bool
)

func main() {
	log.SetFlags(0)

	args := os.Args[1:]

	// Run the update command as early as possible to avoid the possibility of
	// installations being stranded without updates due to errors in other code
	if len(args) > 0 && args[0] == cmdUpdate.Name() {
		cmdUpdate.Run(cmdUpdate, args, nil)
		return
	} else if updater != nil {
		defer updater.backgroundRun() // doesn't run if os.Exit is called
	}

	if len(args) >= 2 && "-a" == args[0] {
		flagApp = args[1]
		args = args[2:]

		if err := readConfig(); err != nil {
			log.Fatal(err)
		}

		if ra, err := appFromGitRemote(flagApp); err == nil {
			serverConf = ra.Server
			flagApp = ra.Name
		}
	}

	if len(args) < 1 {
		usage()
	}

	for _, cmd := range commands {
		if cmd.Name() == args[0] && cmd.Run != nil {
			cmd.Flag.Usage = func() {
				cmd.printUsage(false)
			}
			if err := cmd.Flag.Parse(args[1:]); err != nil {
				os.Exit(2)
			}

			var client *controller.Client
			if !cmd.NoClient {
				server, err := server()
				if err != nil {
					log.Fatal(err)
				}
				if server.TLSPin != "" {
					pin, err := base64.StdEncoding.DecodeString(server.TLSPin)
					if err != nil {
						log.Fatalln("error decoding tls pin:", err)
					}
					client, err = controller.NewClientWithPin(server.URL, server.Key, pin)
				} else {
					client, err = controller.NewClient(server.URL, server.Key)
				}
				if err != nil {
					log.Fatal(err)
				}
			}
			if err := cmd.Run(cmd, cmd.Flag.Args(), client); err != nil {
				log.Fatal(err)
			}
			return
		}
	}

	fmt.Fprintf(os.Stderr, "Unknown command: %s\n", args[0])
	usage()
}

type Config struct {
	Servers []*ServerConfig `toml:"server"`
}

type ServerConfig struct {
	Name    string `json:"name"`
	GitHost string `json:"git_host"`
	URL     string `json:"url"`
	Key     string `json:"key"`
	TLSPin  string `json:"tls_pin"`
}

var config *Config
var serverConf *ServerConfig

func configPath() string {
	p := os.Getenv("FLYNNRC")
	if p == "" {
		p = filepath.Join(homedir(), ".flynnrc")
	}
	return p
}

func readConfig() error {
	if config != nil {
		return nil
	}
	conf := &Config{}
	_, err := toml.DecodeFile(configPath(), conf)
	if err != nil && !os.IsNotExist(err) {
		return err
	}
	config = conf
	return nil
}

func homedir() string {
	if runtime.GOOS == "windows" {
		return os.Getenv("%APPDATA%")
	}
	return os.Getenv("HOME")
}

var ErrNoServers = errors.New("no servers configured")

func server() (*ServerConfig, error) {
	if serverConf != nil {
		return serverConf, nil
	}
	if err := readConfig(); err != nil {
		return nil, err
	}
	if len(config.Servers) == 0 {
		return nil, ErrNoServers
	}
	if flagServer == "" {
		serverConf = config.Servers[0]
		return serverConf, nil
	}
	for _, s := range config.Servers {
		if s.Name == flagServer {
			serverConf = s
			return s, nil
		}
	}
	return nil, fmt.Errorf("unknown server %q", flagServer)
}

var appName string

func app() (string, error) {
	if flagApp != "" {
		return flagApp, nil
	}
	if app := os.Getenv("FLYNN_APP"); app != "" {
		flagApp = app
		return app, nil
	}
	if err := readConfig(); err != nil {
		return "", err
	}

	ra, err := appFromGitRemote(remoteFromGitConfig())
	if err != nil {
		return "", err
	}
	serverConf = ra.Server
	flagApp = ra.Name
	return ra.Name, nil
}

func mustApp() string {
	name, err := app()
	if err != nil {
		log.Fatal(err)
	}
	return name
}

func listRec(w io.Writer, a ...interface{}) {
	for i, x := range a {
		fmt.Fprint(w, x)
		if i+1 < len(a) {
			w.Write([]byte{'\t'})
		} else {
			w.Write([]byte{'\n'})
		}
	}
}
<|endoftext|>


<commit_before>package main

import(
  "fmt"
  "os"
  "github.com/codegangsta/cli"
  "github.com/ricallinson/forgery"
  "github.com/ricallinson/stackr"
  "github.com/spacedock-io/registry/db"
  "github.com/spacedock-io/registry/router"
  "github.com/spacedock-io/registry/config"
  "github.com/spacedock-io/registry/models"
  "github.com/spacedock-io/registry/session"
  "github.com/spacedock-io/registry/cloudfiles"
  "github.com/Southern/logger"
  "github.com/Southern/middleware"
)

const VERSION = "0.0.1"

func main() {
  app := cli.NewApp()

  app.Name = "Registry"
  app.Usage = "Run a standalone Docker registry"
  app.Version = "0.0.1"
  app.Flags = []cli.Flag {
    cli.StringFlag{"port, p", "", "Port number"},
    cli.StringFlag{"index, i", "", "Index URL"},
    cli.StringFlag{"env, e", "dev", "Environment"},
    cli.StringFlag{"config, c", "", "Configuration directory"},
  }

  app.Action = func(c *cli.Context) {
    env := c.String("env")
    dir := c.String("config")
    index := c.String("index")

    if len(env) == 0 {
      env = "dev"
    }
    if len(dir) > 0 {
      config.Dir = dir
    }

    config.Global = config.Load(env)
    config.Logger = logger.New()

    if len(index) > 0 {
      config.Global = config.Global.Set("index", index)
    }

    server := f.CreateServer()
    server.Use(func(req *stackr.Request, res *stackr.Response, next func()) {
      config.Logger.Log(fmt.Sprintf("%s %s", req.Method, req.Url))
      next()
    })
    server.Use(middleware.BodyParser)
    server.Use(func (req *stackr.Request, res *stackr.Response, next func()) {
      defer next()

      res.SetHeader("X-Docker-Registry-Version", VERSION)
      res.SetHeader("X-Docker-Registry-Config", "dev")
    })
    server.Use(sx.Middleware("SECRETVERYSECRET"))
    server.Use(f.ErrorHandler())

    port := c.Int("port")
    if port == 0 {
      // Bug(Colton): Not quite sure why port is being picked up as Float64 at
      // the moment. Still looking into this. It may be intended functionality.
      port = int(config.Global.Get("port").Float64())
    }

    db.New(config.Global)
    db.DB.AutoMigrate(&models.Image{})
    db.DB.AutoMigrate(&models.Tag{})
    db.DB.AutoMigrate(&models.Ancestor{})

    cloudfiles.New(config.Global)

    router.Routes(server)
    config.Logger.Log("Registry listening on port " + fmt.Sprint(port))
    server.Listen(port)
  }

  app.Run(os.Args)
}
<commit_msg>models.Ancestor doesn't exist in AutoMigrate<commit_after>package main

import(
  "fmt"
  "os"
  "github.com/codegangsta/cli"
  "github.com/ricallinson/forgery"
  "github.com/ricallinson/stackr"
  "github.com/spacedock-io/registry/db"
  "github.com/spacedock-io/registry/router"
  "github.com/spacedock-io/registry/config"
  "github.com/spacedock-io/registry/models"
  "github.com/spacedock-io/registry/session"
  "github.com/spacedock-io/registry/cloudfiles"
  "github.com/Southern/logger"
  "github.com/Southern/middleware"
)

const VERSION = "0.0.1"

func main() {
  app := cli.NewApp()

  app.Name = "Registry"
  app.Usage = "Run a standalone Docker registry"
  app.Version = "0.0.1"
  app.Flags = []cli.Flag {
    cli.StringFlag{"port, p", "", "Port number"},
    cli.StringFlag{"index, i", "", "Index URL"},
    cli.StringFlag{"env, e", "dev", "Environment"},
    cli.StringFlag{"config, c", "", "Configuration directory"},
  }

  app.Action = func(c *cli.Context) {
    env := c.String("env")
    dir := c.String("config")
    index := c.String("index")

    if len(env) == 0 {
      env = "dev"
    }
    if len(dir) > 0 {
      config.Dir = dir
    }

    config.Global = config.Load(env)
    config.Logger = logger.New()

    if len(index) > 0 {
      config.Global = config.Global.Set("index", index)
    }

    server := f.CreateServer()
    server.Use(func(req *stackr.Request, res *stackr.Response, next func()) {
      config.Logger.Log(fmt.Sprintf("%s %s", req.Method, req.Url))
      next()
    })
    server.Use(middleware.BodyParser)
    server.Use(func (req *stackr.Request, res *stackr.Response, next func()) {
      defer next()

      res.SetHeader("X-Docker-Registry-Version", VERSION)
      res.SetHeader("X-Docker-Registry-Config", "dev")
    })
    server.Use(sx.Middleware("SECRETVERYSECRET"))
    server.Use(f.ErrorHandler())

    port := c.Int("port")
    if port == 0 {
      // Bug(Colton): Not quite sure why port is being picked up as Float64 at
      // the moment. Still looking into this. It may be intended functionality.
      port = int(config.Global.Get("port").Float64())
    }

    db.New(config.Global)
    db.DB.AutoMigrate(&models.Image{})
    db.DB.AutoMigrate(&models.Tag{})
    // db.DB.AutoMigrate(&models.Ancestor{})

    cloudfiles.New(config.Global)

    router.Routes(server)
    config.Logger.Log("Registry listening on port " + fmt.Sprint(port))
    server.Listen(port)
  }

  app.Run(os.Args)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/CenturyLinkLabs/docker-reg-client/registry"
	"github.com/docker/docker/pkg/units"
	"io/ioutil"
	"log"
	"net/url"
	"os"
	"strings"
)

var (
	client      *registry.Client
	registryURL string
)

type imageNode struct {
	id       string
	size     int64
	tags     []string
	children []*imageNode
}

func init() {
	client = registry.NewClient()
}

func getRepos() *registry.SearchResults {
	log.Print("Fetching repos...")
	results, _ := client.Search.Query("", 0, 0)
	log.Printf("%v repo(s) fetched", results.NumResults)
	return results
}

func getTags(name string) registry.TagMap {
	log.Printf("Fetching tags for %s ...", name)
	tags, _ := client.Repository.ListTags(name, registry.NilAuth{})
	log.Printf("%v tags fetched for repo %s", len(tags), name)
	fqTags := make(registry.TagMap)
	for tag, id := range tags {
		fqTags[fqTag(name, tag)] = id
	}
	return fqTags
}

func getAncestry(id string) []string {
	log.Printf("Fetching ancestry for %s ...", id)
	ancestry, _ := client.Image.GetAncestry(id, registry.NilAuth{})
	log.Printf("%v ancestors fetched for tag %s", len(ancestry), id)
	return ancestry
}

func getMetadata(id string) *registry.ImageMetadata {
	log.Printf("Fetching metadata for %s ...", id)
	metadata, _ := client.Image.GetMetadata(id, registry.NilAuth{})
	log.Printf("Metadata fetched for tag %s", id)
	return metadata
}

func fqTag(name string, t string) string {
	canonicalName := strings.TrimPrefix(name, "library/")
	return canonicalName + ":" + t
}

func printTree(root *imageNode, level int, cumsize int64) {
	cumsize = cumsize + root.size
	if len(root.tags) > 0 || len(root.children) > 1 {
		fmt.Printf("%s %s%v %s\n", root.id, strings.Repeat("  ", level), root.tags, units.HumanSize(float64(cumsize)))
		level = level + 1
		cumsize = 0
	}
	for _, child := range root.children {
		printTree(child, level, cumsize)
	}
}

func main() {
	var (
		remaining   int                                  // how many more responses are we waiting from the goroutine?
		throttleCh  = make(chan struct{}, 10)            // helper to limit concurrency
		tagsCh      = make(chan registry.TagMap)         // tags fetcher/consumer channel
		tagsByImage = make(map[string][]string)          // image ids grouped by tags
		ancestryCh  = make(chan []string)                // ancestries fetcher/consumer channel
		images      = make(map[string]*imageNode)        // already processed nodes as we are building up the trees
		metadataCh  = make(chan *registry.ImageMetadata) // metadata fetcher/consumer channel
		roots       []*imageNode                         // roots as we are building up the threes
	)
	if len(registryURL) == 0 {
		registryURL = os.Getenv("REGISTRY_URL")
	}
	if len(registryURL) == 0 {
		log.Fatal("No registry URL provided, use the environment variable REGISTRY_URL to set it")
	}
	if len(os.Getenv("REGISTREE_DEBUG")) > 0 {
		log.SetOutput(os.Stderr)
	} else {
		log.SetOutput(ioutil.Discard)
	}
	client.BaseURL, _ = url.Parse(registryURL + "/v1/")
	// get tags in parallel
	for _, repo := range getRepos().Results {
		remaining = remaining + 1
		go func(name string) {
			throttleCh <- struct{}{}
			tagsCh <- getTags(name)
			<-throttleCh
		}(repo.Name)
	}
	// group them as they are fetched
	for remaining != 0 {
		for tag, id := range <-tagsCh {
			tags, _ := tagsByImage[id]
			tagsByImage[id] = append(tags, tag)
		}
		remaining = remaining - 1
	}
	// get ancestries in parallel
	for imageId := range tagsByImage {
		go func(id string) {
			throttleCh <- struct{}{}
			ancestryCh <- getAncestry(id)
			<-throttleCh
		}(imageId)
	}
	// process them as they arrive until all tagged images have been used
	for len(tagsByImage) != 0 {
		var (
			ancestry     = <-ancestryCh
			previousNode *imageNode
		)
		for _, id := range ancestry {
			if node, ok := images[id]; ok {
				// we already went up the hierarchy from there, just append a new child
				if previousNode != nil {
					node.children = append(node.children, previousNode)
				}
				previousNode = nil
				break
			}
			// retrieve layer metadata async
			remaining = remaining + 1
			go func(id string) {
				throttleCh <- struct{}{}
				metadataCh <- getMetadata(id)
				<-throttleCh
			}(id)
			// register the node in the tree
			node := &imageNode{id: id}
			if tags, ok := tagsByImage[id]; ok {
				node.tags = tags
				// don't wait for that image's ancestry, we already are going up that one
				delete(tagsByImage, id)
			}
			if previousNode != nil {
				// this is not a leaf in the tree, so attach its child
				node.children = []*imageNode{previousNode}
			}
			images[id] = node
			previousNode = node
		}
		if previousNode != nil {
			// the previous loop didn't break out, so the last node considered is a root
			roots = append(roots, previousNode)
		}
	}
	// store metadata about all images as they get back
	for remaining != 0 {
		metadata := <-metadataCh
		images[metadata.ID].size = metadata.Size
		remaining = remaining - 1
	}
	// dump all the trees
	for _, root := range roots {
		printTree(root, 0, 0)
	}

}
<commit_msg>proper synchronization<commit_after>package main

import (
	"fmt"
	"github.com/CenturyLinkLabs/docker-reg-client/registry"
	"github.com/docker/docker/pkg/units"
	"io/ioutil"
	"log"
	"net/url"
	"os"
	"strings"
	"sync"
)

var (
	client      *registry.Client
	registryURL string
)

type imageNode struct {
	id       string
	size     int64
	tags     []string
	children []*imageNode
}

func init() {
	client = registry.NewClient()
}

func getRepos() *registry.SearchResults {
	log.Print("Fetching repos...")
	results, _ := client.Search.Query("", 0, 0)
	log.Printf("%v repo(s) fetched", results.NumResults)
	return results
}

func getTags(name string) registry.TagMap {
	log.Printf("Fetching tags for %s ...", name)
	tags, _ := client.Repository.ListTags(name, registry.NilAuth{})
	log.Printf("%v tags fetched for repo %s", len(tags), name)
	fqTags := make(registry.TagMap)
	for tag, id := range tags {
		fqTags[fqTag(name, tag)] = id
	}
	return fqTags
}

func getAncestry(id string) []string {
	log.Printf("Fetching ancestry for %s ...", id)
	ancestry, _ := client.Image.GetAncestry(id, registry.NilAuth{})
	log.Printf("%v ancestors fetched for tag %s", len(ancestry), id)
	return ancestry
}

func getMetadata(id string) *registry.ImageMetadata {
	log.Printf("Fetching metadata for %s ...", id)
	metadata, _ := client.Image.GetMetadata(id, registry.NilAuth{})
	log.Printf("Metadata fetched for tag %s", id)
	return metadata
}

func fqTag(name string, t string) string {
	canonicalName := strings.TrimPrefix(name, "library/")
	return canonicalName + ":" + t
}

func printTree(root *imageNode, level int, cumsize int64) {
	cumsize = cumsize + root.size
	if len(root.tags) > 0 || len(root.children) > 1 {
		fmt.Printf("%s %s%v %s\n", root.id, strings.Repeat("  ", level), root.tags, units.HumanSize(float64(cumsize)))
		level = level + 1
		cumsize = 0
	}
	for _, child := range root.children {
		printTree(child, level, cumsize)
	}
}

func main() {
	var (
		wg          sync.WaitGroup
		throttleCh  = make(chan struct{}, 10)            // helper to limit concurrency
		tagsCh      = make(chan registry.TagMap)         // tags fetcher/consumer channel
		tagsByImage = make(map[string][]string)          // image ids grouped by tags
		ancestryCh  = make(chan []string)                // ancestries fetcher/consumer channel
		images      = make(map[string]*imageNode)        // already processed nodes as we are building up the trees
		metadataCh  = make(chan *registry.ImageMetadata) // metadata fetcher/consumer channel
		roots       []*imageNode                         // roots as we are building up the threes
	)
	if len(registryURL) == 0 {
		registryURL = os.Getenv("REGISTRY_URL")
	}
	if len(registryURL) == 0 {
		log.Fatal("No registry URL provided, use the environment variable REGISTRY_URL to set it")
	}
	if len(os.Getenv("REGISTREE_DEBUG")) > 0 {
		log.SetOutput(os.Stderr)
	} else {
		log.SetOutput(ioutil.Discard)
	}
	client.BaseURL, _ = url.Parse(registryURL + "/v1/")
	// get tags in parallel
	for _, repo := range getRepos().Results {
		wg.Add(1)
		go func(name string) {
			defer wg.Done()
			throttleCh <- struct{}{}
			tagsCh <- getTags(name)
			<-throttleCh
		}(repo.Name)
	}
	go func() {
		wg.Wait()
		close(tagsCh)
	}()
	for tags, ok := <-tagsCh; ok; tags, ok = <-tagsCh {
		for tag, id := range tags {
			tagsByImage[id] = append(tagsByImage[id], tag)
		}
	}
	// get ancestries in parallel
	log.Printf("Fetching ancestry for %v images...", len(tagsByImage))
	for imageId := range tagsByImage {
		go func(id string) {
			throttleCh <- struct{}{}
			ancestryCh <- getAncestry(id)
			<-throttleCh
		}(imageId)
	}
	// process them as they arrive until all tagged images have been used
	for len(tagsByImage) != 0 {
		var (
			ancestry     = <-ancestryCh
			previousNode *imageNode
		)
		for _, id := range ancestry {
			if node, ok := images[id]; ok {
				// we already went up the hierarchy from there, just append a new child
				if previousNode != nil {
					node.children = append(node.children, previousNode)
				}
				previousNode = nil
				break
			}
			// register the node in the tree
			node := &imageNode{id: id}
			if tags, ok := tagsByImage[id]; ok {
				node.tags = tags
				// don't wait for that image's ancestry, we already are going up that one
				delete(tagsByImage, id)
			}
			if previousNode != nil {
				// this is not a leaf in the tree, so attach its child
				node.children = []*imageNode{previousNode}
			}
			images[id] = node
			previousNode = node
		}
		if previousNode != nil {
			// the previous loop didn't break out, so the last node considered is a root
			roots = append(roots, previousNode)
		}
	}
	// retrieve size of all images
	for id := range images {
		wg.Add(1)
		go func(id string) {
			defer wg.Done()
			throttleCh <- struct{}{}
			metadataCh <- getMetadata(id)
			<-throttleCh
		}(id)
	}
	go func() {
		wg.Wait()
		close(metadataCh)
	}()
	for metadata, ok := <-metadataCh; ok; metadata, ok = <-metadataCh {
		images[metadata.ID].size = metadata.Size
	}
	// dump all the trees
	for _, root := range roots {
		printTree(root, 0, 0)
	}

}
<|endoftext|>


<commit_before>// main.go
package main

import (
	"github.com/jessevdk/go-flags"
	"os"
	"log"
	"strings"
	"bufio"
	"encoding/base64"
	"github.com/beplus/mobile-icons-generator/app/helper/image-helper"
	"fmt"
)

var args struct {
	Filename string `short:"n" long:"file" description:"filename to make assets"`
}

func main() {
	_, err := flags.ParseArgs(&args, os.Args)
	if err != nil {
		log.Fatal("Parsing flags error")
	}

	if args.Filename == "" {
		log.Fatal("No file set use -n or --file to set it")
	}

	// todo windows \
	s := strings.Split(args.Filename, "/")
	filename := s[len(s)-1]
	// prepare json body

	filenameArray := strings.Split(filename, ".")
	name, extension := filenameArray[0], filenameArray[1]

	myImage, err := image_helper.NewMyImageFromBase64(getImageBase64(args.Filename), name, extension)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("Processing icons... It could few seconds...")

	_, err = myImage.Upload("icons", "local", "", "folder")
	if err != nil {
		log.Println(err)
	} else {
		fmt.Println("Icons saved to folder 'icons'.")
	}
}

func getImageBase64(filename string) string {
	imgFile, err := os.Open(filename)
	if err != nil {
		log.Fatal("Open file fail")
	}
	defer imgFile.Close()

	// create a new buffer base on file size
	fInfo, _ := imgFile.Stat()
	var size int64 = fInfo.Size()
	buf := make([]byte, size)

	// read file content into buffer
	fReader := bufio.NewReader(imgFile)
	fReader.Read(buf)

	// convert the buffer bytes to base64 string - use buf.Bytes() for new image
	return base64.StdEncoding.EncodeToString(buf)
}
<commit_msg>output message fix<commit_after>// main.go
package main

import (
	"github.com/jessevdk/go-flags"
	"os"
	"log"
	"strings"
	"bufio"
	"encoding/base64"
	"github.com/beplus/mobile-icons-generator/app/helper/image-helper"
	"fmt"
)

var args struct {
	Filename string `short:"n" long:"file" description:"filename to make assets"`
}

func main() {
	_, err := flags.ParseArgs(&args, os.Args)
	if err != nil {
		log.Fatal("Parsing flags error")
	}

	if args.Filename == "" {
		log.Fatal("No file set use -n or --file to set it")
	}

	// todo windows \
	s := strings.Split(args.Filename, "/")
	filename := s[len(s)-1]
	// prepare json body

	filenameArray := strings.Split(filename, ".")
	name, extension := filenameArray[0], filenameArray[1]

	myImage, err := image_helper.NewMyImageFromBase64(getImageBase64(args.Filename), name, extension)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("Processing icons... It could few seconds...")

	_, err = myImage.Upload("icons", "local", "", "folder")
	if err != nil {
		log.Println(err)
	} else {
		fmt.Println("Icons saved to folder 'AppIcon'.")
	}
}

func getImageBase64(filename string) string {
	imgFile, err := os.Open(filename)
	if err != nil {
		log.Fatal("Open file fail")
	}
	defer imgFile.Close()

	// create a new buffer base on file size
	fInfo, _ := imgFile.Stat()
	var size int64 = fInfo.Size()
	buf := make([]byte, size)

	// read file content into buffer
	fReader := bufio.NewReader(imgFile)
	fReader.Read(buf)

	// convert the buffer bytes to base64 string - use buf.Bytes() for new image
	return base64.StdEncoding.EncodeToString(buf)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"

	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/cloudwatchevents"
)

func main() {
	var apply bool
	var dryrun bool
	var file string

	flag.BoolVar(&apply, "apply", false, "apply to CloudWatch Events")
	flag.BoolVar(&dryrun, "dry-run", false, "dry-run")
	flag.StringVar(&file, "file", "config.yml", "file path to setting yaml")
	flag.StringVar(&file, "f", "config.yml", "file path to setting yaml (shorthand)")
	flag.Parse()

	sess, err := session.NewSession(nil)
	if err != nil {
		fmt.Errorf("Error %v", err)
	}

	cwe := cloudwatchevents.New(sess)
	result, err := cwe.ListRules(nil)

	if err != nil {
		fmt.Println("Error", err)

	} else {
		fmt.Println("Success")
		fmt.Println(result)
	}
}
<commit_msg>Load to structs from config yaml file<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"

	yaml "gopkg.in/yaml.v2"

	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/cloudwatchevents"
)

func main() {
	var apply bool
	var dryrun bool
	var file string

	flag.BoolVar(&apply, "apply", false, "apply to CloudWatch Events")
	flag.BoolVar(&dryrun, "dry-run", false, "dry-run")
	flag.StringVar(&file, "file", "config.yml", "file path to setting yaml")
	flag.StringVar(&file, "f", "config.yml", "file path to setting yaml (shorthand)")
	flag.Parse()

	sess, err := session.NewSession(nil)
	if err != nil {
		fmt.Errorf("Error %v", err)
	}

	rules := Rules{}
	err := loadYaml(file, &rules)
	if err != nil {
		return err
	}
}

func loadYaml(file string, r *Rules) error {

	buf, err := ioutil.ReadFile(file)
	if err != nil {
		return err
	}

	err = yaml.Unmarshal(buf, &r)
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"code.google.com/p/go-uuid/uuid"
	"errors"
	"flag"
	"fmt"
	"github.com/spacemonkeygo/openssl"
	"io"
	"io/ioutil"
	"log"
	"net"
	"os"
	"regexp"
	"time"
)

var xmppClientIdent string = `<stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client' to='%s' version='1.0'>\n`
var xmppServerPreamble string = `<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' id='%s' from='%s' version='1.0' xml:lang='en'><stream:features><starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'></starttls></stream:features>\n`
var xmppClientStarttls string = `<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>\n`
var xmppServerProceed string = `<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>\n`

type PrefixLogger struct {
	Prefix string
}

func (p *PrefixLogger) Write(data []byte) (int, error) {
	log.Println(p.Prefix, string(data))
	return len(data), nil
}

func NewPrefixLogger(prefix string) io.Writer {
	return &PrefixLogger{prefix}
}

var tlsFeatureMatch *regexp.Regexp = regexp.MustCompile(`<starttls xmlns=['"]urn:ietf:params:xml:ns:xmpp-tls`)

func CanStartClientTLS(conn net.Conn) bool {
	conn.SetDeadline(time.Now().Add(15 * time.Second))
	buf := make([]byte, 10240)
	pos := 0
	var err error
	var n int
	for tlsFeatureMatch.Find(buf) == nil {
		if err != nil {
			log.Println(err)
			return false
		}
		if pos > len(buf)-64 {
			return false
		}
		if bytes.Contains(buf, []byte("/stream:features>")) {
			return false
		}
		n, err = conn.Read(buf[pos:])
		pos += n
	}
	conn.SetDeadline(*new(time.Time))
	return true
}

func StartClientTLS(conn net.Conn, key openssl.PrivateKey, cert *openssl.Certificate) (net.Conn, error) {
	if !CanStartClientTLS(conn) {
		return nil, errors.New("Failed to starttls.")
	}
	_, err := conn.Write([]byte(xmppClientStarttls))
	if err != nil {
		return nil, err
	}
	buf := make([]byte, 1024)
	_, err = conn.Read(buf)
	if !bytes.Contains(buf, []byte("<proceed")) {
		return nil, errors.New("Server did not accept starttls.")
	}
	ctx, err := openssl.NewCtx()
	if err != nil {
		return nil, err
	}
	if cert != nil && key != nil {
		ctx.UseCertificate(cert)
		ctx.UsePrivateKey(key)
	}
	conn, err = openssl.Client(conn, ctx)
	if err != nil {
		return nil, err
	}
	return conn, nil
}

func StartServerTLS(conn net.Conn, host string, key openssl.PrivateKey, cert *openssl.Certificate) (net.Conn, error) {
	var err error
	var n int
	guid := uuid.New()
	_, err = conn.Write([]byte(fmt.Sprintf(xmppServerPreamble, guid, host)))
	if err != nil {
		return nil, err
	}
	buf := make([]byte, 1024)
	pos := 0
	for tlsFeatureMatch.Find(buf) == nil {
		if err != nil {
			log.Println(string(buf))
			return nil, err
		}
		if pos > len(buf)-64 {
			return nil, errors.New("Client did not starttls")
		}
		n, err = conn.Read(buf[pos:])
		pos += n
	}
	_, err = conn.Write([]byte(xmppServerProceed))
	if err != nil {
		return nil, err
	}
	ctx, err := openssl.NewCtx()
	if err != nil {
		return nil, err
	}
	ctx.UseCertificate(cert)
	ctx.UsePrivateKey(key)
	conn, err = openssl.Server(conn, ctx)
	if err != nil {
		return nil, err
	}
	return conn, nil
}

func main() {
	bind := flag.String("bind", "127.0.0.1:5222", "local host:port to serve")
	host := flag.String("host", "", "override xmpp hostname sent in protocol")
	certPath := flag.String("cert", "", "path to SSL cert to serve to connecting clients")
	keyPath := flag.String("key", "", "path to SSL private key")
	verbose := flag.Bool("verbose", false, "verbose output")
	clientTls := flag.Bool("clientTls", false, "use TLS for connecting client (implicit if key/cert are specified)")

	clientCertPath := flag.String("clientCert", "", "path to SSL client cert")
	clientKeyPath := flag.String("clientKey", "", "path to SSL client key")
	flag.Parse()

	args := flag.Args()
	if len(args) < 1 {
		flag.Usage()
		fmt.Fprintf(os.Stderr, "If no SSL certificate is provided, a self-signed one will be generated.\n")
		fmt.Fprintf(os.Stderr, "Example usage:\n  %s [options] <target server>\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "\nError: <target server> required\n")
		os.Exit(1)
	}
	remote := args[0]
	remoteHost, _, err := net.SplitHostPort(remote)
	if *host != "" {
		remoteHost = *host
	}
	if err != nil {
		log.Fatal(err)
	}

	var clientCert *openssl.Certificate
	var clientKey openssl.PrivateKey
	if *clientCertPath != "" && *clientKeyPath != "" {
		log.Println("Using client certificate:", *clientCertPath)
		log.Println("                with key:", *clientKeyPath)
		pem, err := ioutil.ReadFile(*clientCertPath)
		if err != nil {
			log.Fatal(err)
		}
		clientCert, err = openssl.LoadCertificateFromPEM(pem)
		if err != nil {
			log.Fatal(err)
		}
		pem, err = ioutil.ReadFile(*clientKeyPath)
		if err != nil {
			log.Fatal(err)
		}
		clientKey, err = openssl.LoadPrivateKeyFromPEM(pem)
		if err != nil {
			log.Fatal(err)
		}
	}

	var cert *openssl.Certificate
	var key openssl.PrivateKey
	if *certPath != "" && *keyPath != "" {
		*clientTls = true
		log.Println("Using certificate:", *certPath)
		log.Println("Using key:        ", *keyPath)
		pem, err := ioutil.ReadFile(*certPath)
		if err != nil {
			log.Fatal(err)
		}
		cert, err = openssl.LoadCertificateFromPEM(pem)
		if err != nil {
			log.Fatal(err)
		}
		pem, err = ioutil.ReadFile(*keyPath)
		if err != nil {
			log.Fatal(err)
		}
		key, err = openssl.LoadPrivateKeyFromPEM(pem)
		if err != nil {
			log.Fatal(err)
		}
	} else if *clientTls {
		log.Println("Generating self-signed certificate...")
		key, err = openssl.GenerateRSAKey(2048)
		if err != nil {
			log.Fatal(err)
		}
		info := &openssl.CertificateInfo{
			Serial:       1,
			Issued:       0,
			Expires:      24 * time.Hour,
			Country:      "US",
			Organization: "xmppstrip",
			CommonName:   remoteHost,
		}
		cert, err = openssl.NewCertificate(info, key)
		if err != nil {
			log.Fatal(err)
		}
		err = cert.Sign(key, openssl.EVP_SHA256)
		if err != nil {
			log.Fatal(err)
		}
	}

	log.Printf("Binding %s to %s\n", remote, *bind)
	ln, err := net.Listen("tcp", *bind)
	if err != nil {
		log.Fatal(err)
	}
	for {
		conn, err := ln.Accept()
		if err != nil {
			log.Fatal(err)
		}
		log.Println("Connection from:", conn.RemoteAddr())
		go func(client net.Conn) {
			var err error
			if *clientTls {
				client, err = StartServerTLS(client, remoteHost, key, cert)
				if err != nil {
					log.Println(err)
					return
				}
			}
			remoteConn, err := net.Dial("tcp", remote)
			if err != nil {
				log.Println(err)
				return
			}
			_, err = remoteConn.Write([]byte(fmt.Sprintf(xmppClientIdent, remoteHost)))
			if err != nil {
				log.Println(err)
				return
			}
			remoteConn, err = StartClientTLS(remoteConn, clientKey, clientCert)
			if err != nil {
				log.Println(err)
				return
			}
			toRemote := remoteConn.(io.Writer)
			toClient := client.(io.Writer)
			if *verbose {
				toRemote = io.MultiWriter(NewPrefixLogger("->"), remoteConn)
				toClient = io.MultiWriter(NewPrefixLogger("<-"), client)
			}
			go io.Copy(toRemote, client)
			go io.Copy(toClient, remoteConn)
		}(conn)
	}
}
<commit_msg>rename clientTls to striptls<commit_after>package main

import (
	"bytes"
	"code.google.com/p/go-uuid/uuid"
	"errors"
	"flag"
	"fmt"
	"github.com/spacemonkeygo/openssl"
	"io"
	"io/ioutil"
	"log"
	"net"
	"os"
	"regexp"
	"time"
)

var xmppClientIdent string = `<stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client' to='%s' version='1.0'>\n`
var xmppServerPreamble string = `<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' id='%s' from='%s' version='1.0' xml:lang='en'><stream:features><starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'></starttls></stream:features>\n`
var xmppClientStarttls string = `<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>\n`
var xmppServerProceed string = `<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>\n`

type PrefixLogger struct {
	Prefix string
}

func (p *PrefixLogger) Write(data []byte) (int, error) {
	log.Println(p.Prefix, string(data))
	return len(data), nil
}

func NewPrefixLogger(prefix string) io.Writer {
	return &PrefixLogger{prefix}
}

var tlsFeatureMatch *regexp.Regexp = regexp.MustCompile(`<starttls xmlns=['"]urn:ietf:params:xml:ns:xmpp-tls`)

func CanStartClientTLS(conn net.Conn) bool {
	conn.SetDeadline(time.Now().Add(15 * time.Second))
	buf := make([]byte, 10240)
	pos := 0
	var err error
	var n int
	for tlsFeatureMatch.Find(buf) == nil {
		if err != nil {
			log.Println(err)
			return false
		}
		if pos > len(buf)-64 {
			return false
		}
		if bytes.Contains(buf, []byte("/stream:features>")) {
			return false
		}
		n, err = conn.Read(buf[pos:])
		pos += n
	}
	conn.SetDeadline(*new(time.Time))
	return true
}

func StartClientTLS(conn net.Conn, key openssl.PrivateKey, cert *openssl.Certificate) (net.Conn, error) {
	if !CanStartClientTLS(conn) {
		return nil, errors.New("Failed to starttls.")
	}
	_, err := conn.Write([]byte(xmppClientStarttls))
	if err != nil {
		return nil, err
	}
	buf := make([]byte, 1024)
	_, err = conn.Read(buf)
	if !bytes.Contains(buf, []byte("<proceed")) {
		return nil, errors.New("Server did not accept starttls.")
	}
	ctx, err := openssl.NewCtx()
	if err != nil {
		return nil, err
	}
	if cert != nil && key != nil {
		ctx.UseCertificate(cert)
		ctx.UsePrivateKey(key)
	}
	conn, err = openssl.Client(conn, ctx)
	if err != nil {
		return nil, err
	}
	return conn, nil
}

func StartServerTLS(conn net.Conn, host string, key openssl.PrivateKey, cert *openssl.Certificate) (net.Conn, error) {
	var err error
	var n int
	guid := uuid.New()
	_, err = conn.Write([]byte(fmt.Sprintf(xmppServerPreamble, guid, host)))
	if err != nil {
		return nil, err
	}
	buf := make([]byte, 1024)
	pos := 0
	for tlsFeatureMatch.Find(buf) == nil {
		if err != nil {
			log.Println(string(buf))
			return nil, err
		}
		if pos > len(buf)-64 {
			return nil, errors.New("Client did not starttls")
		}
		n, err = conn.Read(buf[pos:])
		pos += n
	}
	_, err = conn.Write([]byte(xmppServerProceed))
	if err != nil {
		return nil, err
	}
	ctx, err := openssl.NewCtx()
	if err != nil {
		return nil, err
	}
	ctx.UseCertificate(cert)
	ctx.UsePrivateKey(key)
	conn, err = openssl.Server(conn, ctx)
	if err != nil {
		return nil, err
	}
	return conn, nil
}

func main() {
	bind := flag.String("bind", "127.0.0.1:5222", "local host:port to serve")
	host := flag.String("host", "", "override xmpp hostname sent in protocol")
	certPath := flag.String("cert", "", "path to SSL cert to serve to connecting clients")
	keyPath := flag.String("key", "", "path to SSL private key")
	verbose := flag.Bool("verbose", false, "verbose output")
	striptls := flag.Bool("striptls", true, "strip tls from client-side (overriden if key/cert are specified)")

	clientCertPath := flag.String("clientCert", "", "path to SSL client cert")
	clientKeyPath := flag.String("clientKey", "", "path to SSL client key")
	flag.Parse()

	args := flag.Args()
	if len(args) < 1 {
		flag.Usage()
		fmt.Fprintf(os.Stderr, "If no SSL certificate is provided, a self-signed one will be generated.\n")
		fmt.Fprintf(os.Stderr, "Example usage:\n  %s [options] <target server>\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "\nError: <target server> required\n")
		os.Exit(1)
	}
	remote := args[0]
	remoteHost, _, err := net.SplitHostPort(remote)
	if *host != "" {
		remoteHost = *host
	}
	if err != nil {
		log.Fatal(err)
	}

	var clientCert *openssl.Certificate
	var clientKey openssl.PrivateKey
	if *clientCertPath != "" && *clientKeyPath != "" {
		log.Println("Using client certificate:", *clientCertPath)
		log.Println("                with key:", *clientKeyPath)
		pem, err := ioutil.ReadFile(*clientCertPath)
		if err != nil {
			log.Fatal(err)
		}
		clientCert, err = openssl.LoadCertificateFromPEM(pem)
		if err != nil {
			log.Fatal(err)
		}
		pem, err = ioutil.ReadFile(*clientKeyPath)
		if err != nil {
			log.Fatal(err)
		}
		clientKey, err = openssl.LoadPrivateKeyFromPEM(pem)
		if err != nil {
			log.Fatal(err)
		}
	}

	var cert *openssl.Certificate
	var key openssl.PrivateKey
	if *certPath != "" && *keyPath != "" {
		*striptls = false
		log.Println("Using certificate:", *certPath)
		log.Println("Using key:        ", *keyPath)
		pem, err := ioutil.ReadFile(*certPath)
		if err != nil {
			log.Fatal(err)
		}
		cert, err = openssl.LoadCertificateFromPEM(pem)
		if err != nil {
			log.Fatal(err)
		}
		pem, err = ioutil.ReadFile(*keyPath)
		if err != nil {
			log.Fatal(err)
		}
		key, err = openssl.LoadPrivateKeyFromPEM(pem)
		if err != nil {
			log.Fatal(err)
		}
	} else if !*striptls {
		log.Println("Generating self-signed certificate...")
		key, err = openssl.GenerateRSAKey(2048)
		if err != nil {
			log.Fatal(err)
		}
		info := &openssl.CertificateInfo{
			Serial:       1,
			Issued:       0,
			Expires:      24 * time.Hour,
			Country:      "US",
			Organization: "xmppstrip",
			CommonName:   remoteHost,
		}
		cert, err = openssl.NewCertificate(info, key)
		if err != nil {
			log.Fatal(err)
		}
		err = cert.Sign(key, openssl.EVP_SHA256)
		if err != nil {
			log.Fatal(err)
		}
	}

	log.Printf("Binding %s to %s\n", remote, *bind)
	ln, err := net.Listen("tcp", *bind)
	if err != nil {
		log.Fatal(err)
	}
	for {
		conn, err := ln.Accept()
		if err != nil {
			log.Fatal(err)
		}
		log.Println("Connection from:", conn.RemoteAddr())
		go func(client net.Conn) {
			var err error
			if !*striptls {
				client, err = StartServerTLS(client, remoteHost, key, cert)
				if err != nil {
					log.Println(err)
					return
				}
			}
			remoteConn, err := net.Dial("tcp", remote)
			if err != nil {
				log.Println(err)
				return
			}
			_, err = remoteConn.Write([]byte(fmt.Sprintf(xmppClientIdent, remoteHost)))
			if err != nil {
				log.Println(err)
				return
			}
			remoteConn, err = StartClientTLS(remoteConn, clientKey, clientCert)
			if err != nil {
				log.Println(err)
				return
			}
			toRemote := remoteConn.(io.Writer)
			toClient := client.(io.Writer)
			if *verbose {
				toRemote = io.MultiWriter(NewPrefixLogger("->"), remoteConn)
				toClient = io.MultiWriter(NewPrefixLogger("<-"), client)
			}
			go io.Copy(toRemote, client)
			go io.Copy(toClient, remoteConn)
		}(conn)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"log"
	"os"
	"time"

	"github.com/gogo/protobuf/proto"

	//log "github.com/golang/glog"
	mesos "github.com/mesos/mesos-go/mesosproto"
	util "github.com/mesos/mesos-go/mesosutil"
	sched "github.com/mesos/mesos-go/scheduler"

	. "github.com/byxorna/moroccron/scheduler"
)

const (
	VERSION = "0.0.0"
)

var (
	master               = flag.String("master", "127.0.0.1:5050", "Master address <ip:port>")
	DOCKER_IMAGE_DEFAULT = "debian:latest"
)

func init() {
	flag.Parse()
}

func main() {

	// Executor
	log.Println("Creating executor information")
	exec := prepareExecutorInfo()
	log.Printf("Created executor info %+v\n", exec)

	// create a channel where we send jobs
	ch := make(chan string, 10)
	ticker := time.Tick(time.Second * 10)
	go func() {
		for {
			x := <-ticker
			log.Printf("Tick!")
			ch <- x.String()
		}
	}()

	// create our scheduler
	log.Println("Creating scheduler")
	scheduler := NewScheduler(exec, ch)
	log.Printf("Created scheduler %+v\n", scheduler)

	// Framework
	log.Println("Creating framework info")
	fwinfo := &mesos.FrameworkInfo{
		User: proto.String(""), // Mesos-go will fill in user.
		Name: proto.String("moroccron-" + VERSION),
	}
	log.Printf("Created fwinfo %+v\n", fwinfo)

	// Scheduler Driver
	log.Println("Creating scheduler driver config")
	config := sched.DriverConfig{
		Scheduler:  scheduler,
		Framework:  fwinfo,
		Master:     *master,
		Credential: (*mesos.Credential)(nil),
	}
	log.Printf("Created driver config %+v\n", config)

	log.Println("Creating new scheduler driver from config")
	driver, err := sched.NewMesosSchedulerDriver(config)

	if err != nil {
		log.Fatalf("Unable to create a SchedulerDriver: %v\n", err.Error())
		os.Exit(3)
	}
	log.Printf("Created scheduler driver %+v\n", driver)

	log.Println("Starting scheduler driver")
	if stat, err := driver.Run(); err != nil {
		log.Fatalf("Framework stopped with status %s and error: %s\n", stat.String(), err.Error())
		os.Exit(4)
	}
}

func prepareExecutorInfo() *mesos.ExecutorInfo {
	// this specifies how the executor will launch the task and identify itsself
	// i.e. command, args, etc. to the container
	return &mesos.ExecutorInfo{
		ExecutorId: util.NewExecutorID("default"),
		Name:       proto.String("Moroccron Executor"),
		Source:     proto.String("moroccron"),
		Container: &mesos.ContainerInfo{
			Type:     mesos.ContainerInfo_DOCKER.Enum(),
			Volumes:  nil,
			Hostname: nil,
			Docker: &mesos.ContainerInfo_DockerInfo{
				Image: &DOCKER_IMAGE_DEFAULT,
			},
		},
		Command: &mesos.CommandInfo{
			Shell: proto.Bool(true),
			Value: proto.String("/bin/date ; /bin/ls ; /bin/hostname ; cat /etc/debian_version"),
			//Uris: CommandInfo_URI{}
			//Value: string binary
			//Arguments: []string args to value
		},
	}
}
<commit_msg>take some time when running task<commit_after>package main

import (
	"flag"
	"log"
	"os"
	"time"

	"github.com/gogo/protobuf/proto"

	//log "github.com/golang/glog"
	mesos "github.com/mesos/mesos-go/mesosproto"
	util "github.com/mesos/mesos-go/mesosutil"
	sched "github.com/mesos/mesos-go/scheduler"

	. "github.com/byxorna/moroccron/scheduler"
)

const (
	VERSION = "0.0.0"
)

var (
	master               = flag.String("master", "127.0.0.1:5050", "Master address <ip:port>")
	DOCKER_IMAGE_DEFAULT = "debian:latest"
)

func init() {
	flag.Parse()
}

func main() {

	// Executor
	log.Println("Creating executor information")
	exec := prepareExecutorInfo()
	log.Printf("Created executor info %+v\n", exec)

	// create a channel where we send jobs
	ch := make(chan string, 10)
	ticker := time.Tick(time.Second * 10)
	go func() {
		for {
			x := <-ticker
			log.Printf("Tick!")
			ch <- x.String()
		}
	}()

	// create our scheduler
	log.Println("Creating scheduler")
	scheduler := NewScheduler(exec, ch)
	log.Printf("Created scheduler %+v\n", scheduler)

	// Framework
	log.Println("Creating framework info")
	fwinfo := &mesos.FrameworkInfo{
		User: proto.String(""), // Mesos-go will fill in user.
		Name: proto.String("moroccron-" + VERSION),
	}
	log.Printf("Created fwinfo %+v\n", fwinfo)

	// Scheduler Driver
	log.Println("Creating scheduler driver config")
	config := sched.DriverConfig{
		Scheduler:  scheduler,
		Framework:  fwinfo,
		Master:     *master,
		Credential: (*mesos.Credential)(nil),
	}
	log.Printf("Created driver config %+v\n", config)

	log.Println("Creating new scheduler driver from config")
	driver, err := sched.NewMesosSchedulerDriver(config)

	if err != nil {
		log.Fatalf("Unable to create a SchedulerDriver: %v\n", err.Error())
		os.Exit(3)
	}
	log.Printf("Created scheduler driver %+v\n", driver)

	log.Println("Starting scheduler driver")
	if stat, err := driver.Run(); err != nil {
		log.Fatalf("Framework stopped with status %s and error: %s\n", stat.String(), err.Error())
		os.Exit(4)
	}
}

func prepareExecutorInfo() *mesos.ExecutorInfo {
	// this specifies how the executor will launch the task and identify itsself
	// i.e. command, args, etc. to the container
	return &mesos.ExecutorInfo{
		ExecutorId: util.NewExecutorID("default"),
		Name:       proto.String("Moroccron Executor"),
		Source:     proto.String("moroccron"),
		Container: &mesos.ContainerInfo{
			Type:     mesos.ContainerInfo_DOCKER.Enum(),
			Volumes:  nil,
			Hostname: nil,
			Docker: &mesos.ContainerInfo_DockerInfo{
				Image: &DOCKER_IMAGE_DEFAULT,
			},
		},
		Command: &mesos.CommandInfo{
			Shell: proto.Bool(true),
			Value: proto.String("set -x ; /bin/date ; /bin/hostname ; cat /etc/debian_version ; sleep 20 ; echo done"),
			//Uris: CommandInfo_URI{}
			//Value: string binary
			//Arguments: []string args to value
		},
	}
}
<|endoftext|>


<commit_before>package main

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

	"github.com/dtan4/ct2stimer/crontab"
	"github.com/dtan4/ct2stimer/systemd"
	flag "github.com/spf13/pflag"
)

var opts = struct {
	after    string
	filename string
	outdir   string
	reload   bool
}{}

func parseArgs(args []string) error {
	f := flag.NewFlagSet("ct2stimer", flag.ExitOnError)

	f.StringVar(&opts.filename, "after", "", "unit dependencies (After=)")
	f.StringVarP(&opts.filename, "file", "f", "", "crontab file")
	f.StringVarP(&opts.outdir, "outdir", "o", systemd.DefaultUnitsDirectory, "directory to save systemd files")
	f.BoolVar(&opts.reload, "reload", false, "reload & start genreated timers")

	f.Parse(args)

	if opts.filename == "" {
		return fmt.Errorf("Please specify crontab file.")
	}

	if opts.outdir == "" {
		return fmt.Errorf("Please specify directory to save systemd files.")
	}

	return nil
}

func reloadSystemd(timers []string) error {
	conn, err := systemd.NewConn()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	defer conn.Close()

	client := systemd.NewClient(conn)

	if err := client.Reload(); err != nil {
		return err
	}

	for _, timerUnit := range timers {
		if err := client.StartUnit(timerUnit); err != nil {
			return err
		}
	}

	return nil
}

func main() {
	if err := parseArgs(os.Args[1:]); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	body, err := ioutil.ReadFile(opts.filename)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	schedules, err := crontab.Parse(string(body))
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	timers := []string{}

	for _, schedule := range schedules {
		calendar, err := schedule.ConvertToSystemdCalendar()
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}

		name := "cron-" + schedule.SHA256Sum()[0:12]

		service, err := systemd.GenerateService(name, schedule.Command, opts.after)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}

		servicePath := filepath.Join(opts.outdir, name+".service")
		if ioutil.WriteFile(servicePath, []byte(service), 0644); err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}

		timer, err := systemd.GenerateTimer(name, calendar)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}

		timerPath := filepath.Join(opts.outdir, name+".timer")
		if ioutil.WriteFile(timerPath, []byte(timer), 0644); err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}

		timers = append(timers, name+".timer")
	}

	if opts.reload {
		if err := reloadSystemd(timers); err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}
	}
}
<commit_msg>Catch file read / write error<commit_after>package main

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

	"github.com/dtan4/ct2stimer/crontab"
	"github.com/dtan4/ct2stimer/systemd"
	flag "github.com/spf13/pflag"
)

var opts = struct {
	after    string
	filename string
	outdir   string
	reload   bool
}{}

func parseArgs(args []string) error {
	f := flag.NewFlagSet("ct2stimer", flag.ExitOnError)

	f.StringVar(&opts.filename, "after", "", "unit dependencies (After=)")
	f.StringVarP(&opts.filename, "file", "f", "", "crontab file")
	f.StringVarP(&opts.outdir, "outdir", "o", systemd.DefaultUnitsDirectory, "directory to save systemd files")
	f.BoolVar(&opts.reload, "reload", false, "reload & start genreated timers")

	f.Parse(args)

	if opts.filename == "" {
		return fmt.Errorf("Please specify crontab file.")
	}

	if opts.outdir == "" {
		return fmt.Errorf("Please specify directory to save systemd files.")
	}

	return nil
}

func reloadSystemd(timers []string) error {
	conn, err := systemd.NewConn()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	defer conn.Close()

	client := systemd.NewClient(conn)

	if err := client.Reload(); err != nil {
		return err
	}

	for _, timerUnit := range timers {
		if err := client.StartUnit(timerUnit); err != nil {
			return err
		}
	}

	return nil
}

func main() {
	if err := parseArgs(os.Args[1:]); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	body, err := ioutil.ReadFile(opts.filename)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	schedules, err := crontab.Parse(string(body))
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	timers := []string{}

	for _, schedule := range schedules {
		calendar, err := schedule.ConvertToSystemdCalendar()
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}

		name := "cron-" + schedule.SHA256Sum()[0:12]

		service, err := systemd.GenerateService(name, schedule.Command, opts.after)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}

		servicePath := filepath.Join(opts.outdir, name+".service")
		if err := ioutil.WriteFile(servicePath, []byte(service), 0644); err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}

		timer, err := systemd.GenerateTimer(name, calendar)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}

		timerPath := filepath.Join(opts.outdir, name+".timer")
		if err := ioutil.WriteFile(timerPath, []byte(timer), 0644); err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}

		timers = append(timers, name+".timer")
	}

	if opts.reload {
		if err := reloadSystemd(timers); err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/go-chi/chi"
	"github.com/go-chi/chi/middleware"
	"github.com/reportportal/commons-go/commons"
	"github.com/reportportal/commons-go/conf"
	"github.com/reportportal/commons-go/server"
	"github.com/unrolled/secure"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
)

func main() {

	currDir, e := os.Getwd()
	if nil != e {
		log.Fatalf("Cannot get workdir: %s", e.Error())
	}

	cfg := conf.EmptyConfig()

	rpConf := struct {
		Cfg         *conf.ServerConfig
		StaticsPath string `env:"RP_STATICS_PATH"`
	}{
		Cfg:         cfg,
		StaticsPath: currDir,
	}

	err := conf.LoadConfig(&rpConf)
	if nil != err {
		log.Fatalf("Cannot log app config")
	}

	info := commons.GetBuildInfo()
	info.Name = "Service UI"

	srv := server.New(rpConf.Cfg, info)
	srv.WithRouter(func(router *chi.Mux) {

		//apply compression
		router.Use(middleware.DefaultCompress)
		router.Use(middleware.Logger)

		//content security policy
		csp := map[string][]string{
			"default-src": {"'self'", "data:", "'unsafe-inline'", "*.uservoice.com"},
			"script-src": {
				"'self'",
				"'unsafe-inline'",
				"'unsafe-eval'",
				"status.reportportal.io",
				"www.google-analytics.com",
				"stats.g.doubleclick.net",
				"*.saucelabs.com",
				"*.epam.com",
				"*.uservoice.com",
				"*.rawgit.com",
			},
			"worker-src":     {"'self'", "blob:"},
			"font-src":       {"'self'", "data:", "fonts.googleapis.com", "fonts.gstatic.com", "*.rawgit.com"},
			"style-src-elem": {"'self'", "data:", "'unsafe-inline'", "*.googleapis.com", "*.rawgit.com"},
			"media-src":      {"'self'", "*.saucelabs.com"},
			"img-src":        {"*", "'self'", "data:", "blob:"},
			"object-src":     {"'self'"},
		}

		//apply content security policies
		router.Use(func(next http.Handler) http.Handler {
			return secure.New(secure.Options{
				ContentTypeNosniff:    true,
				BrowserXssFilter:      true,
				ContentSecurityPolicy: buildCSP(csp),
				STSSeconds:            315360000,
				STSIncludeSubdomains:  true,
				STSPreload:            true,
			}).Handler(next)
		})

		err := os.Chdir(rpConf.StaticsPath)
		if nil != err {
			log.Fatalf("Dir %s not found", rpConf.StaticsPath)
		}

		router.Handle("/*", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			//trim query params
			ext := filepath.Ext(trimQuery(r.URL.String(), "?"))

			// never cache html
			if "/" == r.URL.String() || ".html" == ext {
				w.Header().Add("Cache-Control", "no-cache")
			}

			http.FileServer(http.Dir(rpConf.StaticsPath)).ServeHTTP(&redirectingRW{ResponseWriter: w, Request: r}, r)
		}))

	})

	srv.StartServer()

}

func trimQuery(s string, sep string) string {
	sepIndex := strings.Index(s, sep)
	if -1 != sepIndex {
		return s[:sepIndex]
	}
	return s
}

func buildCSP(csp map[string][]string) string {
	var instr []string
	for k, v := range csp {
		instr = append(instr, k+" "+strings.Join(v, " "))
	}
	return strings.Join(instr, "; ")

}

type redirectingRW struct {
	*http.Request
	http.ResponseWriter
	ignore bool
}

func (hrw *redirectingRW) Header() http.Header {
	return hrw.ResponseWriter.Header()
}

func (hrw *redirectingRW) WriteHeader(status int) {
	if status == 404 {
		hrw.ignore = true
		http.Redirect(hrw.ResponseWriter, hrw.Request, "/ui/#notfound", http.StatusTemporaryRedirect)
	} else {
		hrw.ResponseWriter.WriteHeader(status)
	}

}

func (hrw *redirectingRW) Write(p []byte) (int, error) {
	if hrw.ignore {
		return len(p), nil
	}
	return hrw.ResponseWriter.Write(p)
}
<commit_msg>fix main go issue<commit_after>package main

import (
	"github.com/go-chi/chi"
	"github.com/go-chi/chi/middleware"
	"github.com/reportportal/commons-go/commons"
	"github.com/reportportal/commons-go/conf"
	"github.com/reportportal/commons-go/server"
	"github.com/unrolled/secure"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
)

func main() {
	currDir, e := os.Getwd()
	if nil != e {
		log.Fatalf("Cannot get workdir: %s", e.Error())
	}
	cfg := conf.EmptyConfig()
	rpConf := struct {
		Cfg         *conf.ServerConfig
		StaticsPath string `env:"RP_STATICS_PATH"`
	}{
		Cfg:         cfg,
		StaticsPath: currDir,
	}
	err := conf.LoadConfig(&rpConf)
	if nil != err {
		log.Fatalf("Cannot log app config")
	}
	info := commons.GetBuildInfo()
	info.Name = "Service UI"
	srv := server.New(rpConf.Cfg, info)
	configureRouter(srv, rpConf)
	srv.StartServer()
}

func configureRouter(srv *server.RpServer, rpConf struct {
	Cfg         *conf.ServerConfig
	StaticsPath string `env:"RP_STATICS_PATH"`
}) {
	srv.WithRouter(func(router *chi.Mux) {
		//apply compression
		router.Use(middleware.DefaultCompress)
		router.Use(middleware.Logger)
		//content security policy
		csp := map[string][]string{
			"default-src": {"'self'", "data:", "'unsafe-inline'", "*.uservoice.com"},
			"script-src": {
				"'self'",
				"'unsafe-inline'",
				"'unsafe-eval'",
				"status.reportportal.io",
				"www.google-analytics.com",
				"stats.g.doubleclick.net",
				"*.saucelabs.com",
				"*.epam.com",
				"*.uservoice.com",
				"*.rawgit.com",
			},
			"worker-src":     {"'self'", "blob:"},
			"font-src":       {"'self'", "data:", "fonts.googleapis.com", "fonts.gstatic.com", "*.rawgit.com"},
			"style-src-elem": {"'self'", "data:", "'unsafe-inline'", "*.googleapis.com", "*.rawgit.com"},
			"media-src":      {"'self'", "*.saucelabs.com"},
			"img-src":        {"*", "'self'", "data:", "blob:"},
			"object-src":     {"'self'"},
		}
		//apply content security policies
		router.Use(func(next http.Handler) http.Handler {
			return secure.New(secure.Options{
				ContentTypeNosniff:    true,
				BrowserXssFilter:      true,
				ContentSecurityPolicy: buildCSP(csp),
				STSSeconds:            315360000,
				STSIncludeSubdomains:  true,
				STSPreload:            true,
			}).Handler(next)
		})
		err := os.Chdir(rpConf.StaticsPath)
		if nil != err {
			log.Fatalf("Dir %s not found", rpConf.StaticsPath)
		}
		router.Handle("/*", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			//trim query params
			ext := filepath.Ext(trimQuery(r.URL.String(), "?"))
			// never cache html
			if "/" == r.URL.String() || ".html" == ext {
				w.Header().Add("Cache-Control", "no-cache")
			}
			http.FileServer(http.Dir(rpConf.StaticsPath)).ServeHTTP(&redirectingRW{ResponseWriter: w, Request: r}, r)
		}))
	})
}

func trimQuery(s string, sep string) string {
	sepIndex := strings.Index(s, sep)
	if -1 != sepIndex {
		return s[:sepIndex]
	}
	return s
}

func buildCSP(csp map[string][]string) string {
	var instr []string
	for k, v := range csp {
		instr = append(instr, k+" "+strings.Join(v, " "))
	}
	return strings.Join(instr, "; ")

}

type redirectingRW struct {
	*http.Request
	http.ResponseWriter
	ignore bool
}

func (hrw *redirectingRW) Header() http.Header {
	return hrw.ResponseWriter.Header()
}

func (hrw *redirectingRW) WriteHeader(status int) {
	if status == 404 {
		hrw.ignore = true
		http.Redirect(hrw.ResponseWriter, hrw.Request, "/ui/#notfound", http.StatusTemporaryRedirect)
	} else {
		hrw.ResponseWriter.WriteHeader(status)
	}

}

func (hrw *redirectingRW) Write(p []byte) (int, error) {
	if hrw.ignore {
		return len(p), nil
	}
	return hrw.ResponseWriter.Write(p)
}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"flag"
	"strconv"

	"github.com/golang/glog"

	"github.com/ObjectIsAdvantag/answering-machine/service"
)

const version = "0.1.draft"

func main() {
	var showVersion bool
	var port string
	flag.StringVar(&port, "port", "8080", "ip port of the service, defaults to 8080")
	flag.BoolVar(&showVersion, "version", false, "display version")

	flag.Parse()

	if showVersion {
		glog.Infof("SmartProxy version %s\n", version)
		return
	}

	if _, err := strconv.Atoi(port); err != nil {
		glog.Errorf("Invalid port: %s (%s)\n", port, err)
	}

	// [TODO] Initialize from an env variable
	var apiKey="REPLACE ME"

	glog.Infof("Starting Answering Machine, version: %s\n", version)

	if err := service.Run(apiKey, port, version); err != nil {
		glog.Errorf("Service exited with error: %s\n", err)
		glog.Flush()
		os.Exit(255)
		return
	}

	glog.Info("Service exited gracefully\n")
	glog.Flush()
}
<commit_msg>version updated : v0.1<commit_after>package main

import (
	"os"
	"flag"
	"strconv"

	"github.com/golang/glog"

	"github.com/ObjectIsAdvantag/answering-machine/service"
)

const version = "v0.1"

func main() {
	var showVersion bool
	var port string
	flag.StringVar(&port, "port", "8080", "ip port of the service, defaults to 8080")
	flag.BoolVar(&showVersion, "version", false, "display version")

	flag.Parse()

	if showVersion {
		glog.Infof("SmartProxy version %s\n", version)
		return
	}

	if _, err := strconv.Atoi(port); err != nil {
		glog.Errorf("Invalid port: %s (%s)\n", port, err)
	}

	// [TODO] Initialize from an env variable
	var apiKey="REPLACE ME"

	glog.Infof("Starting Answering Machine, version: %s\n", version)

	if err := service.Run(apiKey, port, version); err != nil {
		glog.Errorf("Service exited with error: %s\n", err)
		glog.Flush()
		os.Exit(255)
		return
	}

	glog.Info("Service exited gracefully\n")
	glog.Flush()
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"github.com/codegangsta/cli"
	"github.com/nfnt/resize"
	"image/png"
	"log"
	"os"
	"strconv"
	"strings"
)

func main() {
	app := cli.NewApp()
	app.Name = "MakeAppIcon"
	app.Version = "0.1"
	app.Usage = "CLI tool to make app icons for IOS and Android"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "filename",
			Value: "Ex: icon.png",
			Usage: "PNG icon file of size 1024x1024",
		},
		cli.StringFlag{
			Name:  "outputdir",
			Value: "Default is current",
			Usage: "Ouput directory of generated app icons",
		},
	}

	app.Action = func(c *cli.Context) {
		name := ""
		if c.NArg() > 0 {
			name = c.Args()[0]
		}

		//open file
		file, err := os.Open(name)
		if err != nil {
			log.Fatal(err)
		}

		// Decode PNG
		img, err := png.Decode(file)
		if err != nil {
			log.Fatal(err)
		}
		file.Close()

		// Reject file if bounds is not 1024x1024
		size := img.Bounds()
		if !(size.Max.X == 1024 && size.Max.Y == 1024) {
			log.Fatal("iTunesConnect requires app icon to be of size 1024x1024.")
		}

		// Decode json from the template
		var app_icons AppIconContents
		err = json.Unmarshal([]byte(APP_ICON_JSON), &app_icons)
		if err != nil {
			log.Fatal(err)
		}

		// Go thorugh the list of images
		for i := 0; i < len(app_icons.Images); i++ {
			image_info := app_icons.Images[i]

			// Parse scalar size
			size_x, _ := strconv.ParseFloat(strings.Split(image_info.Size, "x")[0], 64)
			scale, _ := strconv.ParseFloat(strings.Split(image_info.Scale, "x")[0], 64)

			app_icons.Images[i].image = resize.Resize(uint(size_x*scale), 0, img, resize.Lanczos3)
		}

		// Save
		app_icons.Save(".")
	}

	app.Run(os.Args)
}
<commit_msg>Remove unused flag<commit_after>package main

import (
	"encoding/json"
	"github.com/codegangsta/cli"
	"github.com/nfnt/resize"
	"image/png"
	"log"
	"os"
	"strconv"
	"strings"
)

func main() {
	app := cli.NewApp()
	app.Name = "MakeAppIcon"
	app.Version = "0.1"
	app.Usage = "CLI tool to make app icons for IOS and Android"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "filename",
			Value: "Ex: icon.png",
			Usage: "PNG icon file of size 1024x1024",
		},
	}

	app.Action = func(c *cli.Context) {
		name := ""
		if c.NArg() > 0 {
			name = c.Args()[0]
		}

		//open file
		file, err := os.Open(name)
		if err != nil {
			log.Fatal(err)
		}

		// Decode PNG
		img, err := png.Decode(file)
		if err != nil {
			log.Fatal(err)
		}
		file.Close()

		// Reject file if bounds is not 1024x1024
		size := img.Bounds()
		if !(size.Max.X == 1024 && size.Max.Y == 1024) {
			log.Fatal("iTunesConnect requires app icon to be of size 1024x1024.")
		}

		// Decode json from the template
		var app_icons AppIconContents
		err = json.Unmarshal([]byte(APP_ICON_JSON), &app_icons)
		if err != nil {
			log.Fatal(err)
		}

		// Go thorugh the list of images
		for i := 0; i < len(app_icons.Images); i++ {
			image_info := app_icons.Images[i]

			// Parse scalar size
			size_x, _ := strconv.ParseFloat(strings.Split(image_info.Size, "x")[0], 64)
			scale, _ := strconv.ParseFloat(strings.Split(image_info.Scale, "x")[0], 64)

			app_icons.Images[i].image = resize.Resize(uint(size_x*scale), 0, img, resize.Lanczos3)
		}

		// Save
		app_icons.Save(".")
	}

	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/bitrise-io/go-utils/cmdex"
	"github.com/bitrise-io/go-utils/log"
	"github.com/bitrise-io/go-utils/pathutil"
	"github.com/bitrise-tools/go-xamarin/builder"
	"github.com/bitrise-tools/go-xamarin/constants"
	"github.com/bitrise-tools/go-xamarin/tools"
	shellquote "github.com/kballard/go-shellquote"
)

// ConfigsModel ...
type ConfigsModel struct {
	XamarinSolution      string
	XamarinConfiguration string
	XamarinPlatform      string
	ProjectTypeWhitelist string

	AndroidCustomOptions string
	IOSCustomOptions     string
	TvOSCustomOptions    string
	MacOSCustomOptions   string
	ForceMDTool          string

	DeployDir string
}

func createConfigsModelFromEnvs() ConfigsModel {
	return ConfigsModel{
		XamarinSolution:      os.Getenv("xamarin_solution"),
		XamarinConfiguration: os.Getenv("xamarin_configuration"),
		XamarinPlatform:      os.Getenv("xamarin_platform"),
		ProjectTypeWhitelist: os.Getenv("project_type_whitelist"),

		AndroidCustomOptions: os.Getenv("android_build_command_custom_options"),
		IOSCustomOptions:     os.Getenv("ios_build_command_custom_options"),
		TvOSCustomOptions:    os.Getenv("tvos_build_command_custom_options"),
		MacOSCustomOptions:   os.Getenv("macos_build_command_custom_options"),
		ForceMDTool:          os.Getenv("force_mdtool"),

		DeployDir: os.Getenv("BITRISE_DEPLOY_DIR"),
	}
}

func (configs ConfigsModel) print() {
	log.Info("Configs:")

	log.Detail("- XamarinSolution: %s", configs.XamarinSolution)
	log.Detail("- XamarinConfiguration: %s", configs.XamarinConfiguration)
	log.Detail("- XamarinPlatform: %s", configs.XamarinPlatform)
	log.Detail("- ProjectTypeWhitelist: %s", configs.ProjectTypeWhitelist)

	log.Info("Experimental Configs:")

	log.Detail("- AndroidCustomOptions: %s", configs.AndroidCustomOptions)
	log.Detail("- IOSCustomOptions: %s", configs.IOSCustomOptions)
	log.Detail("- TvOSCustomOptions: %s", configs.TvOSCustomOptions)
	log.Detail("- MacOSCustomOptions: %s", configs.MacOSCustomOptions)
	log.Detail("- ForceMDTool: %s", configs.ForceMDTool)

	log.Info("Other Configs:")

	log.Detail("- DeployDir: %s", configs.DeployDir)
}

func (configs ConfigsModel) validate() error {
	if configs.XamarinSolution == "" {
		return errors.New("No XamarinSolution parameter specified!")
	}
	if exist, err := pathutil.IsPathExists(configs.XamarinSolution); err != nil {
		return fmt.Errorf("Failed to check if XamarinSolution exist at: %s, error: %s", configs.XamarinSolution, err)
	} else if !exist {
		return fmt.Errorf("XamarinSolution not exist at: %s", configs.XamarinSolution)
	}

	if configs.XamarinConfiguration == "" {
		return errors.New("No XamarinConfiguration parameter specified!")
	}

	if configs.XamarinPlatform == "" {
		return errors.New("No XamarinPlatform parameter specified!")
	}

	return nil
}

func exportEnvironmentWithEnvman(keyStr, valueStr string) error {
	cmd := cmdex.NewCommand("envman", "add", "--key", keyStr)
	cmd.SetStdin(strings.NewReader(valueStr))
	return cmd.Run()
}

func exportZipedArtifactDir(pth, deployDir, envKey string) (string, error) {
	parentDir := filepath.Dir(pth)
	dirName := filepath.Base(pth)
	deployPth := filepath.Join(deployDir, dirName+".zip")
	cmd := cmdex.NewCommand("/usr/bin/zip", "-rTy", deployPth, dirName)
	cmd.SetDir(parentDir)
	out, err := cmd.RunAndReturnTrimmedCombinedOutput()
	if err != nil {
		return "", fmt.Errorf("Failed to zip dir: %s, output: %s, error: %s", pth, out, err)
	}

	if err := exportEnvironmentWithEnvman(envKey, deployPth); err != nil {
		return "", fmt.Errorf("Failed to export artifact path (%s) into (%s)", deployPth, envKey)
	}

	return deployPth, nil
}

func exportArtifactDir(pth, deployDir, envKey string) (string, error) {
	base := filepath.Base(pth)
	deployPth := filepath.Join(deployDir, base)

	if err := cmdex.CopyDir(pth, deployDir, false); err != nil {
		return "", fmt.Errorf("Failed to move artifact (%s) to (%s)", pth, deployDir)
	}

	if err := exportEnvironmentWithEnvman(envKey, deployPth); err != nil {
		return "", fmt.Errorf("Failed to export artifact path (%s) into (%s)", deployPth, envKey)
	}

	return deployPth, nil
}

func exportArtifactFile(pth, deployDir, envKey string) (string, error) {
	base := filepath.Base(pth)
	deployPth := filepath.Join(deployDir, base)

	if err := cmdex.CopyFile(pth, deployPth); err != nil {
		return "", fmt.Errorf("Failed to move artifact (%s) to (%s)", pth, deployPth)
	}

	if err := exportEnvironmentWithEnvman(envKey, deployPth); err != nil {
		return "", fmt.Errorf("Failed to export artifact path (%s) into (%s)", deployPth, envKey)
	}

	return deployPth, nil
}

func main() {
	configs := createConfigsModelFromEnvs()

	fmt.Println()
	configs.print()

	if err := configs.validate(); err != nil {
		fmt.Println()
		log.Error("Issue with input: %s", err)
		fmt.Println()

		os.Exit(1)
	}

	// parse project type filters
	projectTypeWhitelist := []constants.SDK{}
	if len(configs.ProjectTypeWhitelist) > 0 {
		split := strings.Split(configs.ProjectTypeWhitelist, ",")
		for _, item := range split {
			item := strings.TrimSpace(item)
			projectType, err := constants.ParseSDK(item)
			if err != nil {
				log.Error("Failed to parse project type (%s), error: %s", item, err)
				os.Exit(1)
			}
			projectTypeWhitelist = append(projectTypeWhitelist, projectType)
		}
	}
	// ---

	// prepare custom options
	projectTypeCustomOptions := map[constants.SDK][]string{}
	projectTypeRawCustomOptions := map[constants.SDK]string{
		constants.SDKAndroid: configs.AndroidCustomOptions,
		constants.SDKIOS:     configs.IOSCustomOptions,
		constants.SDKTvOS:    configs.TvOSCustomOptions,
		constants.SDKMacOS:   configs.MacOSCustomOptions,
	}
	for projectType, rawOptions := range projectTypeRawCustomOptions {
		if rawOptions == "" {
			continue
		}

		split, err := shellquote.Split(rawOptions)
		if err != nil {
			log.Error("Failed to split options (%s), error: %s", err)
		}
		projectTypeCustomOptions[projectType] = split
	}
	// ---

	//
	// build
	fmt.Println()
	log.Info("Building all projects in solution: %s", configs.XamarinSolution)

	builder, err := builder.New(configs.XamarinSolution, projectTypeWhitelist, (configs.ForceMDTool == "yes"))
	if err != nil {
		log.Error("Failed to create xamarin builder, error: %s", err)
		os.Exit(1)
	}

	prepareCallback := func(solutionName string, projectName string, sdk constants.SDK, testFramwork constants.TestFramework, command *tools.Editable) {
		options, ok := projectTypeCustomOptions[sdk]
		if ok {
			(*command).SetCustomOptions(options...)
		}
	}

	callback := func(solutionName string, projectName string, sdk constants.SDK, testFramwork constants.TestFramework, commandStr string, alreadyPerformed bool) {
		fmt.Println()
		log.Info("Building project: %s", projectName)
		log.Done("$ %s", commandStr)
		if alreadyPerformed {
			log.Warn("build command already performed, skipping...")
		}
		fmt.Println()
	}

	warnings, err := builder.BuildAllProjects(configs.XamarinConfiguration, configs.XamarinPlatform, prepareCallback, callback)
	if len(warnings) > 0 {
		log.Warn("Build warnings:")
		for _, warning := range warnings {
			log.Warn(warning)
		}
	}
	if err != nil {
		log.Error("Build failed, error: %s", err)
		os.Exit(1)
	}

	output, err := builder.CollectProjectOutputs(configs.XamarinConfiguration, configs.XamarinPlatform)
	if err != nil {
		log.Error("Failed to collect output, error: %s", err)
		os.Exit(1)
	}
	// ---

	// Export outputs
	fmt.Println()
	log.Info("Exporting generated outputs...")

	for projectName, projectOutput := range output {
		fmt.Println()
		log.Info("%s outputs:", projectName)

		for _, output := range projectOutput.Outputs {
			// Android outputs
			if projectOutput.ProjectType == constants.SDKAndroid && output.OutputType == constants.OutputTypeAPK {
				envKey := "BITRISE_APK_PATH"
				pth, err := exportArtifactFile(output.Pth, configs.DeployDir, envKey)
				if err != nil {
					log.Error("Failed to export apk, error: %s", err)
					os.Exit(1)
				}
				log.Done("apk path (%s) is available in (%s) environment variable", pth, envKey)
			}

			// IOS outputs
			if projectOutput.ProjectType == constants.SDKIOS {
				if output.OutputType == constants.OutputTypeXCArchive {
					envKey := "BITRISE_XCARCHIVE_PATH"
					pth, err := exportArtifactDir(output.Pth, configs.DeployDir, envKey)
					if err != nil {
						log.Error("Failed to export xcarchive, error: %s", err)
						os.Exit(1)
					}
					log.Done("xcarchive path (%s) is available in (%s) environment variable", pth, envKey)
				}

				if output.OutputType == constants.OutputTypeIPA {
					envKey := "BITRISE_IPA_PATH"
					pth, err := exportArtifactFile(output.Pth, configs.DeployDir, envKey)
					if err != nil {
						log.Error("Failed to export ipa, error: %s", err)
						os.Exit(1)
					}
					log.Done("ipa path (%s) is available in (%s) environment variable", pth, envKey)
				}

				if output.OutputType == constants.OutputTypeDSYM {
					envKey := "BITRISE_DSYM_PATH"
					pth, err := exportZipedArtifactDir(output.Pth, configs.DeployDir, envKey)
					if err != nil {
						log.Error("Failed to export dsym, error: %s", err)
						os.Exit(1)
					}
					log.Done("dsym path (%s) is available in (%s) environment variable", pth, envKey)
				}
			}

			// TvOS outputs
			if projectOutput.ProjectType == constants.SDKTvOS {
				if output.OutputType == constants.OutputTypeXCArchive {
					envKey := "BITRISE_TVOS_XCARCHIVE_PATH"
					pth, err := exportArtifactDir(output.Pth, configs.DeployDir, envKey)
					if err != nil {
						log.Error("Failed to export xcarchive, error: %s", err)
						os.Exit(1)
					}
					log.Done("xcarchive path (%s) is available in (%s) environment variable", pth, envKey)
				}

				if output.OutputType == constants.OutputTypeIPA {
					envKey := "BITRISE_TVOS_IPA_PATH"
					pth, err := exportArtifactFile(output.Pth, configs.DeployDir, envKey)
					if err != nil {
						log.Error("Failed to export ipa, error: %s", err)
						os.Exit(1)
					}
					log.Done("ipa path (%s) is available in (%s) environment variable", pth, envKey)
				}

				if output.OutputType == constants.OutputTypeDSYM {
					envKey := "BITRISE_TVOS_DSYM_PATH"
					pth, err := exportZipedArtifactDir(output.Pth, configs.DeployDir, envKey)
					if err != nil {
						log.Error("Failed to export dsym, error: %s", err)
						os.Exit(1)
					}
					log.Done("dsym path (%s) is available in (%s) environment variable", pth, envKey)
				}
			}

			// MacOS outputs
			if projectOutput.ProjectType == constants.SDKMacOS {
				if output.OutputType == constants.OutputTypeXCArchive {
					envKey := "BITRISE_MACOS_XCARCHIVE_PATH"
					pth, err := exportArtifactDir(output.Pth, configs.DeployDir, envKey)
					if err != nil {
						log.Error("Failed to export xcarchive, error: %s", err)
						os.Exit(1)
					}
					log.Done("xcarchive path (%s) is available in (%s) environment variable", pth, envKey)
				}

				if output.OutputType == constants.OutputTypeAPP {
					envKey := "BITRISE_MACOS_APP_PATH"
					pth, err := exportArtifactDir(output.Pth, configs.DeployDir, envKey)
					if err != nil {
						log.Error("Failed to export xcarchive, error: %s", err)
						os.Exit(1)
					}
					log.Done("app path (%s) is available in (%s) environment variable", pth, envKey)
				}

				if output.OutputType == constants.OutputTypePKG {
					envKey := "BITRISE_MACOS_PKG_PATH"
					pth, err := exportArtifactFile(output.Pth, configs.DeployDir, envKey)
					if err != nil {
						log.Error("Failed to export pkg, error: %s", err)
						os.Exit(1)
					}
					log.Done("pkg path (%s) is available in (%s) environment variable", pth, envKey)
				}
			}
		}
	}
	// ---
}
<commit_msg>process only non empty sdk's (#7)<commit_after>package main

import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/bitrise-io/go-utils/cmdex"
	"github.com/bitrise-io/go-utils/log"
	"github.com/bitrise-io/go-utils/pathutil"
	"github.com/bitrise-tools/go-xamarin/builder"
	"github.com/bitrise-tools/go-xamarin/constants"
	"github.com/bitrise-tools/go-xamarin/tools"
	shellquote "github.com/kballard/go-shellquote"
)

// ConfigsModel ...
type ConfigsModel struct {
	XamarinSolution      string
	XamarinConfiguration string
	XamarinPlatform      string
	ProjectTypeWhitelist string

	AndroidCustomOptions string
	IOSCustomOptions     string
	TvOSCustomOptions    string
	MacOSCustomOptions   string
	ForceMDTool          string

	DeployDir string
}

func createConfigsModelFromEnvs() ConfigsModel {
	return ConfigsModel{
		XamarinSolution:      os.Getenv("xamarin_solution"),
		XamarinConfiguration: os.Getenv("xamarin_configuration"),
		XamarinPlatform:      os.Getenv("xamarin_platform"),
		ProjectTypeWhitelist: os.Getenv("project_type_whitelist"),

		AndroidCustomOptions: os.Getenv("android_build_command_custom_options"),
		IOSCustomOptions:     os.Getenv("ios_build_command_custom_options"),
		TvOSCustomOptions:    os.Getenv("tvos_build_command_custom_options"),
		MacOSCustomOptions:   os.Getenv("macos_build_command_custom_options"),
		ForceMDTool:          os.Getenv("force_mdtool"),

		DeployDir: os.Getenv("BITRISE_DEPLOY_DIR"),
	}
}

func (configs ConfigsModel) print() {
	log.Info("Configs:")

	log.Detail("- XamarinSolution: %s", configs.XamarinSolution)
	log.Detail("- XamarinConfiguration: %s", configs.XamarinConfiguration)
	log.Detail("- XamarinPlatform: %s", configs.XamarinPlatform)
	log.Detail("- ProjectTypeWhitelist: %s", configs.ProjectTypeWhitelist)

	log.Info("Experimental Configs:")

	log.Detail("- AndroidCustomOptions: %s", configs.AndroidCustomOptions)
	log.Detail("- IOSCustomOptions: %s", configs.IOSCustomOptions)
	log.Detail("- TvOSCustomOptions: %s", configs.TvOSCustomOptions)
	log.Detail("- MacOSCustomOptions: %s", configs.MacOSCustomOptions)
	log.Detail("- ForceMDTool: %s", configs.ForceMDTool)

	log.Info("Other Configs:")

	log.Detail("- DeployDir: %s", configs.DeployDir)
}

func (configs ConfigsModel) validate() error {
	if configs.XamarinSolution == "" {
		return errors.New("No XamarinSolution parameter specified!")
	}
	if exist, err := pathutil.IsPathExists(configs.XamarinSolution); err != nil {
		return fmt.Errorf("Failed to check if XamarinSolution exist at: %s, error: %s", configs.XamarinSolution, err)
	} else if !exist {
		return fmt.Errorf("XamarinSolution not exist at: %s", configs.XamarinSolution)
	}

	if configs.XamarinConfiguration == "" {
		return errors.New("No XamarinConfiguration parameter specified!")
	}

	if configs.XamarinPlatform == "" {
		return errors.New("No XamarinPlatform parameter specified!")
	}

	return nil
}

func exportEnvironmentWithEnvman(keyStr, valueStr string) error {
	cmd := cmdex.NewCommand("envman", "add", "--key", keyStr)
	cmd.SetStdin(strings.NewReader(valueStr))
	return cmd.Run()
}

func exportZipedArtifactDir(pth, deployDir, envKey string) (string, error) {
	parentDir := filepath.Dir(pth)
	dirName := filepath.Base(pth)
	deployPth := filepath.Join(deployDir, dirName+".zip")
	cmd := cmdex.NewCommand("/usr/bin/zip", "-rTy", deployPth, dirName)
	cmd.SetDir(parentDir)
	out, err := cmd.RunAndReturnTrimmedCombinedOutput()
	if err != nil {
		return "", fmt.Errorf("Failed to zip dir: %s, output: %s, error: %s", pth, out, err)
	}

	if err := exportEnvironmentWithEnvman(envKey, deployPth); err != nil {
		return "", fmt.Errorf("Failed to export artifact path (%s) into (%s)", deployPth, envKey)
	}

	return deployPth, nil
}

func exportArtifactDir(pth, deployDir, envKey string) (string, error) {
	base := filepath.Base(pth)
	deployPth := filepath.Join(deployDir, base)

	if err := cmdex.CopyDir(pth, deployDir, false); err != nil {
		return "", fmt.Errorf("Failed to move artifact (%s) to (%s)", pth, deployDir)
	}

	if err := exportEnvironmentWithEnvman(envKey, deployPth); err != nil {
		return "", fmt.Errorf("Failed to export artifact path (%s) into (%s)", deployPth, envKey)
	}

	return deployPth, nil
}

func exportArtifactFile(pth, deployDir, envKey string) (string, error) {
	base := filepath.Base(pth)
	deployPth := filepath.Join(deployDir, base)

	if err := cmdex.CopyFile(pth, deployPth); err != nil {
		return "", fmt.Errorf("Failed to move artifact (%s) to (%s)", pth, deployPth)
	}

	if err := exportEnvironmentWithEnvman(envKey, deployPth); err != nil {
		return "", fmt.Errorf("Failed to export artifact path (%s) into (%s)", deployPth, envKey)
	}

	return deployPth, nil
}

func main() {
	configs := createConfigsModelFromEnvs()

	fmt.Println()
	configs.print()

	if err := configs.validate(); err != nil {
		fmt.Println()
		log.Error("Issue with input: %s", err)
		fmt.Println()

		os.Exit(1)
	}

	// parse project type filters
	projectTypeWhitelist := []constants.SDK{}
	if len(configs.ProjectTypeWhitelist) > 0 {
		split := strings.Split(configs.ProjectTypeWhitelist, ",")

		for _, item := range split {
			item := strings.TrimSpace(item)
			if item == "" {
				continue
			}

			projectType, err := constants.ParseSDK(item)
			if err != nil {
				log.Error("Failed to parse project type (%s), error: %s", item, err)
				os.Exit(1)
			}

			projectTypeWhitelist = append(projectTypeWhitelist, projectType)
		}
	}
	// ---

	// prepare custom options
	projectTypeCustomOptions := map[constants.SDK][]string{}
	projectTypeRawCustomOptions := map[constants.SDK]string{
		constants.SDKAndroid: configs.AndroidCustomOptions,
		constants.SDKIOS:     configs.IOSCustomOptions,
		constants.SDKTvOS:    configs.TvOSCustomOptions,
		constants.SDKMacOS:   configs.MacOSCustomOptions,
	}
	for projectType, rawOptions := range projectTypeRawCustomOptions {
		if rawOptions == "" {
			continue
		}

		split, err := shellquote.Split(rawOptions)
		if err != nil {
			log.Error("Failed to split options (%s), error: %s", err)
		}
		projectTypeCustomOptions[projectType] = split
	}
	// ---

	//
	// build
	fmt.Println()
	log.Info("Building all projects in solution: %s", configs.XamarinSolution)

	builder, err := builder.New(configs.XamarinSolution, projectTypeWhitelist, (configs.ForceMDTool == "yes"))
	if err != nil {
		log.Error("Failed to create xamarin builder, error: %s", err)
		os.Exit(1)
	}

	prepareCallback := func(solutionName string, projectName string, sdk constants.SDK, testFramwork constants.TestFramework, command *tools.Editable) {
		options, ok := projectTypeCustomOptions[sdk]
		if ok {
			(*command).SetCustomOptions(options...)
		}
	}

	callback := func(solutionName string, projectName string, sdk constants.SDK, testFramwork constants.TestFramework, commandStr string, alreadyPerformed bool) {
		fmt.Println()
		log.Info("Building project: %s", projectName)
		log.Done("$ %s", commandStr)
		if alreadyPerformed {
			log.Warn("build command already performed, skipping...")
		}
		fmt.Println()
	}

	warnings, err := builder.BuildAllProjects(configs.XamarinConfiguration, configs.XamarinPlatform, prepareCallback, callback)
	if len(warnings) > 0 {
		log.Warn("Build warnings:")
		for _, warning := range warnings {
			log.Warn(warning)
		}
	}
	if err != nil {
		log.Error("Build failed, error: %s", err)
		os.Exit(1)
	}

	output, err := builder.CollectProjectOutputs(configs.XamarinConfiguration, configs.XamarinPlatform)
	if err != nil {
		log.Error("Failed to collect output, error: %s", err)
		os.Exit(1)
	}
	// ---

	// Export outputs
	fmt.Println()
	log.Info("Exporting generated outputs...")

	for projectName, projectOutput := range output {
		fmt.Println()
		log.Info("%s outputs:", projectName)

		for _, output := range projectOutput.Outputs {
			// Android outputs
			if projectOutput.ProjectType == constants.SDKAndroid && output.OutputType == constants.OutputTypeAPK {
				envKey := "BITRISE_APK_PATH"
				pth, err := exportArtifactFile(output.Pth, configs.DeployDir, envKey)
				if err != nil {
					log.Error("Failed to export apk, error: %s", err)
					os.Exit(1)
				}
				log.Done("apk path (%s) is available in (%s) environment variable", pth, envKey)
			}

			// IOS outputs
			if projectOutput.ProjectType == constants.SDKIOS {
				if output.OutputType == constants.OutputTypeXCArchive {
					envKey := "BITRISE_XCARCHIVE_PATH"
					pth, err := exportArtifactDir(output.Pth, configs.DeployDir, envKey)
					if err != nil {
						log.Error("Failed to export xcarchive, error: %s", err)
						os.Exit(1)
					}
					log.Done("xcarchive path (%s) is available in (%s) environment variable", pth, envKey)
				}

				if output.OutputType == constants.OutputTypeIPA {
					envKey := "BITRISE_IPA_PATH"
					pth, err := exportArtifactFile(output.Pth, configs.DeployDir, envKey)
					if err != nil {
						log.Error("Failed to export ipa, error: %s", err)
						os.Exit(1)
					}
					log.Done("ipa path (%s) is available in (%s) environment variable", pth, envKey)
				}

				if output.OutputType == constants.OutputTypeDSYM {
					envKey := "BITRISE_DSYM_PATH"
					pth, err := exportZipedArtifactDir(output.Pth, configs.DeployDir, envKey)
					if err != nil {
						log.Error("Failed to export dsym, error: %s", err)
						os.Exit(1)
					}
					log.Done("dsym path (%s) is available in (%s) environment variable", pth, envKey)
				}
			}

			// TvOS outputs
			if projectOutput.ProjectType == constants.SDKTvOS {
				if output.OutputType == constants.OutputTypeXCArchive {
					envKey := "BITRISE_TVOS_XCARCHIVE_PATH"
					pth, err := exportArtifactDir(output.Pth, configs.DeployDir, envKey)
					if err != nil {
						log.Error("Failed to export xcarchive, error: %s", err)
						os.Exit(1)
					}
					log.Done("xcarchive path (%s) is available in (%s) environment variable", pth, envKey)
				}

				if output.OutputType == constants.OutputTypeIPA {
					envKey := "BITRISE_TVOS_IPA_PATH"
					pth, err := exportArtifactFile(output.Pth, configs.DeployDir, envKey)
					if err != nil {
						log.Error("Failed to export ipa, error: %s", err)
						os.Exit(1)
					}
					log.Done("ipa path (%s) is available in (%s) environment variable", pth, envKey)
				}

				if output.OutputType == constants.OutputTypeDSYM {
					envKey := "BITRISE_TVOS_DSYM_PATH"
					pth, err := exportZipedArtifactDir(output.Pth, configs.DeployDir, envKey)
					if err != nil {
						log.Error("Failed to export dsym, error: %s", err)
						os.Exit(1)
					}
					log.Done("dsym path (%s) is available in (%s) environment variable", pth, envKey)
				}
			}

			// MacOS outputs
			if projectOutput.ProjectType == constants.SDKMacOS {
				if output.OutputType == constants.OutputTypeXCArchive {
					envKey := "BITRISE_MACOS_XCARCHIVE_PATH"
					pth, err := exportArtifactDir(output.Pth, configs.DeployDir, envKey)
					if err != nil {
						log.Error("Failed to export xcarchive, error: %s", err)
						os.Exit(1)
					}
					log.Done("xcarchive path (%s) is available in (%s) environment variable", pth, envKey)
				}

				if output.OutputType == constants.OutputTypeAPP {
					envKey := "BITRISE_MACOS_APP_PATH"
					pth, err := exportArtifactDir(output.Pth, configs.DeployDir, envKey)
					if err != nil {
						log.Error("Failed to export xcarchive, error: %s", err)
						os.Exit(1)
					}
					log.Done("app path (%s) is available in (%s) environment variable", pth, envKey)
				}

				if output.OutputType == constants.OutputTypePKG {
					envKey := "BITRISE_MACOS_PKG_PATH"
					pth, err := exportArtifactFile(output.Pth, configs.DeployDir, envKey)
					if err != nil {
						log.Error("Failed to export pkg, error: %s", err)
						os.Exit(1)
					}
					log.Done("pkg path (%s) is available in (%s) environment variable", pth, envKey)
				}
			}
		}
	}
	// ---
}
<|endoftext|>