<commit_before>package main

import (
	"context"
	"errors"
	"fmt"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strconv"

	"github.com/bgentry/go-netrc/netrc"
	"github.com/google/go-github/github"
	"golang.org/x/oauth2"
	"gopkg.in/yaml.v2"
)

var (
	client *github.Client

	NotMergableError        = errors.New("Not mergable")
	BranchNotFoundError     = errors.New("Branch not found")
	NonDeletableBranchError = errors.New("Branch cannot be deleted")
	PullReqNotFoundError    = errors.New("Pull request not found")
)

func init() {
	client = github.NewClient(newClient())
}

type tokenSource struct {
	token *oauth2.Token
}

func (t *tokenSource) Token() (*oauth2.Token, error) {
	return t.token, nil
}

func hubConfigPath() string {
	filename := filepath.Join(os.Getenv("HOME"), ".config", "hub")
	if _, err := os.Stat(filename); os.IsNotExist(err) {
		panic(fmt.Sprintf("no such file or directory: %s", filename))
	}
	return filename
}

func accessTokenFromHubConfig() string {
	f, err := os.Open(hubConfigPath())
	if err != nil {
		return ""
	}

	config := struct {
		GitHub []struct {
			OauthToken string `yaml:"oauth_token"`
		} `yaml:"github.com"`
	}{}
	err = yaml.NewDecoder(f).Decode(&config)
	if err != nil {
		log.Printf("couldn't decode hub config: %+v", err)
		return ""
	}
	if len(config.GitHub) == 0 {
		return ""
	}
	return config.GitHub[0].OauthToken
}

func netrcPath() string {
	filename := filepath.Join(os.Getenv("HOME"), ".netrc")
	if _, err := os.Stat(filename); os.IsNotExist(err) {
		panic(fmt.Sprintf("no such file or directory: %s", filename))
	}
	return filename
}

func accessTokenFromNetrc() string {
	machine, err := netrc.FindMachine(netrcPath(), "api.github.com")
	if err != nil {
		panic(err)
	}
	if machine == nil {
		return ""
	}
	return machine.Password
}

func newClient() *http.Client {
	if accessToken := accessTokenFromNetrc(); accessToken != "" {
		return oauth2.NewClient(oauth2.NoContext, &tokenSource{
			&oauth2.Token{AccessToken: accessToken},
		})
	}
	if accessToken := accessTokenFromHubConfig(); accessToken != "" {
		return oauth2.NewClient(oauth2.NoContext, &tokenSource{
			&oauth2.Token{AccessToken: accessToken},
		})
	}
	return http.DefaultClient
}

func stringToInt(number string) int {
	intVal, err := strconv.Atoi(number)
	if err != nil {
		panic(err)
	}
	return intVal
}

func getPullRequest(owner, repo, number string) (*github.PullRequest, error) {
	pr, res, prGetErr := client.PullRequests.Get(context.Background(), owner, repo, stringToInt(number))
	if prGetErr != nil {
		switch res.StatusCode {
		case 404:
			return nil, PullReqNotFoundError
		default:
			return nil, prGetErr
		}
	}
	return pr, prGetErr
}

func mergePullRequest(owner, repo, number string) error {
	if verbose {
		log.Printf("Attempting to merge PR #%s on %s/%s...\n", number, owner, repo)
	}

	commitMsg := fmt.Sprintf("Merge pull request %v", number)
	_, res, mergeErr := client.PullRequests.Merge(
		context.Background(),
		owner,
		repo,
		stringToInt(number),
		commitMsg,
		&github.PullRequestOptions{},
	)

	if mergeErr != nil {
		if verbose {
			fmt.Println("Received an error!", mergeErr)
		}
		switch res.StatusCode {
		case 405:
			return NotMergableError
		case 404:
			return PullReqNotFoundError
		default:
			return mergeErr
		}
	}

	return nil
}

func deleteBranchForPullRequest(owner, repo, number string) error {
	pr, prGetErr := getPullRequest(owner, repo, number)
	if prGetErr != nil {
		return prGetErr
	}

	if *pr.Head.User.Login == owner && *pr.Head.Ref != "" {
		if verbose {
			log.Println("Deleting the branch.")
		}
		err := deleteBranch(owner, repo, *pr.Head.Ref)
		if err != nil {
			return err
		}
	}

	return nil
}

func deleteBranch(owner, repo, branch string) error {
	switch branch {
	case "master":
		fallthrough
	case "gh-pages":
		fallthrough
	case "dev":
		fallthrough
	case "staging":
		return NonDeletableBranchError
	}

	ref := fmt.Sprintf("heads/%s", branch)

	res, deleteBranchErr := client.Git.DeleteRef(context.Background(), owner, repo, ref)

	if deleteBranchErr != nil {
		switch res.StatusCode {
		case 422:
			return BranchNotFoundError
		default:
			return deleteBranchErr
		}
	}

	return nil
}
<commit_msg>Don't delete main branch either<commit_after>package main

import (
	"context"
	"errors"
	"fmt"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strconv"

	"github.com/bgentry/go-netrc/netrc"
	"github.com/google/go-github/github"
	"golang.org/x/oauth2"
	"gopkg.in/yaml.v2"
)

var (
	client *github.Client

	NotMergableError        = errors.New("Not mergable")
	BranchNotFoundError     = errors.New("Branch not found")
	NonDeletableBranchError = errors.New("Branch cannot be deleted")
	PullReqNotFoundError    = errors.New("Pull request not found")
)

func init() {
	client = github.NewClient(newClient())
}

type tokenSource struct {
	token *oauth2.Token
}

func (t *tokenSource) Token() (*oauth2.Token, error) {
	return t.token, nil
}

func hubConfigPath() string {
	filename := filepath.Join(os.Getenv("HOME"), ".config", "hub")
	if _, err := os.Stat(filename); os.IsNotExist(err) {
		panic(fmt.Sprintf("no such file or directory: %s", filename))
	}
	return filename
}

func accessTokenFromHubConfig() string {
	f, err := os.Open(hubConfigPath())
	if err != nil {
		return ""
	}

	config := struct {
		GitHub []struct {
			OauthToken string `yaml:"oauth_token"`
		} `yaml:"github.com"`
	}{}
	err = yaml.NewDecoder(f).Decode(&config)
	if err != nil {
		log.Printf("couldn't decode hub config: %+v", err)
		return ""
	}
	if len(config.GitHub) == 0 {
		return ""
	}
	return config.GitHub[0].OauthToken
}

func netrcPath() string {
	filename := filepath.Join(os.Getenv("HOME"), ".netrc")
	if _, err := os.Stat(filename); os.IsNotExist(err) {
		panic(fmt.Sprintf("no such file or directory: %s", filename))
	}
	return filename
}

func accessTokenFromNetrc() string {
	machine, err := netrc.FindMachine(netrcPath(), "api.github.com")
	if err != nil {
		panic(err)
	}
	if machine == nil {
		return ""
	}
	return machine.Password
}

func newClient() *http.Client {
	if accessToken := accessTokenFromNetrc(); accessToken != "" {
		return oauth2.NewClient(oauth2.NoContext, &tokenSource{
			&oauth2.Token{AccessToken: accessToken},
		})
	}
	if accessToken := accessTokenFromHubConfig(); accessToken != "" {
		return oauth2.NewClient(oauth2.NoContext, &tokenSource{
			&oauth2.Token{AccessToken: accessToken},
		})
	}
	return http.DefaultClient
}

func stringToInt(number string) int {
	intVal, err := strconv.Atoi(number)
	if err != nil {
		panic(err)
	}
	return intVal
}

func getPullRequest(owner, repo, number string) (*github.PullRequest, error) {
	pr, res, prGetErr := client.PullRequests.Get(context.Background(), owner, repo, stringToInt(number))
	if prGetErr != nil {
		switch res.StatusCode {
		case 404:
			return nil, PullReqNotFoundError
		default:
			return nil, prGetErr
		}
	}
	return pr, prGetErr
}

func mergePullRequest(owner, repo, number string) error {
	if verbose {
		log.Printf("Attempting to merge PR #%s on %s/%s...\n", number, owner, repo)
	}

	commitMsg := fmt.Sprintf("Merge pull request %v", number)
	_, res, mergeErr := client.PullRequests.Merge(
		context.Background(),
		owner,
		repo,
		stringToInt(number),
		commitMsg,
		&github.PullRequestOptions{},
	)

	if mergeErr != nil {
		if verbose {
			fmt.Println("Received an error!", mergeErr)
		}
		switch res.StatusCode {
		case 405:
			return NotMergableError
		case 404:
			return PullReqNotFoundError
		default:
			return mergeErr
		}
	}

	return nil
}

func deleteBranchForPullRequest(owner, repo, number string) error {
	pr, prGetErr := getPullRequest(owner, repo, number)
	if prGetErr != nil {
		return prGetErr
	}

	if *pr.Head.User.Login == owner && *pr.Head.Ref != "" {
		if verbose {
			log.Println("Deleting the branch.")
		}
		err := deleteBranch(owner, repo, *pr.Head.Ref)
		if err != nil {
			return err
		}
	}

	return nil
}

func deleteBranch(owner, repo, branch string) error {
	switch branch {
	case "main", "master", "gh-pages", "dev", "staging":
		return NonDeletableBranchError
	}

	ref := fmt.Sprintf("heads/%s", branch)

	res, deleteBranchErr := client.Git.DeleteRef(context.Background(), owner, repo, ref)

	if deleteBranchErr != nil {
		switch res.StatusCode {
		case 422:
			return BranchNotFoundError
		default:
			return deleteBranchErr
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package hooks

import (
	"context"
	"sort"
	"time"

	"github.com/ovh/cds/sdk/log"
)

// Entry point of the internal scheduler
func (s *Service) runScheduler(c context.Context) error {
	ctx, cancel := context.WithCancel(c)
	defer cancel()

	go func() {
		if err := s.dequeueTaskExecutions(ctx); err != nil {
			log.Error("Hooks> runScheduler> dequeueLongRunningTasks> %v", err)
			cancel()
		}
	}()

	go func() {
		if err := s.retryTaskExecutionsRoutine(ctx); err != nil {
			log.Error("Hooks> runScheduler> retryTaskExecutionsRoutine> %v", err)
			cancel()
		}
	}()

	go func() {
		if err := s.deleteTaskExecutionsRoutine(ctx); err != nil {
			log.Error("Hooks> runScheduler> deleteTaskExecutionsRoutine> %v", err)
			cancel()
		}
	}()

	<-ctx.Done()
	return ctx.Err()
}

// Every x seconds, the scehduler try to relaunch all tasks which have never been processed, or in error
func (s *Service) retryTaskExecutionsRoutine(c context.Context) error {
	tick := time.NewTicker(time.Duration(s.Cfg.RetryDelay) * time.Second)
	for {
		select {
		case <-c.Done():
			tick.Stop()
			return c.Err()
		case <-tick.C:
			tasks, err := s.Dao.FindAllTasks()
			if err != nil {
				log.Error("Hooks> retryTaskExecutionsRoutine > Unable to find all tasks: %v", err)
				continue
			}
			for _, t := range tasks {
				execs, err := s.Dao.FindAllTaskExecutions(&t)
				if err != nil {
					log.Error("Hooks> retryTaskExecutionsRoutine > Unable to find all task executions (%s): %v", t.UUID, err)
					continue
				}
				for _, e := range execs {
					if e.ProcessingTimestamp == 0 && e.Timestamp <= time.Now().UnixNano() {
						log.Debug("Hooks> retryTaskExecutionsRoutine > enqueing task %s (%v, %v)", t.UUID, e.Timestamp, time.Now().UnixNano())
						s.Dao.EnqueueTaskExecution(&e)
						continue
					}
					if e.NbErrors < s.Cfg.RetryError && e.LastError != "" {
						s.Dao.EnqueueTaskExecution(&e)
						continue
					}
				}
			}
		}
	}
}

// Every 60 seconds, old executions of each task are deleted
func (s *Service) deleteTaskExecutionsRoutine(c context.Context) error {
	tick := time.NewTicker(time.Duration(60) * time.Second)
	for {
		select {
		case <-c.Done():
			tick.Stop()
			return c.Err()
		case <-tick.C:
			tasks, err := s.Dao.FindAllTasks()
			if err != nil {
				log.Error("Hooks> deleteTaskExecutionsRoutine > Unable to find all tasks: %v", err)
				continue
			}
			for _, t := range tasks {
				execs, err := s.Dao.FindAllTaskExecutions(&t)
				if err != nil {
					log.Error("Hooks> deleteTaskExecutionsRoutine > Unable to find all task executions (%s): %v", t.UUID, err)
					continue
				}
				sort.Slice(execs, func(i, j int) bool {
					return execs[i].Timestamp > execs[j].Timestamp
				})

				for i, e := range execs {
					if i >= s.Cfg.ExecutionHistory && e.ProcessingTimestamp != 0 {
						s.Dao.DeleteTaskExecution(&e)
					}
				}
			}
		}
	}
}

// Get from queue task execution
func (s *Service) dequeueTaskExecutions(c context.Context) error {
	for {
		if c.Err() != nil {
			return c.Err()
		}

		// Dequeuing context
		var taskKey string
		s.Cache.DequeueWithContext(c, schedulerQueueKey, &taskKey)

		// Load the task execution
		var t = TaskExecution{}
		if !s.Cache.Get(taskKey, &t) {
			continue
		}

		task := s.Dao.FindTask(t.UUID)
		if task == nil {
			log.Error("Hooks> dequeueTaskExecutions failed: Task not found")
			t.LastError = "Internal Error: Task not found"
			t.NbErrors++
		} else if task.Stopped {
			t.LastError = "Executions skipped: Task has been stopped"
			t.NbErrors++
		} else if err := s.doTask(c, task, &t); err != nil {
			log.Error("Hooks> dequeueTaskExecutions failed: %v", err)
			t.LastError = err.Error()
			t.NbErrors++
		}

		//Save the execution
		t.ProcessingTimestamp = time.Now().UnixNano()
		s.Dao.SaveTaskExecution(&t)

		//Start (or restart) the task
		s.startTask(c, task)

		continue
	}
}
<commit_msg>fix (hooks): webhook every seconds (#1391)<commit_after>package hooks

import (
	"context"
	"sort"
	"time"

	"github.com/ovh/cds/sdk/log"
)

// Entry point of the internal scheduler
func (s *Service) runScheduler(c context.Context) error {
	ctx, cancel := context.WithCancel(c)
	defer cancel()

	go func() {
		if err := s.dequeueTaskExecutions(ctx); err != nil {
			log.Error("Hooks> runScheduler> dequeueLongRunningTasks> %v", err)
			cancel()
		}
	}()

	go func() {
		if err := s.retryTaskExecutionsRoutine(ctx); err != nil {
			log.Error("Hooks> runScheduler> retryTaskExecutionsRoutine> %v", err)
			cancel()
		}
	}()

	go func() {
		if err := s.deleteTaskExecutionsRoutine(ctx); err != nil {
			log.Error("Hooks> runScheduler> deleteTaskExecutionsRoutine> %v", err)
			cancel()
		}
	}()

	<-ctx.Done()
	return ctx.Err()
}

// Every x seconds, the scehduler try to relaunch all tasks which have never been processed, or in error
func (s *Service) retryTaskExecutionsRoutine(c context.Context) error {
	tick := time.NewTicker(time.Duration(s.Cfg.RetryDelay) * time.Second)
	for {
		select {
		case <-c.Done():
			tick.Stop()
			return c.Err()
		case <-tick.C:
			tasks, err := s.Dao.FindAllTasks()
			if err != nil {
				log.Error("Hooks> retryTaskExecutionsRoutine > Unable to find all tasks: %v", err)
				continue
			}
			for _, t := range tasks {
				execs, err := s.Dao.FindAllTaskExecutions(&t)
				if err != nil {
					log.Error("Hooks> retryTaskExecutionsRoutine > Unable to find all task executions (%s): %v", t.UUID, err)
					continue
				}
				for _, e := range execs {
					if e.ProcessingTimestamp == 0 && e.Timestamp <= time.Now().UnixNano() {
						log.Debug("Hooks> retryTaskExecutionsRoutine > enqueing task %s (%v, %v)", t.UUID, e.Timestamp, time.Now().UnixNano())
						s.Dao.EnqueueTaskExecution(&e)
						continue
					}
					if e.NbErrors < s.Cfg.RetryError && e.LastError != "" {
						s.Dao.EnqueueTaskExecution(&e)
						continue
					}
				}
			}
		}
	}
}

// Every 60 seconds, old executions of each task are deleted
func (s *Service) deleteTaskExecutionsRoutine(c context.Context) error {
	tick := time.NewTicker(time.Duration(60) * time.Second)
	for {
		select {
		case <-c.Done():
			tick.Stop()
			return c.Err()
		case <-tick.C:
			tasks, err := s.Dao.FindAllTasks()
			if err != nil {
				log.Error("Hooks> deleteTaskExecutionsRoutine > Unable to find all tasks: %v", err)
				continue
			}
			for _, t := range tasks {
				execs, err := s.Dao.FindAllTaskExecutions(&t)
				if err != nil {
					log.Error("Hooks> deleteTaskExecutionsRoutine > Unable to find all task executions (%s): %v", t.UUID, err)
					continue
				}
				sort.Slice(execs, func(i, j int) bool {
					return execs[i].Timestamp > execs[j].Timestamp
				})

				for i, e := range execs {
					if i >= s.Cfg.ExecutionHistory && e.ProcessingTimestamp != 0 {
						s.Dao.DeleteTaskExecution(&e)
					}
				}
			}
		}
	}
}

// Get from queue task execution
func (s *Service) dequeueTaskExecutions(c context.Context) error {
	for {
		if c.Err() != nil {
			return c.Err()
		}

		// Dequeuing context
		var taskKey string
		s.Cache.DequeueWithContext(c, schedulerQueueKey, &taskKey)

		// Load the task execution
		var t = TaskExecution{}
		if !s.Cache.Get(taskKey, &t) {
			continue
		}
		t.ProcessingTimestamp = time.Now().UnixNano()
		s.Dao.SaveTaskExecution(&t)

		task := s.Dao.FindTask(t.UUID)
		if task == nil {
			log.Error("Hooks> dequeueTaskExecutions failed: Task not found")
			t.LastError = "Internal Error: Task not found"
			t.NbErrors++
		} else if task.Stopped {
			t.LastError = "Executions skipped: Task has been stopped"
			t.NbErrors++
		} else if err := s.doTask(c, task, &t); err != nil {
			log.Error("Hooks> dequeueTaskExecutions failed: %v", err)
			t.LastError = err.Error()
			t.NbErrors++
		}

		//Save the execution
		t.ProcessingTimestamp = time.Now().UnixNano()
		s.Dao.SaveTaskExecution(&t)

		//Start (or restart) the task
		s.startTask(c, task)

		continue
	}
}
<|endoftext|>


<commit_before>package xmltree

import "testing"

func TestSomething(t *testing.T) {
	NewDoc("1.0")
}

<commit_msg>First realish test<commit_after>package xmltree

import "testing"

func TestSomething(t *testing.T) {
	doc := NewDoc("1.0")
	buffer := BufferCreate()
	result := doc.NodeDump(buffer, doc.NodePtr, 0, 0)
	println("Result Size:", result)
	println("Result:", buffer.BufferContent())
}

<|endoftext|>


<commit_before>package vsphere

import (
	"fmt"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/vmware/govmomi"
	"github.com/vmware/govmomi/find"
	"github.com/vmware/govmomi/vim25/types"
  "github.com/vmware/govmomi/vim25/mo"
)

func resourceVsphereVm() *schema.Resource {
	return &schema.Resource{
		Create: resourceVsphereVmCreate,
		Read:   resourceVsphereVmRead,
		Update: resourceVsphereVmUpdate,
		Delete: resourceVsphereVmDelete,

		Schema: map[string]*schema.Schema{
			"template_name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"vm_name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
      "ip_address": &schema.Schema{
        Type:   schema.TypeString,
        Computed: true,
      },
      "cpus": &schema.Schema{
        Type: schema.TypeInt,
        Required: true,
      },
      "memory_mb": &schema.Schema{
        Type: schema.TypeInt,
        Required: true,
      },
		},
	}
}

func resourceVsphereVmCreate(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*govmomi.Client)

	finder := find.NewFinder(client, false)

	datacenter, err := finder.DefaultDatacenter()

	if err != nil {
		return err
	}

	finder.SetDatacenter(datacenter)

	resourcePool, err := finder.DefaultResourcePool()

	if err != nil {
		return err
	}

	rpRef := resourcePool.Reference()

	vm, err := finder.VirtualMachine(d.Get("template_name").(string))

	if err != nil {
		return err
	}

	folders, err := datacenter.Folders()

	if err != nil {
		return err
	}

	clonespec := types.VirtualMachineCloneSpec{
		Config: &types.VirtualMachineConfigSpec{
      NumCPUs: d.Get("cpus").(int),
      MemoryMB: int64(d.Get("memory_mb").(int)),
      CpuHotAddEnabled: true,
      CpuHotRemoveEnabled: true,
      MemoryHotAddEnabled: true,
    },
		Location: types.VirtualMachineRelocateSpec{
			Pool: &rpRef,
		},
	}

	task, err := vm.Clone(folders.VmFolder, d.Get("vm_name").(string), clonespec)

	if err != nil {
		return err
	}

	_, err = task.WaitForResult(nil)

	if err != nil {
		return err
	}

  d.SetId(d.Get("vm_name").(string))

	return resourceVsphereVmRead(d, meta)
}

func resourceVsphereVmRead(d *schema.ResourceData, meta interface{}) error {
  client := meta.(*govmomi.Client)

  finder := find.NewFinder(client, false)

  datacenter, err := finder.DefaultDatacenter()

  if err != nil {
    return err
  }

  finder.SetDatacenter(datacenter)

  if err != nil {
    return err
  }

  vm, err := finder.VirtualMachine(d.Get("vm_name").(string))

  if err != nil {
    if err.Error() == fmt.Sprintf("vm '%s' not found", d.Get("vm_name").(string)) {
      d.SetId("")
      return nil
    }
  }

  props := []string{"summary"}

  var mvm mo.VirtualMachine

  err = client.Properties(vm.Reference(), props, &mvm)

  if err != nil {
    return err
  }

  d.Set("memory_mb", mvm.Summary.Config.MemorySizeMB)
  d.Set("cpus", mvm.Summary.Config.NumCpu)

	return nil
}

func resourceVsphereVmUpdate(d *schema.ResourceData, meta interface{}) error {
  client := meta.(*govmomi.Client)

  finder := find.NewFinder(client, false)

  datacenter, err := finder.DefaultDatacenter()

  if err != nil {
    return err
  }

  finder.SetDatacenter(datacenter)

  vm, err := finder.VirtualMachine(d.Get("vm_name").(string))

  if err != nil {
    return err
  }

  configspec := types.VirtualMachineConfigSpec{
      NumCPUs: d.Get("cpus").(int),
      MemoryMB: int64(d.Get("memory_mb").(int)),
  }

  task, err := vm.Reconfigure(configspec)

  if err != nil {
    return err
  }

  _, err = task.WaitForResult(nil)

  if err != nil {
    return err
  }

	return resourceVsphereVmRead(d, meta)
}

func resourceVsphereVmDelete(d *schema.ResourceData, meta interface{}) error {
  client := meta.(*govmomi.Client)

  finder := find.NewFinder(client, false)

  datacenter, err := finder.DefaultDatacenter()

  if err != nil {
    return err
  }

  finder.SetDatacenter(datacenter)

  if err != nil {
    return err
  }

  vm, err := finder.VirtualMachine(d.Get("vm_name").(string))

  if err != nil {
    return err
  }

  task, err := vm.Destroy()

  if err != nil {
    return err
  }

  _, err = task.WaitForResult(nil)

  if err != nil {
    return err
  }

  return nil

}
<commit_msg>Now with static IP capability<commit_after>package vsphere

import (
	"fmt"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/vmware/govmomi"
	"github.com/vmware/govmomi/find"
	"github.com/vmware/govmomi/vim25/types"
  "github.com/vmware/govmomi/vim25/mo"
)

func resourceVsphereVm() *schema.Resource {
	return &schema.Resource{
		Create: resourceVsphereVmCreate,
		Read:   resourceVsphereVmRead,
		Update: resourceVsphereVmUpdate,
		Delete: resourceVsphereVmDelete,

		Schema: map[string]*schema.Schema{
			"template_name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"vm_name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
      "ip_address": &schema.Schema{
        Type:   schema.TypeString,
        Computed: true,
      },
      "cpus": &schema.Schema{
        Type: schema.TypeInt,
        Required: true,
      },
      "memory_mb": &schema.Schema{
        Type: schema.TypeInt,
        Required: true,
      },
      "static_ip": &schema.Schema{
        Type: schema.TypeString,
        Optional: true,
      },
		},
	}
}

func resourceVsphereVmCreate(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*govmomi.Client)

	finder := find.NewFinder(client, false)

	datacenter, err := finder.DefaultDatacenter()

	if err != nil {
		return err
	}

	finder.SetDatacenter(datacenter)

	resourcePool, err := finder.DefaultResourcePool()

	if err != nil {
		return err
	}

	rpRef := resourcePool.Reference()

	vm, err := finder.VirtualMachine(d.Get("template_name").(string))

	if err != nil {
		return err
	}

	folders, err := datacenter.Folders()

	if err != nil {
		return err
	}

	clonespec := types.VirtualMachineCloneSpec{
		Config: &types.VirtualMachineConfigSpec{
      NumCPUs: d.Get("cpus").(int),
      MemoryMB: int64(d.Get("memory_mb").(int)),
      CpuHotAddEnabled: true,
      CpuHotRemoveEnabled: true,
      MemoryHotAddEnabled: true,
    },
		Location: types.VirtualMachineRelocateSpec{
			Pool: &rpRef,
		},
    PowerOn: true,
	}

  ipAddress := d.Get("static_ip").(string)

  if ipAddress != "" {
    ip := types.CustomizationFixedIp{
      IpAddress: ipAddress,
    }
    specManager := client.CustomizationSpecManager()
    specItem, _ := specManager.GetCustomizationSpec("Ubuntu 1")
    specItem.Spec.NicSettingMap[0].Adapter.Ip = &ip
    clonespec.Customization = &specItem.Spec
  }

	task, err := vm.Clone(folders.VmFolder, d.Get("vm_name").(string), clonespec)

	if err != nil {
		return err
	}

	_, err = task.WaitForResult(nil)

	if err != nil {
		return err
	}

  d.SetId(d.Get("vm_name").(string))

	return resourceVsphereVmRead(d, meta)
}

func resourceVsphereVmRead(d *schema.ResourceData, meta interface{}) error {
  client := meta.(*govmomi.Client)

  finder := find.NewFinder(client, false)

  datacenter, err := finder.DefaultDatacenter()

  if err != nil {
    return err
  }

  finder.SetDatacenter(datacenter)

  if err != nil {
    return err
  }

  vm, err := finder.VirtualMachine(d.Get("vm_name").(string))

  if err != nil {
    if err.Error() == fmt.Sprintf("vm '%s' not found", d.Get("vm_name").(string)) {
      d.SetId("")
      return nil
    }
  }

  props := []string{"summary"}

  var mvm mo.VirtualMachine

  err = client.Properties(vm.Reference(), props, &mvm)

  if err != nil {
    return err
  }

  d.Set("memory_mb", mvm.Summary.Config.MemorySizeMB)
  d.Set("cpus", mvm.Summary.Config.NumCpu)

	return nil
}

func resourceVsphereVmUpdate(d *schema.ResourceData, meta interface{}) error {
  client := meta.(*govmomi.Client)

  finder := find.NewFinder(client, false)

  datacenter, err := finder.DefaultDatacenter()

  if err != nil {
    return err
  }

  finder.SetDatacenter(datacenter)

  vm, err := finder.VirtualMachine(d.Get("vm_name").(string))

  if err != nil {
    return err
  }

  configspec := types.VirtualMachineConfigSpec{
      NumCPUs: d.Get("cpus").(int),
      MemoryMB: int64(d.Get("memory_mb").(int)),
  }

  task, err := vm.Reconfigure(configspec)

  if err != nil {
    return err
  }

  _, err = task.WaitForResult(nil)

  if err != nil {
    return err
  }

	return resourceVsphereVmRead(d, meta)
}

func resourceVsphereVmDelete(d *schema.ResourceData, meta interface{}) error {
  client := meta.(*govmomi.Client)

  finder := find.NewFinder(client, false)

  datacenter, err := finder.DefaultDatacenter()

  if err != nil {
    return err
  }

  finder.SetDatacenter(datacenter)

  if err != nil {
    return err
  }

  vm, err := finder.VirtualMachine(d.Get("vm_name").(string))

  if err != nil {
    return err
  }

  task, err := vm.PowerOff()

  if err != nil {
    return err
  }

  _, err = task.WaitForResult(nil)

  if err != nil {
    return err
  }

  task, err = vm.Destroy()

  if err != nil {
    return err
  }

  _, err = task.WaitForResult(nil)

  if err != nil {
    return err
  }

  return nil

}
<|endoftext|>


<commit_before>// Copyright 2017 The StudyGolang Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// https://studygolang.com
// Author:polaris	polaris@studygolang.com

package logic

import (
	. "db"
	"errors"
	"fmt"
	"io/ioutil"
	"model"
	"net/http"
	"strings"
	"time"

	"github.com/polaris1119/goutils"

	"github.com/polaris1119/logger"
	"github.com/tidwall/gjson"
	"golang.org/x/net/context"
)

type GithubLogic struct{}

var DefaultGithub = GithubLogic{}

type prInfo struct {
	prURL    string
	username string
	avatar   string
	prTime   time.Time
	hadMerge bool
	number   int
}

var noMoreDataErr = errors.New("pull request: no more data")

func (self GithubLogic) PullRequestEvent(ctx context.Context, body []byte) error {
	objLog := GetLogger(ctx)

	result := gjson.ParseBytes(body)

	thePRURL := result.Get("pull_request.url").String()
	objLog.Infoln("GithubLogic PullRequestEvent, url:", thePRURL)

	_prInfo := &prInfo{
		prURL:    thePRURL,
		username: result.Get("pull_request.user.login").String(),
		avatar:   result.Get("pull_request.user.avatar_url").String(),
		prTime:   result.Get("pull_request.created_at").Time(),
		hadMerge: result.Get("pull_request.merged").Bool(),
	}

	err := self.dealFiles(_prInfo)

	objLog.Infoln("pull request deal successfully!")

	go self.statUserTime()

	return err
}

func (self GithubLogic) PullPR(repo string, isAll bool) error {
	if !isAll {
		err := self.pullPR(repo, 1)

		// stat gctt user time
		self.statUserTime()

		return err
	}

	var (
		err  error
		page = 1
	)

	for {
		err = self.pullPR(repo, page, "asc")
		if err == noMoreDataErr {
			break
		}

		page++
	}

	// stat gctt user time
	self.statUserTime()

	return err
}

func (self GithubLogic) pullPR(repo string, page int, directions ...string) error {
	prListURL := fmt.Sprintf("%s/repos/%s/pulls?state=all&per_page=30&page=%d", GithubAPIBaseUrl, repo, page)

	if len(directions) > 0 {
		prListURL += "&direction=" + directions[0]
	}

	resp, err := http.Get(prListURL)
	if err != nil {
		logger.Errorln("GithubLogic PullPR get error:", err)
		return err
	}
	body, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()
	if err != nil {
		logger.Errorln("GithubLogic PullPR read all error:", err)
		return err
	}

	result := gjson.ParseBytes(body)

	if len(result.Array()) == 0 {
		return noMoreDataErr
	}

	var outErr error

	result.ForEach(func(key, val gjson.Result) bool {
		_prInfo := &prInfo{
			prURL:    val.Get("url").String(),
			username: val.Get("user.login").String(),
			avatar:   val.Get("user.avatar_url").String(),
			prTime:   val.Get("created_at").Time(),
			hadMerge: val.Get("merged_at").Type != gjson.Null,
			number:   int(val.Get("number").Int()),
		}

		err = self.dealFiles(_prInfo)
		if err != nil {
			outErr = err
		}

		return true
	})

	return outErr
}

func (self GithubLogic) dealFiles(_prInfo *prInfo) error {
	if _prInfo.prURL == "" {
		return nil
	}

	filesURL := _prInfo.prURL + "/files"
	resp, err := http.Get(filesURL)
	if err != nil {
		logger.Errorln("github fetch files error:", err, "url:", filesURL)
		return err
	}
	body, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()
	if err != nil {
		logger.Errorln("github read files resp error:", err)
		return err
	}
	filesResult := gjson.ParseBytes(body)

	// 1. 领取翻译任务时，只是改变一个文件，且是 sources 目录下的，文件修改；
	// 2. 任务完成时，删除一个文件，创建一个新文件，删除的文件是 sources 目录下的，创建的文件是 translated 目录下的
	// 3. 翻译完成一篇，同时又领取新的一篇

	length := len(filesResult.Array())
	if length == 1 {
		err = self.translating(filesResult, _prInfo)
	} else if length == 2 {
		err = self.translated(filesResult, _prInfo)
	} else if length == 3 {
		err = self.translateSilmu(filesResult, _prInfo)
	}

	return err
}

func (self GithubLogic) translating(filesResult gjson.Result, _prInfo *prInfo) error {
	var outErr error
	filesResult.ForEach(func(key, val gjson.Result) bool {
		filename := val.Get("filename").String()
		// 是否对原文的改动
		if !strings.HasPrefix(filename, "sources") {
			return true
		}

		filenames := strings.SplitN(filename, "/", 3)
		if len(filenames) < 3 {
			return true
		}
		title := filenames[2]
		if title == "" {
			return true
		}

		// 认为是开始翻译
		status := val.Get("status").String()
		if status == "modified" && _prInfo.hadMerge {
			err := self.insertOrUpdateGCCT(_prInfo, title, false)
			if err != nil {
				outErr = err
			}
		}
		return true
	})

	return outErr
}

func (self GithubLogic) translated(filesResult gjson.Result, _prInfo *prInfo) error {
	var (
		sourceTitle  string
		isTranslated = true
	)

	// 校验是否一个包含删除 sources 的操作，一个包含增加 translated 的操作
	filesResult.ForEach(func(key, val gjson.Result) bool {
		if !isTranslated {
			return false
		}

		status := val.Get("status").String()
		filename := val.Get("filename").String()

		if status == "removed" {
			if strings.HasPrefix(filename, "sources") {
				filenames := strings.SplitN(filename, "/", 3)
				if len(filenames) < 3 {
					return true
				}
				sourceTitle = filenames[2]
			} else {
				isTranslated = false
			}
		} else if status == "added" {
			if !strings.HasPrefix(filename, "translated") {
				isTranslated = false
			}
		}

		return true
	})

	if !isTranslated || sourceTitle == "" {
		return nil
	}

	return self.insertOrUpdateGCCT(_prInfo, sourceTitle, true)
}

func (self GithubLogic) translateSilmu(filesResult gjson.Result, _prInfo *prInfo) error {
	var (
		sourceTitle  string
		isTranslated = true
	)

	filesResult.ForEach(func(key, val gjson.Result) bool {
		if !isTranslated {
			return false
		}

		status := val.Get("status").String()
		filename := val.Get("filename").String()

		if status == "removed" {
			if strings.HasPrefix(filename, "sources") {
				filenames := strings.SplitN(filename, "/", 3)
				if len(filenames) < 3 {
					return true
				}
				sourceTitle = filenames[2]
			} else {
				isTranslated = false
			}
		} else if status == "added" {
			if !strings.HasPrefix(filename, "translated") {
				isTranslated = false
			}
		} else if status == "modified" {
			// 提交完成，之后又领取了新的一篇
			if strings.HasPrefix(filename, "sources") {
				filenames := strings.SplitN(filename, "/", 3)
				if len(filenames) < 3 {
					return true
				}
				title := filenames[2]
				if title == "" {
					return true
				}

				self.insertOrUpdateGCCT(_prInfo, title, false)
			}
		}

		return true
	})

	if !isTranslated || sourceTitle == "" {
		return nil
	}

	return self.insertOrUpdateGCCT(_prInfo, sourceTitle, true)
}

func (GithubLogic) insertOrUpdateGCCT(_prInfo *prInfo, title string, isTranslated bool) error {
	md5 := goutils.Md5(title)
	gcttGit := &model.GCTTGit{}
	_, err := MasterDB.Where("md5=?", md5).Get(gcttGit)
	if err != nil {
		logger.Errorln("GithubLogic insertOrUpdateGCCT get error:", err)
		return err
	}
	if gcttGit.Username != _prInfo.username {
		return nil
	}

	gcttUser := DefaultGCTT.FindOne(nil, _prInfo.username)

	session := MasterDB.NewSession()
	defer session.Close()
	session.Begin()

	if gcttUser.Id == 0 {
		gcttUser.Username = _prInfo.username
		gcttUser.Avatar = _prInfo.avatar
		gcttUser.JoinedAt = _prInfo.prTime.Unix()
		_, err = session.Insert(gcttUser)
		if err != nil {
			session.Rollback()
			logger.Errorln("GithubLogic insertOrUpdateGCCT insert gctt_user error:", err)
			return err
		}
	}

	// 已经存在
	if gcttGit.Id > 0 {
		if gcttGit.TranslatedAt == 0 && isTranslated {
			gcttGit.TranslatedAt = _prInfo.prTime.Unix()
			gcttGit.PR = _prInfo.number
			_, err = MasterDB.Id(gcttGit.Id).Update(gcttGit)
			if err != nil {
				session.Rollback()
				logger.Errorln("GithubLogic insertOrUpdateGCCT update error:", err)
				return err
			}
		}

		session.Commit()
		return nil
	}

	gcttGit.Username = _prInfo.username
	gcttGit.Title = title
	gcttGit.Md5 = md5
	gcttGit.TranslatingAt = _prInfo.prTime.Unix()
	_, err = MasterDB.Insert(gcttGit)
	if err != nil {
		session.Rollback()
		logger.Errorln("GithubLogic insertOrUpdateGCCTGit insert error:", err)
		return err
	}

	session.Commit()
	return nil
}

func (GithubLogic) statUserTime() {
	gcttUsers := make([]*model.GCTTUser, 0)
	err := MasterDB.Find(&gcttUsers)
	if err != nil {
		logger.Errorln("GithubLogic statUserTime find error:", err)
		return
	}

	for _, gcttUser := range gcttUsers {
		gcttGits := make([]*model.GCTTGit, 0)
		err = MasterDB.Where("username=?", gcttUser.Username).OrderBy("id ASC").Find(&gcttGits)
		if err != nil {
			logger.Errorln("GithubLogic find gctt git error:", err)
			continue
		}

		var avgTime, lastAt int64
		for _, gcttGit := range gcttGits {
			if gcttGit.TranslatingAt != 0 && gcttGit.TranslatedAt != 0 {
				avgTime += gcttGit.TranslatedAt - gcttGit.TranslatingAt
			}

			if gcttGit.TranslatedAt > lastAt {
				lastAt = gcttGit.TranslatedAt
			}
		}

		// 查询是否绑定了本站账号
		uid := DefaultThirdUser.findUid(gcttUser.Username, model.BindTypeGithub)

		gcttUser.Num = len(gcttGits)
		gcttUser.AvgTime = int(avgTime)
		gcttUser.LastAt = lastAt
		gcttUser.Uid = uid
		_, err = MasterDB.Id(gcttUser.Id).Update(gcttUser)
		if err != nil {
			logger.Errorln("GithubLogic update gctt user error:", err)
		}
	}
}
<commit_msg>bugfix<commit_after>// Copyright 2017 The StudyGolang Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// https://studygolang.com
// Author:polaris	polaris@studygolang.com

package logic

import (
	. "db"
	"errors"
	"fmt"
	"io/ioutil"
	"model"
	"net/http"
	"strings"
	"time"

	"github.com/polaris1119/goutils"

	"github.com/polaris1119/logger"
	"github.com/tidwall/gjson"
	"golang.org/x/net/context"
)

type GithubLogic struct{}

var DefaultGithub = GithubLogic{}

type prInfo struct {
	prURL    string
	username string
	avatar   string
	prTime   time.Time
	hadMerge bool
	number   int
}

var noMoreDataErr = errors.New("pull request: no more data")

func (self GithubLogic) PullRequestEvent(ctx context.Context, body []byte) error {
	objLog := GetLogger(ctx)

	result := gjson.ParseBytes(body)

	thePRURL := result.Get("pull_request.url").String()
	objLog.Infoln("GithubLogic PullRequestEvent, url:", thePRURL)

	_prInfo := &prInfo{
		prURL:    thePRURL,
		username: result.Get("pull_request.user.login").String(),
		avatar:   result.Get("pull_request.user.avatar_url").String(),
		prTime:   result.Get("pull_request.created_at").Time(),
		hadMerge: result.Get("pull_request.merged").Bool(),
	}

	err := self.dealFiles(_prInfo)

	objLog.Infoln("pull request deal successfully!")

	go self.statUserTime()

	return err
}

func (self GithubLogic) PullPR(repo string, isAll bool) error {
	if !isAll {
		err := self.pullPR(repo, 1)

		// stat gctt user time
		self.statUserTime()

		return err
	}

	var (
		err  error
		page = 1
	)

	for {
		err = self.pullPR(repo, page, "asc")
		if err == noMoreDataErr {
			break
		}

		page++
	}

	// stat gctt user time
	self.statUserTime()

	return err
}

func (self GithubLogic) pullPR(repo string, page int, directions ...string) error {
	prListURL := fmt.Sprintf("%s/repos/%s/pulls?state=all&per_page=30&page=%d", GithubAPIBaseUrl, repo, page)

	if len(directions) > 0 {
		prListURL += "&direction=" + directions[0]
	}

	resp, err := http.Get(prListURL)
	if err != nil {
		logger.Errorln("GithubLogic PullPR get error:", err)
		return err
	}
	body, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()
	if err != nil {
		logger.Errorln("GithubLogic PullPR read all error:", err)
		return err
	}

	result := gjson.ParseBytes(body)

	if len(result.Array()) == 0 {
		return noMoreDataErr
	}

	var outErr error

	result.ForEach(func(key, val gjson.Result) bool {
		_prInfo := &prInfo{
			prURL:    val.Get("url").String(),
			username: val.Get("user.login").String(),
			avatar:   val.Get("user.avatar_url").String(),
			prTime:   val.Get("created_at").Time(),
			hadMerge: val.Get("merged_at").Type != gjson.Null,
			number:   int(val.Get("number").Int()),
		}

		err = self.dealFiles(_prInfo)
		if err != nil {
			outErr = err
		}

		return true
	})

	return outErr
}

func (self GithubLogic) dealFiles(_prInfo *prInfo) error {
	if _prInfo.prURL == "" {
		return nil
	}

	filesURL := _prInfo.prURL + "/files"
	resp, err := http.Get(filesURL)
	if err != nil {
		logger.Errorln("github fetch files error:", err, "url:", filesURL)
		return err
	}
	body, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()
	if err != nil {
		logger.Errorln("github read files resp error:", err)
		return err
	}
	filesResult := gjson.ParseBytes(body)

	// 1. 领取翻译任务时，只是改变一个文件，且是 sources 目录下的，文件修改；
	// 2. 任务完成时，删除一个文件，创建一个新文件，删除的文件是 sources 目录下的，创建的文件是 translated 目录下的
	// 3. 翻译完成一篇，同时又领取新的一篇

	length := len(filesResult.Array())
	if length == 1 {
		err = self.translating(filesResult, _prInfo)
	} else if length == 2 {
		err = self.translated(filesResult, _prInfo)
	} else if length == 3 {
		err = self.translateSilmu(filesResult, _prInfo)
	}

	return err
}

func (self GithubLogic) translating(filesResult gjson.Result, _prInfo *prInfo) error {
	var outErr error
	filesResult.ForEach(func(key, val gjson.Result) bool {
		filename := val.Get("filename").String()
		// 是否对原文的改动
		if !strings.HasPrefix(filename, "sources") {
			return true
		}

		filenames := strings.SplitN(filename, "/", 3)
		if len(filenames) < 3 {
			return true
		}
		title := filenames[2]
		if title == "" {
			return true
		}

		// 认为是开始翻译
		status := val.Get("status").String()
		if status == "modified" && _prInfo.hadMerge {
			err := self.insertOrUpdateGCCT(_prInfo, title, false)
			if err != nil {
				outErr = err
			}
		}
		return true
	})

	return outErr
}

func (self GithubLogic) translated(filesResult gjson.Result, _prInfo *prInfo) error {
	var (
		sourceTitle  string
		isTranslated = true
	)

	// 校验是否一个包含删除 sources 的操作，一个包含增加 translated 的操作
	filesResult.ForEach(func(key, val gjson.Result) bool {
		if !isTranslated {
			return false
		}

		status := val.Get("status").String()
		filename := val.Get("filename").String()

		if status == "removed" {
			if strings.HasPrefix(filename, "sources") {
				filenames := strings.SplitN(filename, "/", 3)
				if len(filenames) < 3 {
					return true
				}
				sourceTitle = filenames[2]
			} else {
				isTranslated = false
			}
		} else if status == "added" {
			if !strings.HasPrefix(filename, "translated") {
				isTranslated = false
			}
		}

		return true
	})

	if !isTranslated || sourceTitle == "" {
		return nil
	}

	return self.insertOrUpdateGCCT(_prInfo, sourceTitle, true)
}

func (self GithubLogic) translateSilmu(filesResult gjson.Result, _prInfo *prInfo) error {
	var (
		sourceTitle  string
		isTranslated = true
	)

	filesResult.ForEach(func(key, val gjson.Result) bool {
		if !isTranslated {
			return false
		}

		status := val.Get("status").String()
		filename := val.Get("filename").String()

		if status == "removed" {
			if strings.HasPrefix(filename, "sources") {
				filenames := strings.SplitN(filename, "/", 3)
				if len(filenames) < 3 {
					return true
				}
				sourceTitle = filenames[2]
			} else {
				isTranslated = false
			}
		} else if status == "added" {
			if !strings.HasPrefix(filename, "translated") {
				isTranslated = false
			}
		} else if status == "modified" {
			// 提交完成，之后又领取了新的一篇
			if strings.HasPrefix(filename, "sources") {
				filenames := strings.SplitN(filename, "/", 3)
				if len(filenames) < 3 {
					return true
				}
				title := filenames[2]
				if title == "" {
					return true
				}

				self.insertOrUpdateGCCT(_prInfo, title, false)
			}
		}

		return true
	})

	if !isTranslated || sourceTitle == "" {
		return nil
	}

	return self.insertOrUpdateGCCT(_prInfo, sourceTitle, true)
}

func (GithubLogic) insertOrUpdateGCCT(_prInfo *prInfo, title string, isTranslated bool) error {
	md5 := goutils.Md5(title)
	gcttGit := &model.GCTTGit{}
	_, err := MasterDB.Where("md5=?", md5).Get(gcttGit)
	if err != nil {
		logger.Errorln("GithubLogic insertOrUpdateGCCT get error:", err)
		return err
	}
	if gcttGit.Id > 0 {
		if gcttGit.Username != _prInfo.username {
			return nil
		}
	}

	gcttUser := DefaultGCTT.FindOne(nil, _prInfo.username)

	session := MasterDB.NewSession()
	defer session.Close()
	session.Begin()

	if gcttUser.Id == 0 {
		gcttUser.Username = _prInfo.username
		gcttUser.Avatar = _prInfo.avatar
		gcttUser.JoinedAt = _prInfo.prTime.Unix()
		_, err = session.Insert(gcttUser)
		if err != nil {
			session.Rollback()
			logger.Errorln("GithubLogic insertOrUpdateGCCT insert gctt_user error:", err)
			return err
		}
	}

	// 已经存在
	if gcttGit.Id > 0 {
		if gcttGit.TranslatedAt == 0 && isTranslated {
			gcttGit.TranslatedAt = _prInfo.prTime.Unix()
			gcttGit.PR = _prInfo.number
			_, err = MasterDB.Id(gcttGit.Id).Update(gcttGit)
			if err != nil {
				session.Rollback()
				logger.Errorln("GithubLogic insertOrUpdateGCCT update error:", err)
				return err
			}
		}

		session.Commit()
		return nil
	}

	gcttGit.Username = _prInfo.username
	gcttGit.Title = title
	gcttGit.Md5 = md5
	gcttGit.TranslatingAt = _prInfo.prTime.Unix()
	_, err = MasterDB.Insert(gcttGit)
	if err != nil {
		session.Rollback()
		logger.Errorln("GithubLogic insertOrUpdateGCCTGit insert error:", err)
		return err
	}

	session.Commit()
	return nil
}

func (GithubLogic) statUserTime() {
	gcttUsers := make([]*model.GCTTUser, 0)
	err := MasterDB.Find(&gcttUsers)
	if err != nil {
		logger.Errorln("GithubLogic statUserTime find error:", err)
		return
	}

	for _, gcttUser := range gcttUsers {
		gcttGits := make([]*model.GCTTGit, 0)
		err = MasterDB.Where("username=?", gcttUser.Username).OrderBy("id ASC").Find(&gcttGits)
		if err != nil {
			logger.Errorln("GithubLogic find gctt git error:", err)
			continue
		}

		var avgTime, lastAt int64
		for _, gcttGit := range gcttGits {
			if gcttGit.TranslatingAt != 0 && gcttGit.TranslatedAt != 0 {
				avgTime += gcttGit.TranslatedAt - gcttGit.TranslatingAt
			}

			if gcttGit.TranslatedAt > lastAt {
				lastAt = gcttGit.TranslatedAt
			}
		}

		// 查询是否绑定了本站账号
		uid := DefaultThirdUser.findUid(gcttUser.Username, model.BindTypeGithub)

		gcttUser.Num = len(gcttGits)
		gcttUser.AvgTime = int(avgTime)
		gcttUser.LastAt = lastAt
		gcttUser.Uid = uid
		_, err = MasterDB.Id(gcttUser.Id).Update(gcttUser)
		if err != nil {
			logger.Errorln("GithubLogic update gctt user error:", err)
		}
	}
}
<|endoftext|>


<commit_before>package filters

import (
	"reflect"
	"regexp"
	"strings"

	d "github.com/appPlant/alpinepass/src/data"
	"github.com/appPlant/alpinepass/src/util"
	"github.com/fatih/structs"
)

//Separator is tha character used for separating filter keys and values.
const Separator string = "="

//PropertyFilter allows filtering a Config for the content of its properties.
type PropertyFilter struct {
	Slices []string
}

func (p PropertyFilter) filter(data d.Config) d.Config {
	verifyFlags(p.Slices) //TODO verify only once and not for every Config
	for i := 0; i < len(p.Slices); i++ {
		data = filterProperty(p.Slices[i], data)
	}
	return data
}

func filterProperty(property string, data d.Config) d.Config {
	var split = strings.Split(property, Separator)
	var key = split[0]
	var value = split[1]
	var regex = regexp.MustCompile(value)

	//TODO check that key exists in Config field

	t := reflect.ValueOf(data)

	var field reflect.StructField

	for i := 0; i < t.NumField(); i++ {
		field = t.Type().Field(i)
		if strings.ToLower(field.Name) == key {
			break
		}
	}

	if field.Type.String() == "string" {
		if !regex.MatchString(t.FieldByName(field.Name).String()) {
			data.IsValid = false
		}
	}
	if field.Type.String() == "[]string" {
		var values = t.FieldByName(field.Name)
		for i := 0; i < values.Len(); i++ {
			if !regex.MatchString(values.Index(i).String()) {
				data.IsValid = false
				break
			}
		}
	}

	//fmt.Print("### Type: ")
	//fmt.Println(reflect.TypeOf(fieldValue))
	//fmt.Println(t.FieldByName(field).Type().String())
	//TODO Is the outer if condition necessary? Aren't all fields just strings?
	/*
		if reflect.TypeOf(fieldValue).String() == "string" {
			if t.FieldByName(field).Type().String() == "[]string" {
				//fmt.Println("### Filtering a list!")
				for i := 0; i < fieldValue.len; i++ {

				}
			} else {
				//fmt.Println("### Filtering a string!")
				if !regex.MatchString(fieldValue) {
					data.IsValid = false
				}
			}
		}
	*/

	return data
}

//verifyFlags checks that the input flags are valid.
func verifyFlags(flags []string) {
	for i := 0; i < len(flags); i++ {
		flag := flags[i]

		//Do some simple checks.
		if !strings.Contains(flag, Separator) {
			util.ThrowError("The filter does not contain '" + Separator + "'! Flag: " + flag)
		}
		if strings.Count(flag, Separator) > 1 {
			util.ThrowError("The filter contains too many '" + Separator + "'! Flag: " + flag)
		}

		//Check that the key part of a flag matches the fields available in struct Config.
		data := d.Config{}
		fieldNames := structs.Names(data)
		key := strings.ToLower(strings.Split(flag, Separator)[0])
		isContained := false
		for j := 0; j < len(fieldNames); j++ {
			if key == strings.ToLower(fieldNames[j]) {
				isContained = true
			}
		}
		if !isContained {
			util.ThrowError("The filter type is not valid! Flag: " + flag)
		}
	}
}
<commit_msg>Adjust filter logic<commit_after>package filters

import (
	"reflect"
	"regexp"
	"strings"

	d "github.com/appPlant/alpinepass/src/data"
	"github.com/appPlant/alpinepass/src/util"
	"github.com/fatih/structs"
)

//Separator is tha character used for separating filter keys and values.
const Separator string = "="

//PropertyFilter allows filtering a Config for the content of its properties.
type PropertyFilter struct {
	Slices []string
}

func (p PropertyFilter) filter(data d.Config) d.Config {
	verifyFlags(p.Slices) //TODO verify only once and not for every Config
	for i := 0; i < len(p.Slices); i++ {
		data = filterProperty(p.Slices[i], data)
	}
	return data
}

func filterProperty(property string, data d.Config) d.Config {
	var split = strings.Split(property, Separator)
	var key = split[0]
	var value = split[1]
	var regex = regexp.MustCompile(value)

	//TODO check that key exists in Config field

	t := reflect.ValueOf(data)

	var field reflect.StructField

	for i := 0; i < t.NumField(); i++ {
		field = t.Type().Field(i)
		if strings.ToLower(field.Name) == key {
			break
		}
	}

	if field.Type.String() == "string" {
		if !regex.MatchString(t.FieldByName(field.Name).String()) {
			data.IsValid = false
		}
	}
	if field.Type.String() == "[]string" {
		var values = t.FieldByName(field.Name)
		for i := 0; i < values.Len(); i++ {
			var valid = false
			if regex.MatchString(values.Index(i).String()) {
				valid = true
				break
			}
			if !valid {
				data.IsValid = false
			}
		}
	}

	//fmt.Print("### Type: ")
	//fmt.Println(reflect.TypeOf(fieldValue))
	//fmt.Println(t.FieldByName(field).Type().String())
	//TODO Is the outer if condition necessary? Aren't all fields just strings?
	/*
		if reflect.TypeOf(fieldValue).String() == "string" {
			if t.FieldByName(field).Type().String() == "[]string" {
				//fmt.Println("### Filtering a list!")
				for i := 0; i < fieldValue.len; i++ {

				}
			} else {
				//fmt.Println("### Filtering a string!")
				if !regex.MatchString(fieldValue) {
					data.IsValid = false
				}
			}
		}
	*/

	return data
}

//verifyFlags checks that the input flags are valid.
func verifyFlags(flags []string) {
	for i := 0; i < len(flags); i++ {
		flag := flags[i]

		//Do some simple checks.
		if !strings.Contains(flag, Separator) {
			util.ThrowError("The filter does not contain '" + Separator + "'! Flag: " + flag)
		}
		if strings.Count(flag, Separator) > 1 {
			util.ThrowError("The filter contains too many '" + Separator + "'! Flag: " + flag)
		}

		//Check that the key part of a flag matches the fields available in struct Config.
		data := d.Config{}
		fieldNames := structs.Names(data)
		key := strings.ToLower(strings.Split(flag, Separator)[0])
		isContained := false
		for j := 0; j < len(fieldNames); j++ {
			if key == strings.ToLower(fieldNames[j]) {
				isContained = true
			}
		}
		if !isContained {
			util.ThrowError("The filter type is not valid! Flag: " + flag)
		}
	}
}
<|endoftext|>


<commit_before>package gitter

import (
	"net/http"
	"fmt"
	"io/ioutil"
	"encoding/json"
	"net/url"
	"strconv"
)

var GITTER_REST_API string = "https://api.gitter.im/v1/"
var GITTER_STREAM_API string = "https://stream.gitter.im/v1/"

func New(token string) *Gitter {
	s := &Gitter{}
	s.config.token = token
	s.config.client = &http.Client{}
	return s
}

type Gitter struct {
	config struct {
		       token  string
		       client *http.Client
	       }
	debug  bool
}

// Set your own http client. Can be useful in App Engine case.
func (gitter *Gitter) SetClient(client *http.Client) {
	gitter.config.client = client
}

// Get current user
func (gitter *Gitter) GetUser() (*User, error) {

	var users []User
	response, err := gitter.get(GITTER_REST_API + "user")
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(response, &users)
	if err != nil {
		return nil, err
	}

	if len(users) > 0 {
		return &users[0], nil
	}

	return nil, GitterApiError{What:"Failed to retrieve current user"}
}

// List of Rooms the user is part of
func (gitter *Gitter) GetUserRooms(userId string) ([]Room, error) {

	var rooms []Room
	response, err := gitter.get(GITTER_REST_API + "user/" + userId + "/rooms")
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(response, &rooms)
	if err != nil {
		return nil, err
	}

	return rooms, nil
}

// List rooms the current user is in
func (gitter *Gitter) GetRooms() ([]Room, error) {

	var rooms []Room
	response, err := gitter.get(GITTER_REST_API + "rooms")
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(response, &rooms)
	if err != nil {
		return nil, err
	}

	return rooms, nil
}

// Get room by id
func (gitter *Gitter) GetRoom(roomId string) (*Room, error) {

	var room Room
	response, err := gitter.get(GITTER_REST_API + "rooms/" + roomId)
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(response, &room)
	if err != nil {
		return nil, err
	}

	return &room, nil
}

// List of messages in a room.
// Pagination is optional. You can pass nil or specific pagination params.
func (gitter *Gitter) GetMessages(roomId string, params *Pagination) ([]Message, error) {

	var messages []Message
	url := GITTER_REST_API + "rooms/" + roomId + "/chatMessages"
	if params != nil {
		url += "?" + params.encode()
	}
	response, err := gitter.get(url)
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(response, &messages)
	if err != nil {
		return nil, err
	}

	return messages, nil
}

// Get message in a room by message id.
func (gitter *Gitter) GetMessage(roomId, messageId string) (*Message, error) {

	var message Message
	response, err := gitter.get(GITTER_REST_API + "rooms/" + roomId + "/chatMessages/" + messageId)
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(response, &message)
	if err != nil {
		return nil, err
	}

	return &message, nil
}

// Pagination params
type Pagination struct {

	// Skip n messages
	Skip     int

	// Get messages before beforeId
	BeforeId string

	// Get messages after afterId
	AfterId  string

	// Maximum number of messages to return
	Limit    int
}

func (messageParams *Pagination) encode() string {
	values := url.Values{}

	if messageParams.AfterId != "" {
		values.Add("afterId", messageParams.AfterId)
	}

	if messageParams.BeforeId != "" {
		values.Add("beforeId", messageParams.BeforeId)
	}

	if messageParams.Skip > 0 {
		values.Add("skip", strconv.Itoa(messageParams.Skip))
	}

	if messageParams.Limit > 0 {
		values.Add("limit", strconv.Itoa(messageParams.Limit))
	}

	return values.Encode()
}

func (gitter *Gitter) getResponse(url string) (*http.Response, error) {
	r, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}
	r.Header.Set("Content-Type", "application/json")
	r.Header.Set("Accept", "application/json")
	r.Header.Set("Authorization", "Bearer " + gitter.config.token)
	response, err := gitter.config.client.Do(r)
	if err != nil {
		return nil, err
	}
	return response, nil
}

func (gitter *Gitter) get(url string) ([]byte, error) {
	resp, err := gitter.getResponse(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode == 401 {
		return nil, GitterApiError{What: fmt.Sprintf("Status code: %v", resp.StatusCode) }
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	return body, nil
}

type GitterApiError struct {
	What string
}

func (e GitterApiError) Error() string {
	return fmt.Sprintf("%v", e.What)
}<commit_msg>Added sending message<commit_after>package gitter

import (
	"net/http"
	"fmt"
	"io/ioutil"
	"encoding/json"
	"net/url"
	"strconv"
	"bytes"
)

var GITTER_REST_API string = "https://api.gitter.im/v1/"
var GITTER_STREAM_API string = "https://stream.gitter.im/v1/"

func New(token string) *Gitter {
	s := &Gitter{}
	s.config.token = token
	s.config.client = &http.Client{}
	return s
}

type Gitter struct {
	config struct {
		       token  string
		       client *http.Client
	       }
	debug  bool
}

// Set your own http client. Can be useful in App Engine case.
func (gitter *Gitter) SetClient(client *http.Client) {
	gitter.config.client = client
}

// Get current user
func (gitter *Gitter) GetUser() (*User, error) {

	var users []User
	response, err := gitter.get(GITTER_REST_API + "user")
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(response, &users)
	if err != nil {
		return nil, err
	}

	if len(users) > 0 {
		return &users[0], nil
	}

	return nil, GitterApiError{What:"Failed to retrieve current user"}
}

// List of Rooms the user is part of
func (gitter *Gitter) GetUserRooms(userId string) ([]Room, error) {

	var rooms []Room
	response, err := gitter.get(GITTER_REST_API + "user/" + userId + "/rooms")
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(response, &rooms)
	if err != nil {
		return nil, err
	}

	return rooms, nil
}

// List rooms the current user is in
func (gitter *Gitter) GetRooms() ([]Room, error) {

	var rooms []Room
	response, err := gitter.get(GITTER_REST_API + "rooms")
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(response, &rooms)
	if err != nil {
		return nil, err
	}

	return rooms, nil
}

// Get room by id
func (gitter *Gitter) GetRoom(roomId string) (*Room, error) {

	var room Room
	response, err := gitter.get(GITTER_REST_API + "rooms/" + roomId)
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(response, &room)
	if err != nil {
		return nil, err
	}

	return &room, nil
}

// List of messages in a room.
// Pagination is optional. You can pass nil or specific pagination params.
func (gitter *Gitter) GetMessages(roomId string, params *Pagination) ([]Message, error) {

	var messages []Message
	url := GITTER_REST_API + "rooms/" + roomId + "/chatMessages"
	if params != nil {
		url += "?" + params.encode()
	}
	response, err := gitter.get(url)
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(response, &messages)
	if err != nil {
		return nil, err
	}

	return messages, nil
}

// Get message in a room by message id.
func (gitter *Gitter) GetMessage(roomId, messageId string) (*Message, error) {

	var message Message
	response, err := gitter.get(GITTER_REST_API + "rooms/" + roomId + "/chatMessages/" + messageId)
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(response, &message)
	if err != nil {
		return nil, err
	}

	return &message, nil
}

// Send a message to a room
func (gitter *Gitter) SendMessage(roomId, text string) error {

	message := Message{Text:text}
	body, _ := json.Marshal(message)
	err := gitter.post(GITTER_REST_API + "rooms/" + roomId + "/chatMessages", body)
	if err != nil {
		return err
	}

	return nil
}

// Pagination params
type Pagination struct {

	// Skip n messages
	Skip     int

	// Get messages before beforeId
	BeforeId string

	// Get messages after afterId
	AfterId  string

	// Maximum number of messages to return
	Limit    int
}

func (messageParams *Pagination) encode() string {
	values := url.Values{}

	if messageParams.AfterId != "" {
		values.Add("afterId", messageParams.AfterId)
	}

	if messageParams.BeforeId != "" {
		values.Add("beforeId", messageParams.BeforeId)
	}

	if messageParams.Skip > 0 {
		values.Add("skip", strconv.Itoa(messageParams.Skip))
	}

	if messageParams.Limit > 0 {
		values.Add("limit", strconv.Itoa(messageParams.Limit))
	}

	return values.Encode()
}

func (gitter *Gitter) getResponse(url string) (*http.Response, error) {
	r, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}
	r.Header.Set("Content-Type", "application/json")
	r.Header.Set("Accept", "application/json")
	r.Header.Set("Authorization", "Bearer " + gitter.config.token)
	response, err := gitter.config.client.Do(r)
	if err != nil {
		return nil, err
	}
	return response, nil
}

func (gitter *Gitter) get(url string) ([]byte, error) {
	resp, err := gitter.getResponse(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode == 401 {
		return nil, GitterApiError{What: fmt.Sprintf("Status code: %v", resp.StatusCode) }
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	return body, nil
}

func (gitter *Gitter) post(url string, body []byte) error {
	r, err := http.NewRequest("POST", url, bytes.NewBuffer(body))
	if err != nil {
		return err
	}

	r.Header.Set("Content-Type", "application/json")
	r.Header.Set("Accept", "application/json")
	r.Header.Set("Authorization", "Bearer " + gitter.config.token)

	resp, err := gitter.config.client.Do(r)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode == 401 {
		return GitterApiError{What: fmt.Sprintf("Status code: %v", resp.StatusCode) }
	}

	return nil
}

type GitterApiError struct {
	What string
}

func (e GitterApiError) Error() string {
	return fmt.Sprintf("%v", e.What)
}<|endoftext|>


<commit_before>package UserManager

import (
	"encoding/json"
	"io/ioutil"
	"github.com/pkg/errors"
	"os"
	"path/filepath"
	"reflect"
)

//readDataToMemory Reads a given file as json , decodes this json to a UserMap and returns the UserMap. The Files data must be an Encoded UserMap(see saveDataToFile)
func readDataToMemory(path string) (data UserMap, err error) {
	var bytedata []byte
	data = make(UserMap)
	// read the whole file at once
	bytedata, err = ioutil.ReadFile(path)
	if err != nil {
		errors.Wrap(err, "Error in ReadFromFile")
		return
	}

	//Decode json byte array to hashmap TODO=Find better serialisation
	err = json.Unmarshal(bytedata, &data)

	if err != nil {
		errors.Wrap(err, "Error in ReadFromFile while decoding Json byte array to hashmap")
		return
	}

	return
}

//saveDataToFile saves a given UserMap to a file in the given path by encoding the UserMap as Json and writing the Text to the Filesystem
func saveDataToFile(data UserMap, path string) (err error) {
	var bytedata []byte

	if _, err := os.Stat(path); os.IsNotExist(err) {
		os.MkdirAll(filepath.Dir(path), os.ModePerm)
		os.Create(path)
	}

	//Encode file to Json byte array TODO=Find better serialisation
	bytedata, err = json.Marshal(data)
	if err != nil {
		errors.Wrap(err, "Error in SaveToFile while engoding map to json")
		return
	}

	// write the whole body at once with unix permission TODO=CHECK Windows permission working ?
	err = ioutil.WriteFile(path, bytedata, 0660)
	if err != nil {
		errors.Wrap(err, "Error in SaveToFile while writing file to disk")
		return
	}
	return
}

//writeUser adds a UserRecord to the Persistent UserStorage. checks UserRecord if all elements are set, returns error if not.
//Then the Package Global UserMap(in userStorage) gets written to file by SaveDataToFile.
func writeUser(record UserRecord, path string) (err error) {
	managersUserStorage.RWMutex.Lock()
	defer managersUserStorage.RWMutex.Unlock()

	//TODO cause error if value is nil and dont add user
	v := reflect.ValueOf(record)
	for i := 0; i < v.NumField(); i++ {
		if v.Field(i).Interface() == nil {
			errors.WithMessage(err, "A Field of the userrecord was Nil")
			return
		}
	}

	managersUserStorage.UserMap[record.Email] = record //TODO ADD error handling

	err = saveDataToFile(managersUserStorage.UserMap, path + "/userdatabase")
	if err != nil {
		errors.Wrap(err, "Error in Write User while saving data to Disk")
		//TODO Revert Changes done to Global UserStorage
	}

	return
}

//ReadUser finds a UserRecord in the PackageGlobal UserStorage by Email and returns nil or an valid entry.
func ReadUser(email string) (record UserRecord, present bool, err error) {
	managersUserStorage.RWMutex.RLock()
	defer managersUserStorage.RWMutex.RUnlock()

	record , present = managersUserStorage.UserMap[email] //TODO ADD error handling
	err = nil

	return
}

func getNextUID() (id int16) {
	id = 0
	for _, value := range managersUserStorage.UserMap {
		if(value.UID > id) {
			id = value.UID
		}
	}
	return id+1;
}<commit_msg>Comment<commit_after>package UserManager

import (
	"encoding/json"
	"io/ioutil"
	"github.com/pkg/errors"
	"os"
	"path/filepath"
	"reflect"
)

//readDataToMemory Reads a given file as json , decodes this json to a UserMap and returns the UserMap. The Files data must be an Encoded UserMap(see saveDataToFile)
func readDataToMemory(path string) (data UserMap, err error) {
	var bytedata []byte
	data = make(UserMap)
	// read the whole file at once
	bytedata, err = ioutil.ReadFile(path)
	if err != nil {
		errors.Wrap(err, "Error in ReadFromFile")
		return
	}

	//Decode json byte array to hashmap TODO=Find better serialisation
	err = json.Unmarshal(bytedata, &data)

	if err != nil {
		errors.Wrap(err, "Error in ReadFromFile while decoding Json byte array to hashmap")
		return
	}

	return
}

//saveDataToFile saves a given UserMap to a file in the given path by encoding the UserMap as Json and writing the Text to the Filesystem
func saveDataToFile(data UserMap, path string) (err error) {
	var bytedata []byte

	if _, err := os.Stat(path); os.IsNotExist(err) {
		os.MkdirAll(filepath.Dir(path), os.ModePerm)
		os.Create(path)
	}

	//Encode file to Json byte array TODO=Find better serialisation
	bytedata, err = json.Marshal(data)
	if err != nil {
		errors.Wrap(err, "Error in SaveToFile while engoding map to json")
		return
	}

	// write the whole body at once with unix permission TODO=CHECK Windows permission working ?
	err = ioutil.WriteFile(path, bytedata, 0660)
	if err != nil {
		errors.Wrap(err, "Error in SaveToFile while writing file to disk")
		return
	}
	return
}

//writeUser adds a UserRecord to the Persistent UserStorage. checks UserRecord if all elements are set, returns error if not.
//Then the Package Global UserMap(in userStorage) gets written to file by SaveDataToFile.
func writeUser(record UserRecord, path string) (err error) {
	managersUserStorage.RWMutex.Lock()
	defer managersUserStorage.RWMutex.Unlock()

	//TODO cause error if value is nil and dont add user
	v := reflect.ValueOf(record)
	for i := 0; i < v.NumField(); i++ {
		if v.Field(i).Interface() == nil {
			errors.WithMessage(err, "A Field of the userrecord was Nil")
			return
		}
	}

	managersUserStorage.UserMap[record.Email] = record //TODO ADD error handling

	err = saveDataToFile(managersUserStorage.UserMap, path + "/userdatabase")
	if err != nil {
		errors.Wrap(err, "Error in Write User while saving data to Disk")
		//TODO Revert Changes done to Global UserStorage
	}

	return
}

//ReadUser finds a UserRecord in the PackageGlobal UserStorage by Email and returns nil or an valid entry.
func ReadUser(email string) (record UserRecord, present bool, err error) {
	managersUserStorage.RWMutex.RLock()
	defer managersUserStorage.RWMutex.RUnlock()

	record , present = managersUserStorage.UserMap[email] //TODO ADD error handling
	err = nil

	return
}

//getNextUID finds the next possible UID which can be used for new users
func getNextUID() (id int16) {
	id = 0
	for _, value := range managersUserStorage.UserMap {
		if(value.UID > id) {
			id = value.UID
		}
	}
	return id+1;
}<|endoftext|>


<commit_before>package filter_test

import (
	"testing"
	"time"

	"github.com/lxc/lxd/lxd/filter"
	"github.com/lxc/lxd/shared/api"
	"github.com/stretchr/testify/assert"
)

func TestValueOf_Instance(t *testing.T) {
	date := time.Date(2020, 1, 29, 11, 10, 32, 0, time.UTC)
	instance := api.Instance{
		InstancePut: api.InstancePut{
			Architecture: "x86_64",
			Config: map[string]string{
				"image.os": "Busybox",
			},
			Stateful: false,
		},
		CreatedAt: date,
		Name:      "c1",
		ExpandedConfig: map[string]string{
			"image.os": "Busybox",
		},
		ExpandedDevices: map[string]map[string]string{
			"root": {
				"path": "/",
				"pool": "default",
				"type": "disk",
			},
		},
		Status: "Running",
	}
	cases := map[string]interface{}{
		"architecture":               "x86_64",
		"created_at":                 date,
		"config.image.os":            "Busybox",
		"name":                       "c1",
		"expanded_config.image.os":   "Busybox",
		"expanded_devices.root.pool": "default",
		"status":                     "Running",
		"stateful":                   false,
	}
	for field := range cases {
		t.Run(field, func(t *testing.T) {
			value := filter.ValueOf(instance, field)
			assert.Equal(t, cases[field], value)
		})
	}

}
<commit_msg>lxd/filter: Workaround gofmt bug<commit_after>package filter_test

import (
	"testing"
	"time"

	"github.com/lxc/lxd/lxd/filter"
	"github.com/lxc/lxd/shared/api"
	"github.com/stretchr/testify/assert"
)

func TestValueOf_Instance(t *testing.T) {
	date := time.Date(2020, 1, 29, 11, 10, 32, 0, time.UTC)
	instance := api.Instance{
		InstancePut: api.InstancePut{
			Architecture: "x86_64",
			Config: map[string]string{
				"image.os": "BusyBox",
			},
			Stateful: false,
		},
		CreatedAt: date,
		Name:      "c1",
		ExpandedConfig: map[string]string{
			"image.os": "BusyBox",
		},
		ExpandedDevices: map[string]map[string]string{
			"root": {
				"path": "/",
				"pool": "default",
				"type": "disk",
			},
		},
		Status: "Running",
	}

	cases := map[string]interface{}{}
	cases["architecture"] = "x86_64"
	cases["created_at"] = date
	cases["config.image.os"] = "BusyBox"
	cases["name"] = "c1"
	cases["expanded_config.image.os"] = "BusyBox"
	cases["expanded_devices.root.pool"] = "default"
	cases["status"] = "Running"
	cases["stateful"] = false

	for field := range cases {
		t.Run(field, func(t *testing.T) {
			value := filter.ValueOf(instance, field)
			assert.Equal(t, cases[field], value)
		})
	}

}
<|endoftext|>


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

package github

import (
	"fmt"
	"time"
)

// IssuesService handles communication with the issue related
// methods of the GitHub API.
//
// GitHub API docs: http://developer.github.com/v3/issues/
type IssuesService struct {
	client *Client
}

// Issue represents a GitHub issue on a repository.
type Issue struct {
	Number    *int       `json:"number,omitempty"`
	State     *string    `json:"state,omitempty"`
	Title     *string    `json:"title,omitempty"`
	Body      *string    `json:"body,omitempty"`
	User      *User      `json:"user,omitempty"`
	Labels    []Label    `json:"labels,omitempty"`
	Assignee  *User      `json:"assignee,omitempty"`
	Comments  *int       `json:"comments,omitempty"`
	ClosedAt  *time.Time `json:"closed_at,omitempty"`
	CreatedAt *time.Time `json:"created_at,omitempty"`
	UpdatedAt *time.Time `json:"updated_at,omitempty"`

	// TODO(willnorris): milestone
}

func (i Issue) String() string {
	return Stringify(i)
}

// IssueRequest represents a request to create/edit an issue.
// It is separate from Issue above because otherwise Labels
// and Assignee fail to serialize to the correct JSON.
type IssueRequest struct {
	Title    *string  `json:"title,omitempty"`
	Body     *string  `json:"body,omitempty"`
	Labels   []string `json:"labels,omitempty"`
	Assignee *string  `json:"assignee,omitempty"`
	State    *string  `json:"state,omitempty"`

	// TODO(willnorris): milestone here too!
}

// IssueListOptions specifies the optional parameters to the IssuesService.List
// and IssuesService.ListByOrg methods.
type IssueListOptions struct {
	// Filter specifies which issues to list.  Possible values are: assigned,
	// created, mentioned, subscribed, all.  Default is "assigned".
	Filter string `url:"filter,omitempty"`

	// State filters issues based on their state.  Possible values are: open,
	// closed.  Default is "open".
	State string `url:"state,omitempty"`

	// Labels filters issues based on their label.
	Labels []string `url:"labels,comma,omitempty"`

	// Sort specifies how to sort issues.  Possible values are: created, updated,
	// and comments.  Default value is "assigned".
	Sort string `url:"sort,omitempty"`

	// Direction in which to sort issues.  Possible values are: asc, desc.
	// Default is "asc".
	Direction string `url:"direction,omitempty"`

	// Since filters issues by time.
	Since time.Time `url:"since,omitempty"`

	ListOptions
}

// List the issues for the authenticated user.  If all is true, list issues
// across all the user's visible repositories including owned, member, and
// organization repositories; if false, list only owned and member
// repositories.
//
// GitHub API docs: http://developer.github.com/v3/issues/#list-issues
func (s *IssuesService) List(all bool, opt *IssueListOptions) ([]Issue, *Response, error) {
	var u string
	if all {
		u = "issues"
	} else {
		u = "user/issues"
	}
	return s.listIssues(u, opt)
}

// ListByOrg fetches the issues in the specified organization for the
// authenticated user.
//
// GitHub API docs: http://developer.github.com/v3/issues/#list-issues
func (s *IssuesService) ListByOrg(org string, opt *IssueListOptions) ([]Issue, *Response, error) {
	u := fmt.Sprintf("orgs/%v/issues", org)
	return s.listIssues(u, opt)
}

func (s *IssuesService) listIssues(u string, opt *IssueListOptions) ([]Issue, *Response, error) {
	u, err := addOptions(u, opt)
	if err != nil {
		return nil, nil, err
	}

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

	issues := new([]Issue)
	resp, err := s.client.Do(req, issues)
	if err != nil {
		return nil, resp, err
	}

	return *issues, resp, err
}

// IssueListByRepoOptions specifies the optional parameters to the
// IssuesService.ListByRepo method.
type IssueListByRepoOptions struct {
	// Milestone limits issues for the specified milestone.  Possible values are
	// a milestone number, "none" for issues with no milestone, "*" for issues
	// with any milestone.
	Milestone string `url:"milestone,omitempty"`

	// State filters issues based on their state.  Possible values are: open,
	// closed.  Default is "open".
	State string `url:"state,omitempty"`

	// Assignee filters issues based on their assignee.  Possible values are a
	// user name, "none" for issues that are not assigned, "*" for issues with
	// any assigned user.
	Assignee string `url:"assignee,omitempty"`

	// Assignee filters issues based on their creator.
	Creator string `url:"creator,omitempty"`

	// Assignee filters issues to those mentioned a specific user.
	Mentioned string `url:"mentioned,omitempty"`

	// Labels filters issues based on their label.
	Labels []string `url:"labels,omitempty,comma"`

	// Sort specifies how to sort issues.  Possible values are: created, updated,
	// and comments.  Default value is "assigned".
	Sort string `url:"sort,omitempty"`

	// Direction in which to sort issues.  Possible values are: asc, desc.
	// Default is "asc".
	Direction string `url:"direction,omitempty"`

	// Since filters issues by time.
	Since time.Time `url:"since,omitempty"`

	ListOptions
}

// ListByRepo lists the issues for the specified repository.
//
// GitHub API docs: http://developer.github.com/v3/issues/#list-issues-for-a-repository
func (s *IssuesService) ListByRepo(owner string, repo string, opt *IssueListByRepoOptions) ([]Issue, *Response, error) {
	u := fmt.Sprintf("repos/%v/%v/issues", owner, repo)
	u, err := addOptions(u, opt)
	if err != nil {
		return nil, nil, err
	}

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

	issues := new([]Issue)
	resp, err := s.client.Do(req, issues)
	if err != nil {
		return nil, resp, err
	}

	return *issues, resp, err
}

// Get a single issue.
//
// GitHub API docs: http://developer.github.com/v3/issues/#get-a-single-issue
func (s *IssuesService) Get(owner string, repo string, number int) (*Issue, *Response, error) {
	u := fmt.Sprintf("repos/%v/%v/issues/%d", owner, repo, number)
	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

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

	return issue, resp, err
}

// Create a new issue on the specified repository.
//
// GitHub API docs: http://developer.github.com/v3/issues/#create-an-issue
func (s *IssuesService) Create(owner string, repo string, issue *IssueRequest) (*Issue, *Response, error) {
	u := fmt.Sprintf("repos/%v/%v/issues", owner, repo)
	req, err := s.client.NewRequest("POST", u, issue)
	if err != nil {
		return nil, nil, err
	}

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

	return i, resp, err
}

// Edit an issue.
//
// GitHub API docs: http://developer.github.com/v3/issues/#edit-an-issue
func (s *IssuesService) Edit(owner string, repo string, number int, issue *IssueRequest) (*Issue, *Response, error) {
	u := fmt.Sprintf("repos/%v/%v/issues/%d", owner, repo, number)
	req, err := s.client.NewRequest("PATCH", u, issue)
	if err != nil {
		return nil, nil, err
	}

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

	return i, resp, err
}
<commit_msg>Add URL and HTMLURL to Issue<commit_after>// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package github

import (
	"fmt"
	"time"
)

// IssuesService handles communication with the issue related
// methods of the GitHub API.
//
// GitHub API docs: http://developer.github.com/v3/issues/
type IssuesService struct {
	client *Client
}

// Issue represents a GitHub issue on a repository.
type Issue struct {
	Number    *int       `json:"number,omitempty"`
	State     *string    `json:"state,omitempty"`
	Title     *string    `json:"title,omitempty"`
	Body      *string    `json:"body,omitempty"`
	User      *User      `json:"user,omitempty"`
	Labels    []Label    `json:"labels,omitempty"`
	Assignee  *User      `json:"assignee,omitempty"`
	Comments  *int       `json:"comments,omitempty"`
	ClosedAt  *time.Time `json:"closed_at,omitempty"`
	CreatedAt *time.Time `json:"created_at,omitempty"`
	UpdatedAt *time.Time `json:"updated_at,omitempty"`
	URL       *string    `json:"url,omitempty"`
	HTMLURL   *string    `json:"html_url,omitempty"`

	// TODO(willnorris): milestone
}

func (i Issue) String() string {
	return Stringify(i)
}

// IssueRequest represents a request to create/edit an issue.
// It is separate from Issue above because otherwise Labels
// and Assignee fail to serialize to the correct JSON.
type IssueRequest struct {
	Title    *string  `json:"title,omitempty"`
	Body     *string  `json:"body,omitempty"`
	Labels   []string `json:"labels,omitempty"`
	Assignee *string  `json:"assignee,omitempty"`
	State    *string  `json:"state,omitempty"`

	// TODO(willnorris): milestone here too!
}

// IssueListOptions specifies the optional parameters to the IssuesService.List
// and IssuesService.ListByOrg methods.
type IssueListOptions struct {
	// Filter specifies which issues to list.  Possible values are: assigned,
	// created, mentioned, subscribed, all.  Default is "assigned".
	Filter string `url:"filter,omitempty"`

	// State filters issues based on their state.  Possible values are: open,
	// closed.  Default is "open".
	State string `url:"state,omitempty"`

	// Labels filters issues based on their label.
	Labels []string `url:"labels,comma,omitempty"`

	// Sort specifies how to sort issues.  Possible values are: created, updated,
	// and comments.  Default value is "assigned".
	Sort string `url:"sort,omitempty"`

	// Direction in which to sort issues.  Possible values are: asc, desc.
	// Default is "asc".
	Direction string `url:"direction,omitempty"`

	// Since filters issues by time.
	Since time.Time `url:"since,omitempty"`

	ListOptions
}

// List the issues for the authenticated user.  If all is true, list issues
// across all the user's visible repositories including owned, member, and
// organization repositories; if false, list only owned and member
// repositories.
//
// GitHub API docs: http://developer.github.com/v3/issues/#list-issues
func (s *IssuesService) List(all bool, opt *IssueListOptions) ([]Issue, *Response, error) {
	var u string
	if all {
		u = "issues"
	} else {
		u = "user/issues"
	}
	return s.listIssues(u, opt)
}

// ListByOrg fetches the issues in the specified organization for the
// authenticated user.
//
// GitHub API docs: http://developer.github.com/v3/issues/#list-issues
func (s *IssuesService) ListByOrg(org string, opt *IssueListOptions) ([]Issue, *Response, error) {
	u := fmt.Sprintf("orgs/%v/issues", org)
	return s.listIssues(u, opt)
}

func (s *IssuesService) listIssues(u string, opt *IssueListOptions) ([]Issue, *Response, error) {
	u, err := addOptions(u, opt)
	if err != nil {
		return nil, nil, err
	}

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

	issues := new([]Issue)
	resp, err := s.client.Do(req, issues)
	if err != nil {
		return nil, resp, err
	}

	return *issues, resp, err
}

// IssueListByRepoOptions specifies the optional parameters to the
// IssuesService.ListByRepo method.
type IssueListByRepoOptions struct {
	// Milestone limits issues for the specified milestone.  Possible values are
	// a milestone number, "none" for issues with no milestone, "*" for issues
	// with any milestone.
	Milestone string `url:"milestone,omitempty"`

	// State filters issues based on their state.  Possible values are: open,
	// closed.  Default is "open".
	State string `url:"state,omitempty"`

	// Assignee filters issues based on their assignee.  Possible values are a
	// user name, "none" for issues that are not assigned, "*" for issues with
	// any assigned user.
	Assignee string `url:"assignee,omitempty"`

	// Assignee filters issues based on their creator.
	Creator string `url:"creator,omitempty"`

	// Assignee filters issues to those mentioned a specific user.
	Mentioned string `url:"mentioned,omitempty"`

	// Labels filters issues based on their label.
	Labels []string `url:"labels,omitempty,comma"`

	// Sort specifies how to sort issues.  Possible values are: created, updated,
	// and comments.  Default value is "assigned".
	Sort string `url:"sort,omitempty"`

	// Direction in which to sort issues.  Possible values are: asc, desc.
	// Default is "asc".
	Direction string `url:"direction,omitempty"`

	// Since filters issues by time.
	Since time.Time `url:"since,omitempty"`

	ListOptions
}

// ListByRepo lists the issues for the specified repository.
//
// GitHub API docs: http://developer.github.com/v3/issues/#list-issues-for-a-repository
func (s *IssuesService) ListByRepo(owner string, repo string, opt *IssueListByRepoOptions) ([]Issue, *Response, error) {
	u := fmt.Sprintf("repos/%v/%v/issues", owner, repo)
	u, err := addOptions(u, opt)
	if err != nil {
		return nil, nil, err
	}

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

	issues := new([]Issue)
	resp, err := s.client.Do(req, issues)
	if err != nil {
		return nil, resp, err
	}

	return *issues, resp, err
}

// Get a single issue.
//
// GitHub API docs: http://developer.github.com/v3/issues/#get-a-single-issue
func (s *IssuesService) Get(owner string, repo string, number int) (*Issue, *Response, error) {
	u := fmt.Sprintf("repos/%v/%v/issues/%d", owner, repo, number)
	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

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

	return issue, resp, err
}

// Create a new issue on the specified repository.
//
// GitHub API docs: http://developer.github.com/v3/issues/#create-an-issue
func (s *IssuesService) Create(owner string, repo string, issue *IssueRequest) (*Issue, *Response, error) {
	u := fmt.Sprintf("repos/%v/%v/issues", owner, repo)
	req, err := s.client.NewRequest("POST", u, issue)
	if err != nil {
		return nil, nil, err
	}

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

	return i, resp, err
}

// Edit an issue.
//
// GitHub API docs: http://developer.github.com/v3/issues/#edit-an-issue
func (s *IssuesService) Edit(owner string, repo string, number int, issue *IssueRequest) (*Issue, *Response, error) {
	u := fmt.Sprintf("repos/%v/%v/issues/%d", owner, repo, number)
	req, err := s.client.NewRequest("PATCH", u, issue)
	if err != nil {
		return nil, nil, err
	}

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

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