<commit_before>// Copyright (c) 2013-2014 by Michael Dvorkin. All Rights Reserved.
// Use of this source code is governed by a MIT-style license that can
// be found in the LICENSE file.

package donna

import ()

var razoringMargin = [4]int{0, 512, 512+128, 512+256}
var futilityMargin = [4]int{0, 256, 512, 512+128}

// Search with zero window.
func (p *Position) searchWithZeroWindow(beta, depth int) int {
	p.game.nodes++
	if p.isRepetition() {
		return 0
	}

	ply := Ply()
	bestScore := ply - Checkmate
	if bestScore >= beta {
		return bestScore //beta
	}

	// Probe cache.
	cachedMove := Move(0)
	if cached := p.probeCache(); cached != nil {
		cachedMove = cached.move
		if cached.depth >= depth {
			score := cached.score
			if score > Checkmate - MaxPly && score <= Checkmate {
				score -= ply
			} else if score >= -Checkmate && score < -Checkmate + MaxPly {
				score += ply
			}

			if (cached.flags == cacheExact) ||
				(cached.flags == cacheBeta && score >= beta) ||
				(cached.flags == cacheAlpha && score <= beta) {
				return score
			}
		}
	}

	score := p.Evaluate()

	// Razoring and futility pruning. TODO: disable or tune-up in puzzle solving mode.
	if depth < len(razoringMargin) {
		if margin := beta - razoringMargin[depth]; score < margin && beta < Checkmate - MaxPly && cachedMove == Move(0) {
			if p.outposts[pawn(p.color)]&mask7th[p.color] == 0 { // No pawns on 7th.
				razorScore := p.searchQuiescence(margin-1, margin)
				if razorScore < margin {
					return razorScore
				}
			}
		}

		if margin := score - futilityMargin[depth]; margin >= beta && beta > -Checkmate + MaxPly {
			if p.outposts[p.color] & ^p.outposts[king(p.color)] & ^p.outposts[pawn(p.color)] != 0 {
				return margin
			}
		}
	}

	// Null move pruning.
	if depth > 1 && score >= beta && p.outposts[p.color].count() > 5 /*&& beta > -31000*/ {
		reduction := 3 + depth/4
		if score-100 > beta {
			reduction++
		}

		position := p.MakeNullMove()
		if depth <= reduction {
			score = -position.searchQuiescence(-beta, 1-beta)
		} else {
			score = -position.searchWithZeroWindow(1-beta, depth-reduction)
		}
		position.TakeBackNullMove()

		if score >= beta {
			return score
		}
	}

	moveCount := 0
	gen := NewGen(p, ply).generateMoves().rank(cachedMove)
	for move := gen.NextMove(); move != 0; move = gen.NextMove() {
		if position := p.MakeMove(move); position != nil {
			//Log("%*szero/%s> depth: %d, ply: %d, move: %s\n", ply*2, ` `, C(p.color), depth, ply, move)
			inCheck, giveCheck := position.isInCheck(position.color), position.isInCheck(position.color^1)

			reducedDepth := depth
			if !inCheck && !giveCheck && move&(isCapture|isPromo) == 0 && depth >= 3 && moveCount >= 8 {
				reducedDepth = depth - 2 // Late move reduction. TODO: disable or tune-up in puzzle solving mode.
				if reducedDepth > 0 && moveCount >= 16 {
					reducedDepth--
					if reducedDepth > 0 && moveCount >= 32 {
						reducedDepth--
					}
				}
			} else if !inCheck {
				reducedDepth = depth - 1
			}

			moveScore := 0
			if reducedDepth == 0 {
				moveScore = -position.searchQuiescence(-beta, 1-beta)
			} else if inCheck {
				moveScore = -position.searchInCheck(1-beta, reducedDepth)
			} else {
				moveScore = -position.searchWithZeroWindow(1-beta, reducedDepth)

				// Verify late move reduction.
				if reducedDepth < depth-1 && moveScore >= beta {
					moveScore = -position.searchWithZeroWindow(1-beta, depth-1)
				}
			}

			position.TakeBack(move)
			moveCount++

			if moveScore > bestScore {
				if moveScore >= beta {
					p.cache(move, moveScore, depth, cacheBeta)
					p.game.saveGood(depth, move)
					return moveScore
				}
				bestScore = moveScore
			}
		}
	} // next move.

	if moveCount == 0 {
		return 0
	}

	return bestScore
}
<commit_msg>Do null move pruning only the position was not caused by null move<commit_after>// Copyright (c) 2013-2014 by Michael Dvorkin. All Rights Reserved.
// Use of this source code is governed by a MIT-style license that can
// be found in the LICENSE file.

package donna

import ()

var razoringMargin = [4]int{0, 512, 512+128, 512+256}
var futilityMargin = [4]int{0, 256, 512, 512+128}

// Search with zero window.
func (p *Position) searchWithZeroWindow(beta, depth int) int {
	p.game.nodes++
	if p.isRepetition() {
		return 0
	}

	ply := Ply()
	bestScore := ply - Checkmate
	if bestScore >= beta {
		return bestScore //beta
	}

	// Probe cache.
	cachedMove := Move(0)
	if cached := p.probeCache(); cached != nil {
		cachedMove = cached.move
		if cached.depth >= depth {
			score := cached.score
			if score > Checkmate - MaxPly && score <= Checkmate {
				score -= ply
			} else if score >= -Checkmate && score < -Checkmate + MaxPly {
				score += ply
			}

			if (cached.flags == cacheExact) ||
				(cached.flags == cacheBeta && score >= beta) ||
				(cached.flags == cacheAlpha && score <= beta) {
				return score
			}
		}
	}

	score := p.Evaluate()

	// Razoring and futility pruning. TODO: disable or tune-up in puzzle solving mode.
	if depth < len(razoringMargin) {
		if margin := beta - razoringMargin[depth]; score < margin && beta < Checkmate - MaxPly && cachedMove == Move(0) {
			if p.outposts[pawn(p.color)]&mask7th[p.color] == 0 { // No pawns on 7th.
				razorScore := p.searchQuiescence(margin-1, margin)
				if razorScore < margin {
					return razorScore
				}
			}
		}

		if margin := score - futilityMargin[depth]; margin >= beta && beta > -Checkmate + MaxPly {
			if p.outposts[p.color] & ^p.outposts[king(p.color)] & ^p.outposts[pawn(p.color)] != 0 {
				return margin
			}
		}
	}

	// Null move pruning.
	if depth > 1 && score >= beta && p.outposts[p.color].count() > 5 && !p.isNull() {
		reduction := 3 + depth/4
		if score-100 > beta {
			reduction++
		}

		position := p.MakeNullMove()
		if depth <= reduction {
			score = -position.searchQuiescence(-beta, 1-beta)
		} else {
			score = -position.searchWithZeroWindow(1-beta, depth-reduction)
		}
		position.TakeBackNullMove()

		if score >= beta {
			return score
		}
	}

	moveCount := 0
	gen := NewGen(p, ply).generateMoves().rank(cachedMove)
	for move := gen.NextMove(); move != 0; move = gen.NextMove() {
		if position := p.MakeMove(move); position != nil {
			//Log("%*szero/%s> depth: %d, ply: %d, move: %s\n", ply*2, ` `, C(p.color), depth, ply, move)
			inCheck, giveCheck := position.isInCheck(position.color), position.isInCheck(position.color^1)

			reducedDepth := depth
			if !inCheck && !giveCheck && move&(isCapture|isPromo) == 0 && depth >= 3 && moveCount >= 8 {
				reducedDepth = depth - 2 // Late move reduction. TODO: disable or tune-up in puzzle solving mode.
				if reducedDepth > 0 && moveCount >= 16 {
					reducedDepth--
					if reducedDepth > 0 && moveCount >= 32 {
						reducedDepth--
					}
				}
			} else if !inCheck {
				reducedDepth = depth - 1
			}

			moveScore := 0
			if reducedDepth == 0 {
				moveScore = -position.searchQuiescence(-beta, 1-beta)
			} else if inCheck {
				moveScore = -position.searchInCheck(1-beta, reducedDepth)
			} else {
				moveScore = -position.searchWithZeroWindow(1-beta, reducedDepth)

				// Verify late move reduction.
				if reducedDepth < depth-1 && moveScore >= beta {
					moveScore = -position.searchWithZeroWindow(1-beta, depth-1)
				}
			}

			position.TakeBack(move)
			moveCount++

			if moveScore > bestScore {
				if moveScore >= beta {
					p.cache(move, moveScore, depth, cacheBeta)
					p.game.saveGood(depth, move)
					return moveScore
				}
				bestScore = moveScore
			}
		}
	} // next move.

	if moveCount == 0 {
		return 0
	}

	return bestScore
}
<|endoftext|>


<commit_before>package load

// Person is used to load the people.
type Person struct {
	Name    string `json:"name"`
	Inquest struct {
		DeathDate    string   `json:"death_date,omitempty"`
		DeathVerdict string   `json:"death_verdict,omitempty"`
		DeathCauses  []string `json:"death_causes,omitempty"`
		Year         string   `json:"year,omitempty"`
		Permalink    string   `json:"permalink,omitempty"`
	} `json:"inquest,omitempty"`
	Birth struct {
		BirthDate   string `json:"birth_date,omitempty"`
		BirthPlace  string `json:"birth_place,omitempty"`
		BirthMother string `json:"birth_mother,omitempty"`
		BirthFather string `json:"birth_father,omitempty"`
		Year        string `json:"year,omitempty"`
		Permalink   string `json:"permalink,omitempty"`
	} `json:"birth,omitempty"`
	Immigration struct {
		ImmigrationDate string `json:"immigration_date,omitempty"`
		FromCountry     string `json:"from_country,omitempty"`
		Year            string `json:"year,omitempty"`
		Permalink       string `json:"permalink,omitempty"`
	} `json:"immigration,omitempty"`
	Convict struct {
		DepartureDate string `json:"departure_date,omitempty"`
		ConvictPort   string `json:"convict_port,omitempty"`
		ConvictShip   string `json:"convict_ship,omitempty"`
		Year          string `json:"yea,omitemptyr"`
		Permalink     string `json:"permalink,omitempty"`
	} `json:"convict,omitempty"`
	Bankruptcy struct {
		BankruptDate string `json:"bankrupt_date,omitempty"`
		Year         string `json:"year,omitempty"`
		Permalink    string `json:"permalink,omitempty"`
	} `json:"bankruptcy,omitempty"`
	Marriage struct {
		MarriageDate  string `json:"marriage_date,omitempty"`
		SpouseName    string `json:"spouse_name,omitempty"`
		MarriagePlace string `json:"marriage_place,omitempty"`
		Year          string `json:"year,omitempty"`
		Permalink     string `json:"permalink,omitempty"`
	} `json:"marriage,omitempty"`
	Court struct {
		TrialDate    string `json:"trial_date,omitempty"`
		TrialOffence string `json:"trial_offence,omitempty"`
		Year         string `json:"year,omitempty"`
		Permalink    string `json:"permalink,omitempty"`
	} `json:"court,omitempty"`
	HealthWelfare struct {
		AdmissionDate string `json:"admission_date,omitempty"`
		Property      string `json:"property,omitempty"`
		Remarks       string `json:"remarks,omitempty"`
		Year          string `json:"year,omitempty"`
		Permalink     string `json:"permalink,omitempty"`
	} `json:"health-welfare,omitempty"`
	Census struct {
		CensusYear     string `json:"census_year,omitempty"`
		CensusPlace    string `json:"census_place,omitempty"`
		CensusChildren bool   `json:"census_children,omitempty"`
		Year           string `json:"year,omitempty"`
		Permalink      string `json:"permalink,omitempty"`
	} `json:"census,omitempty"`
}
<commit_msg>Fix missing convict events<commit_after>package load

// Person is used to load the people.
type Person struct {
	Name    string `json:"name"`
	Inquest struct {
		DeathDate    string   `json:"death_date,omitempty"`
		DeathVerdict string   `json:"death_verdict,omitempty"`
		DeathCauses  []string `json:"death_causes,omitempty"`
		Year         string   `json:"year,omitempty"`
		Permalink    string   `json:"permalink,omitempty"`
	} `json:"inquest,omitempty"`
	Birth struct {
		BirthDate   string `json:"birth_date,omitempty"`
		BirthPlace  string `json:"birth_place,omitempty"`
		BirthMother string `json:"birth_mother,omitempty"`
		BirthFather string `json:"birth_father,omitempty"`
		Year        string `json:"year,omitempty"`
		Permalink   string `json:"permalink,omitempty"`
	} `json:"birth,omitempty"`
	Immigration struct {
		ImmigrationDate string `json:"immigration_date,omitempty"`
		FromCountry     string `json:"from_country,omitempty"`
		Year            string `json:"year,omitempty"`
		Permalink       string `json:"permalink,omitempty"`
	} `json:"immigration,omitempty"`
	Convict struct {
		DepartureDate string `json:"departure_date,omitempty"`
		ConvictPort   string `json:"convict_port,omitempty"`
		ConvictShip   string `json:"convict_ship,omitempty"`
		Year          string `json:"year,omitemptyr"`
		Permalink     string `json:"permalink,omitempty"`
	} `json:"convict,omitempty"`
	Bankruptcy struct {
		BankruptDate string `json:"bankrupt_date,omitempty"`
		Year         string `json:"year,omitempty"`
		Permalink    string `json:"permalink,omitempty"`
	} `json:"bankruptcy,omitempty"`
	Marriage struct {
		MarriageDate  string `json:"marriage_date,omitempty"`
		SpouseName    string `json:"spouse_name,omitempty"`
		MarriagePlace string `json:"marriage_place,omitempty"`
		Year          string `json:"year,omitempty"`
		Permalink     string `json:"permalink,omitempty"`
	} `json:"marriage,omitempty"`
	Court struct {
		TrialDate    string `json:"trial_date,omitempty"`
		TrialOffence string `json:"trial_offence,omitempty"`
		Year         string `json:"year,omitempty"`
		Permalink    string `json:"permalink,omitempty"`
	} `json:"court,omitempty"`
	HealthWelfare struct {
		AdmissionDate string `json:"admission_date,omitempty"`
		Property      string `json:"property,omitempty"`
		Remarks       string `json:"remarks,omitempty"`
		Year          string `json:"year,omitempty"`
		Permalink     string `json:"permalink,omitempty"`
	} `json:"health-welfare,omitempty"`
	Census struct {
		CensusYear     string `json:"census_year,omitempty"`
		CensusPlace    string `json:"census_place,omitempty"`
		CensusChildren bool   `json:"census_children,omitempty"`
		Year           string `json:"year,omitempty"`
		Permalink      string `json:"permalink,omitempty"`
	} `json:"census,omitempty"`
}
<|endoftext|>


<commit_before>package cmd

import (
	"bufio"
	"fmt"
	"github.com/spf13/cobra"
	"github.com/xwb1989/sqlparser"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/newlee/tequila/viz"
	"regexp"
)

func printJoin(table sqlparser.TableExpr, currentQuery *viz.Query) {
	switch table := table.(type) {
	case *sqlparser.JoinTableExpr:
		printJoin(table.RightExpr, currentQuery)
		printJoin(table.LeftExpr, currentQuery)
	case *sqlparser.AliasedTableExpr:
		tName := sqlparser.String(table.Expr)
		if strings.HasPrefix(tName, "ODSUSER.T_") {
			currentQuery.AddTable(tName, table.As.String())
		}

		if strings.HasPrefix(tName, "(select") {
			//fmt.Println("----------"+ table.As.String())
			//fmt.Println("----------"+ tName)
		}
	default:
		fmt.Println("----------------")
	}
}
func printWhen(when sqlparser.Expr, currentQuery *viz.Query) {
	switch when := when.(type) {
	case *sqlparser.ComparisonExpr:
		left := sqlparser.String(when.Left)
		if strings.Contains(left, ".") {
			currentQuery.AddColumn(left)
		}
		right := sqlparser.String(when.Right)
		if strings.Contains(right, ".") {
			currentQuery.AddColumn(right)
		}

		switch l := when.Left.(type) {
		case *sqlparser.Subquery:
			parseQuery(sqlparser.String(l.Select))
		default:
			printWhen(l, currentQuery)
		}
		switch l := when.Right.(type) {
		case *sqlparser.Subquery:
			parseQuery(sqlparser.String(l.Select))
		default:
			printWhen(l, currentQuery)
		}
	case *sqlparser.OrExpr:
		printWhen(when.Left, currentQuery)
		printWhen(when.Right, currentQuery)
	case *sqlparser.ExistsExpr:
		parseQuery(sqlparser.String(when.Subquery.Select))
	case *sqlparser.IsExpr:
		currentQuery.AddColumn(sqlparser.String(when.Expr))
	case *sqlparser.ParenExpr:
		printWhen(when.Expr, currentQuery)
	case *sqlparser.AndExpr:
		printWhen(when.Left, currentQuery)
		printWhen(when.Right, currentQuery)
	case *sqlparser.ColName:
		tname := when.Qualifier.Name.String()
		col := when.Name.String()
		if tname != "" {
			currentQuery.AddColumn(fmt.Sprintf("%s.%s", tname, col))
		}
	default:
		//fmt.Println(reflect.TypeOf(when).String() + sqlparser.String(when))
	}
}

var queryArr = make([]*viz.Query, 0)

var sqlParseCmd *cobra.Command = &cobra.Command{
	Use:   "sp",
	Short: "query sql parse",
	Long:  ``,
	Run: func(cmd *cobra.Command, args []string) {
		source := cmd.Flag("source").Value.String()
		codeFiles := make([]string, 0)
		filepath.Walk(source, func(path string, fi os.FileInfo, err error) error {
			if strings.HasSuffix(path, ".bdy") || strings.HasSuffix(path, ".sql") {
				codeFiles = append(codeFiles, path)
			}

			return nil
		})

		querys := make([]string, 0)
		for _, codeFileName := range codeFiles {
			codeFile, _ := os.Open(codeFileName)
			scanner := bufio.NewScanner(codeFile)
			scanner.Split(bufio.ScanLines)
			query := ""
			begin := false
			for scanner.Scan() {

				line := scanner.Text()

				tmp := strings.Fields(strings.ToUpper(line))
				for _, word := range tmp {

					if word == "UPDATE" {
						begin = true
					}
					if !begin && strings.HasSuffix(word, "SELECT") {
						begin = true
					}

					if word != "" {
						break
					}
				}

				if begin {
					if strings.Contains(line, "--") && !strings.Contains(line, "/") {
						tmp := strings.Split(line, "--")
						line = tmp[0]
					}
					if strings.Contains(line, "F_QHH(") && strings.Contains(line, "SUBSTR") {
						re, _ := regexp.Compile("F_QHH\\(([\\S\\s]+?)\\)")
						submatch := re.FindStringSubmatch(line)

						line = strings.Replace(line, submatch[0], submatch[1], -1)
					}

					if strings.Contains(line, "TRIM(") && strings.Contains(line, "SUBSTR") {
						re, _ := regexp.Compile("TRIM\\(([\\S\\s]+?)\\)")
						submatch := re.FindStringSubmatch(line)

						line = strings.Replace(line, submatch[0], submatch[1], -1)
					}

					if strings.Contains(line, "ROW_NUMBER()") {
						line = "0"
					}

					if strings.Contains(strings.ToUpper(line), "(PARTITION BY") {
						line = "mm"
					}

					if strings.Contains(line, "LENGTHB(") {
						line = strings.Replace(line, "LENGTHB(", "LENGTH(", -1)
					}

					if strings.Contains(strings.ToUpper(line), " DATE") && !strings.Contains(line, "SELECT") {
						line = strings.Replace(strings.ToUpper(line), " DATE", "", -1)
					}

					if strings.HasPrefix(line, "/*") {
						continue
					}

					query = query + line + "\n"
				}
				if strings.Contains(line, ";") && begin {
					begin = false
					querys = append(querys, query)
					query = ""
				}
			}
		}

		for _, query := range querys {
			parseQuery(query)
		}
		fq := &viz.Query{Sql: "", Tables: make(map[string]*viz.QueryTable)}
		for _, q := range queryArr {
			fq.Merge(q)
		}
		fq.ToString()

	},
}

func parseQuery(query string) {
	sql := strings.ToUpper(query)
	sql = strings.Replace(query, "(+)", "", -1)
	sql = strings.Replace(sql, ";", "", -1)
	sql = strings.Replace(sql, "INTO", "", -1)

	stmt, err := sqlparser.Parse(sql)
	if err != nil {
		//fmt.Println(sql)
		//fmt.Println("parse error: " + err.Error())
		return
	}
	switch stmt := stmt.(type) {
	case *sqlparser.Select:
		var currentQuery = viz.NewQuery(query)

		for _, node := range stmt.From {
			printJoin(node, currentQuery)
		}
		for _, node := range stmt.SelectExprs {
			switch node := node.(type) {
			case *sqlparser.AliasedExpr:
				switch expr := node.Expr.(type) {
				case *sqlparser.CaseExpr:
					for _, when := range expr.Whens {
						printWhen(when.Cond, currentQuery)
					}
				default:
					column := sqlparser.String(expr)
					column = strings.ToUpper(column)
					if column != "NULL" && column != "SYSDATE" && !strings.HasPrefix(column, "'") && !strings.HasPrefix(column, "V_") {
						_, err := strconv.Atoi(column)
						if err != nil {
							currentQuery.AddColumn(column)
						}
					}
				}

			default:
				currentQuery.AddColumn(sqlparser.String(node))
			}

		}
		if stmt.Where != nil {
			printWhen(stmt.Where.Expr, currentQuery)
		}
		queryArr = append(queryArr, currentQuery)
	case *sqlparser.Update:

		var currentQuery = viz.NewQuery(query)
		for _, node := range stmt.Exprs {
			switch node := node.Expr.(type) {
			case *sqlparser.Subquery:
				parseQuery(sqlparser.String(node.Select))
			default:
			}
		}
		printWhen(stmt.Where.Expr,currentQuery)
	case *sqlparser.Delete:
		var currentQuery = viz.NewQuery(query)
		printWhen(stmt.Where.Expr, currentQuery)
	case *sqlparser.Insert:
	}
}

func init() {
	rootCmd.AddCommand(sqlParseCmd)

	sqlParseCmd.Flags().StringP("source", "s", "", "source code directory")
	sqlParseCmd.Flags().StringP("filter", "f", "coll__graph.dot", "dot file filter")
	sqlParseCmd.Flags().StringP("output", "o", "dep.dot", "output dot file name")
}
<commit_msg>fix substr * func expr<commit_after>package cmd

import (
	"bufio"
	"fmt"
	"github.com/spf13/cobra"
	"github.com/xwb1989/sqlparser"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/newlee/tequila/viz"
	"regexp"
	"reflect"
)

func printJoin(table sqlparser.TableExpr, currentQuery *viz.Query) {
	switch table := table.(type) {
	case *sqlparser.JoinTableExpr:
		printJoin(table.RightExpr, currentQuery)
		printJoin(table.LeftExpr, currentQuery)
		printWhen(table.Condition.On,currentQuery)
	case *sqlparser.AliasedTableExpr:
		tName := sqlparser.String(table.Expr)
		if strings.HasPrefix(tName, "ODSUSER.T_") {
			currentQuery.AddTable(tName, table.As.String())
		}

		if strings.HasPrefix(tName, "(select") {
			//fmt.Println("----------"+ table.As.String())
			//fmt.Println("----------"+ tName)
		}
	default:
		fmt.Println("----------------")
	}
}
func printWhen(when sqlparser.Expr, currentQuery *viz.Query) {
	switch when := when.(type) {
	case *sqlparser.ComparisonExpr:
		left := sqlparser.String(when.Left)
		if strings.Contains(left, ".") {
			currentQuery.AddColumn(left)
		}
		right := sqlparser.String(when.Right)
		if strings.Contains(right, ".") {
			currentQuery.AddColumn(right)
		}

		switch l := when.Left.(type) {
		case *sqlparser.Subquery:
			parseQuery(sqlparser.String(l.Select))
		default:
			printWhen(l, currentQuery)
		}
		switch l := when.Right.(type) {
		case *sqlparser.Subquery:
			parseQuery(sqlparser.String(l.Select))
		default:
			printWhen(l, currentQuery)
		}
	case *sqlparser.OrExpr:
		printWhen(when.Left, currentQuery)
		printWhen(when.Right, currentQuery)
	case *sqlparser.ExistsExpr:
		parseQuery(sqlparser.String(when.Subquery.Select))
	case *sqlparser.IsExpr:
		currentQuery.AddColumn(sqlparser.String(when.Expr))
	case *sqlparser.ParenExpr:
		printWhen(when.Expr, currentQuery)
	case *sqlparser.AndExpr:
		printWhen(when.Left, currentQuery)
		printWhen(when.Right, currentQuery)
	case *sqlparser.ColName:
		tname := when.Qualifier.Name.String()
		col := when.Name.String()
		if tname != "" {
			currentQuery.AddColumn(fmt.Sprintf("%s.%s", tname, col))
		}
	case *sqlparser.SubstrExpr:
		tname := when.Name.Qualifier.Name.String()
		col := when.Name.Name.String()
		if tname != "" {
			currentQuery.AddColumn(fmt.Sprintf("%s.%s", tname, col))
		}
	case *sqlparser.FuncExpr:
		tname := when.Qualifier.String()
		col := when.Name.String()
		if tname != "" {
			currentQuery.AddColumn(fmt.Sprintf("%s.%s", tname, col))
		}
	case *sqlparser.SQLVal:
	case *sqlparser.BinaryExpr:
	case sqlparser.ValTuple:

	default:
		fmt.Println(reflect.TypeOf(when).String() + " --- " + sqlparser.String(when))
	}
}

var queryArr = make([]*viz.Query, 0)

var sqlParseCmd *cobra.Command = &cobra.Command{
	Use:   "sp",
	Short: "query sql parse",
	Long:  ``,
	Run: func(cmd *cobra.Command, args []string) {
		source := cmd.Flag("source").Value.String()
		codeFiles := make([]string, 0)
		filepath.Walk(source, func(path string, fi os.FileInfo, err error) error {
			if strings.HasSuffix(path, ".bdy") || strings.HasSuffix(path, ".sql") {
				codeFiles = append(codeFiles, path)
			}

			return nil
		})

		querys := make([]string, 0)
		for _, codeFileName := range codeFiles {
			codeFile, _ := os.Open(codeFileName)
			scanner := bufio.NewScanner(codeFile)
			scanner.Split(bufio.ScanLines)
			query := ""
			begin := false
			for scanner.Scan() {

				line := scanner.Text()

				tmp := strings.Fields(strings.ToUpper(line))
				for _, word := range tmp {

					if word == "UPDATE" {
						begin = true
					}
					if !begin && strings.HasSuffix(word, "SELECT") {
						begin = true
					}

					if word != "" {
						break
					}
				}

				if begin {
					if strings.Contains(line, "--") && !strings.Contains(line, "/") {
						tmp := strings.Split(line, "--")
						line = tmp[0]
					}
					if strings.Contains(line, "F_QHH(") && strings.Contains(line, "SUBSTR") {
						re, _ := regexp.Compile("F_QHH\\(([\\S\\s]+?)\\)")
						submatch := re.FindStringSubmatch(line)

						line = strings.Replace(line, submatch[0], submatch[1], -1)
					}

					if strings.Contains(line, "TRIM(") && strings.Contains(line, "SUBSTR") {
						re, _ := regexp.Compile("TRIM\\(([\\S\\s]+?)\\)")
						submatch := re.FindStringSubmatch(line)

						line = strings.Replace(line, submatch[0], submatch[1], -1)
					}

					if strings.Contains(line, "ROW_NUMBER()") {
						line = "0"
					}

					if strings.Contains(strings.ToUpper(line), "(PARTITION BY") {
						line = "mm"
					}

					if strings.Contains(line, "LENGTHB(") {
						line = strings.Replace(line, "LENGTHB(", "LENGTH(", -1)
					}

					if strings.Contains(strings.ToUpper(line), " DATE") && !strings.Contains(line, "SELECT") {
						line = strings.Replace(strings.ToUpper(line), " DATE", "", -1)
					}

					if strings.HasPrefix(line, "/*") {
						continue
					}

					query = query + line + "\n"
				}
				if strings.Contains(line, ";") && begin {
					begin = false
					querys = append(querys, query)
					query = ""
				}
			}
		}

		for _, query := range querys {
			parseQuery(query)
		}
		fq := &viz.Query{Sql: "", Tables: make(map[string]*viz.QueryTable)}
		for _, q := range queryArr {
			fq.Merge(q)
		}
		fq.ToString()

	},
}

func parseQuery(query string) {
	sql := strings.ToUpper(query)
	sql = strings.Replace(query, "(+)", "", -1)
	sql = strings.Replace(sql, ";", "", -1)
	sql = strings.Replace(sql, "INTO", "", -1)

	stmt, err := sqlparser.Parse(sql)
	if err != nil {
		//fmt.Println(sql)
		//fmt.Println("parse error: " + err.Error())
		return
	}
	switch stmt := stmt.(type) {
	case *sqlparser.Select:
		var currentQuery = viz.NewQuery(query)

		for _, node := range stmt.From {
			printJoin(node, currentQuery)
		}
		for _, node := range stmt.SelectExprs {
			switch node := node.(type) {
			case *sqlparser.AliasedExpr:
				switch expr := node.Expr.(type) {
				case *sqlparser.CaseExpr:
					for _, when := range expr.Whens {
						printWhen(when.Cond, currentQuery)
					}
				default:
					column := sqlparser.String(expr)
					column = strings.ToUpper(column)
					if column != "NULL" && column != "SYSDATE" && !strings.HasPrefix(column, "'") && !strings.HasPrefix(column, "V_") {
						_, err := strconv.Atoi(column)
						if err != nil {
							currentQuery.AddColumn(column)
						}
					}
				}

			default:
				currentQuery.AddColumn(sqlparser.String(node))
			}

		}
		if stmt.Where != nil {
			printWhen(stmt.Where.Expr, currentQuery)
		}
		queryArr = append(queryArr, currentQuery)
	case *sqlparser.Update:

		var currentQuery = viz.NewQuery(query)
		for _, node := range stmt.Exprs {
			switch node := node.Expr.(type) {
			case *sqlparser.Subquery:
				parseQuery(sqlparser.String(node.Select))
			default:
			}
		}
		printWhen(stmt.Where.Expr,currentQuery)
	case *sqlparser.Delete:
		var currentQuery = viz.NewQuery(query)
		printWhen(stmt.Where.Expr, currentQuery)
	case *sqlparser.Insert:
	}
}

func init() {
	rootCmd.AddCommand(sqlParseCmd)

	sqlParseCmd.Flags().StringP("source", "s", "", "source code directory")
	sqlParseCmd.Flags().StringP("filter", "f", "coll__graph.dot", "dot file filter")
	sqlParseCmd.Flags().StringP("output", "o", "dep.dot", "output dot file name")
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/rand"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	mrand "math/rand"
	"os"
	"time"

	"github.com/NebulousLabs/Sia/api"
	"github.com/NebulousLabs/Sia/types"
)

// storageRenter unlocks the wallet, mines some currency, sets an allowance
// using that currency, and uploads some files.  It will periodically try to
// download those files, printing any errors that occur.
func (j *JobRunner) storageRenter() {
	done := make(chan struct{})
	defer close(done)

	j.tg.OnStop(func() {
		<-done
	})

	err := j.client.Post("/wallet/unlock", fmt.Sprintf("encryptionpassword=%s&dictionary=%s", j.walletPassword, "english"), nil)
	if err != nil {
		log.Printf("[%v jobStorageRenter ERROR]: %v\n", j.siaDirectory, err)
		return
	}

	err = j.client.Get("/miner/start", nil)
	if err != nil {
		log.Printf("[%v jobStorageRenter ERROR: %v\n", j.siaDirectory, err)
		return
	}

	// Mine at least 100,000 SC
	desiredbalance := types.NewCurrency64(100000).Mul(types.SiacoinPrecision)
	success := false
	for start := time.Now(); time.Since(start) < 5*time.Minute; {
		select {
		case <-j.tg.StopChan():
			return
		case <-time.After(time.Second):
		}

		var walletInfo api.WalletGET
		err = j.client.Get("/wallet", &walletInfo)
		if err != nil {
			log.Printf("[%v jobStorageRenter ERROR]: %v\n", j.siaDirectory, err)
			return
		}
		if walletInfo.ConfirmedSiacoinBalance.Cmp(desiredbalance) > 0 {
			success = true
			break
		}
	}
	if !success {
		log.Printf("[%v jobStorageRenter ERROR]: timeout: could not mine enough currency after 5 minutes\n", j.siaDirectory)
		return
	}

	// Set an initial 50ksc allowance
	allowance := types.NewCurrency64(50000).Mul(types.SiacoinPrecision)
	if err := j.client.Post("/renter", fmt.Sprintf("funds=%v&period=100", allowance), nil); err != nil {
		log.Printf("[%v jobStorageRenter ERROR: %v\n", j.siaDirectory, err)
	}

	// Every 1000 seconds, set a new allowance.
	go func() {
		for {
			j.tg.Add()

			select {
			case <-j.tg.StopChan():
				j.tg.Done()
				return
			case <-time.After(time.Second * 1000):
			}

			// set an allowance of 50kSC + a random offset from 0-10ksc
			allowance := types.NewCurrency64(50000).Mul(types.SiacoinPrecision)
			if err := j.client.Post("/renter", fmt.Sprintf("funds=%v&period=100", allowance), nil); err != nil {
				log.Printf("[%v jobStorageRenter ERROR: %v\n", j.siaDirectory, err)
			}

			j.tg.Done()
		}
	}()

	// Every 120 seconds, upload a 500MB file.  Delete one file at random once every 10 files.
	go func() {
		var files []string
		for i := 0; ; i++ {
			j.tg.Add()

			select {
			case <-j.tg.StopChan():
				j.tg.Done()
				return
			case <-time.After(time.Second * 120):
			}

			// Every 10 files, delete one file at random.
			if i%10 == 0 {
				randindex := mrand.Intn(len(files))
				if err := j.client.Post(fmt.Sprintf("/renter/delete/%v", files[randindex]), "", nil); err != nil {
					log.Printf("[%v jobStorageRenter ERROR: %v\n", j.siaDirectory, err)
				}
				files = append(files[:randindex], files[randindex+1:]...)
			}

			// Generate some random data to upload
			f, err := ioutil.TempFile("", "antfarm-renter")
			if err != nil {
				log.Printf("[%v jobStorageRenter ERROR: %v\n", j.siaDirectory, err)
			}
			defer os.Remove(f.Name())

			_, err = io.CopyN(f, rand.Reader, 500000000)
			if err != nil {
				log.Printf("[%v jobStorageRenter ERROR: %v\n", j.siaDirectory, err)
			}

			// Upload the random data
			if err = j.client.Post(fmt.Sprintf("/renter/upload/%v", f.Name()), fmt.Sprintf("source=%v", f.Name()), nil); err != nil {
				log.Printf("[%v jobStorageRenter ERROR: %v\n", j.siaDirectory, err)
			}

			files = append(files, f.Name())

			j.tg.Done()
		}
	}()
}
<commit_msg>delete one file every iteration after the first 10 uploads<commit_after>package main

import (
	"crypto/rand"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	mrand "math/rand"
	"os"
	"time"

	"github.com/NebulousLabs/Sia/api"
	"github.com/NebulousLabs/Sia/types"
)

// storageRenter unlocks the wallet, mines some currency, sets an allowance
// using that currency, and uploads some files.  It will periodically try to
// download those files, printing any errors that occur.
func (j *JobRunner) storageRenter() {
	done := make(chan struct{})
	defer close(done)

	j.tg.OnStop(func() {
		<-done
	})

	err := j.client.Post("/wallet/unlock", fmt.Sprintf("encryptionpassword=%s&dictionary=%s", j.walletPassword, "english"), nil)
	if err != nil {
		log.Printf("[%v jobStorageRenter ERROR]: %v\n", j.siaDirectory, err)
		return
	}

	err = j.client.Get("/miner/start", nil)
	if err != nil {
		log.Printf("[%v jobStorageRenter ERROR: %v\n", j.siaDirectory, err)
		return
	}

	// Mine at least 100,000 SC
	desiredbalance := types.NewCurrency64(100000).Mul(types.SiacoinPrecision)
	success := false
	for start := time.Now(); time.Since(start) < 5*time.Minute; {
		select {
		case <-j.tg.StopChan():
			return
		case <-time.After(time.Second):
		}

		var walletInfo api.WalletGET
		err = j.client.Get("/wallet", &walletInfo)
		if err != nil {
			log.Printf("[%v jobStorageRenter ERROR]: %v\n", j.siaDirectory, err)
			return
		}
		if walletInfo.ConfirmedSiacoinBalance.Cmp(desiredbalance) > 0 {
			success = true
			break
		}
	}
	if !success {
		log.Printf("[%v jobStorageRenter ERROR]: timeout: could not mine enough currency after 5 minutes\n", j.siaDirectory)
		return
	}

	// Set an initial 50ksc allowance
	allowance := types.NewCurrency64(50000).Mul(types.SiacoinPrecision)
	if err := j.client.Post("/renter", fmt.Sprintf("funds=%v&period=100", allowance), nil); err != nil {
		log.Printf("[%v jobStorageRenter ERROR: %v\n", j.siaDirectory, err)
	}

	// Every 1000 seconds, set a new allowance.
	go func() {
		for {
			j.tg.Add()

			select {
			case <-j.tg.StopChan():
				j.tg.Done()
				return
			case <-time.After(time.Second * 1000):
			}

			// set an allowance of 50kSC + a random offset from 0-10ksc
			allowance := types.NewCurrency64(50000).Mul(types.SiacoinPrecision)
			if err := j.client.Post("/renter", fmt.Sprintf("funds=%v&period=100", allowance), nil); err != nil {
				log.Printf("[%v jobStorageRenter ERROR: %v\n", j.siaDirectory, err)
			}

			j.tg.Done()
		}
	}()

	// Every 120 seconds, upload a 500MB file.  Delete one file at random once every 10 files.
	go func() {
		var files []string
		for i := 0; ; i++ {
			j.tg.Add()

			select {
			case <-j.tg.StopChan():
				j.tg.Done()
				return
			case <-time.After(time.Second * 120):
			}

			// After 10 files, delete one file at random every iteration.
			if i >= 10 {
				randindex := mrand.Intn(len(files))
				if err := j.client.Post(fmt.Sprintf("/renter/delete/%v", files[randindex]), "", nil); err != nil {
					log.Printf("[%v jobStorageRenter ERROR: %v\n", j.siaDirectory, err)
				}
				files = append(files[:randindex], files[randindex+1:]...)
			}

			// Generate some random data to upload
			f, err := ioutil.TempFile("", "antfarm-renter")
			if err != nil {
				log.Printf("[%v jobStorageRenter ERROR: %v\n", j.siaDirectory, err)
			}
			defer os.Remove(f.Name())

			_, err = io.CopyN(f, rand.Reader, 500000000)
			if err != nil {
				log.Printf("[%v jobStorageRenter ERROR: %v\n", j.siaDirectory, err)
			}

			// Upload the random data
			if err = j.client.Post(fmt.Sprintf("/renter/upload/%v", f.Name()), fmt.Sprintf("source=%v", f.Name()), nil); err != nil {
				log.Printf("[%v jobStorageRenter ERROR: %v\n", j.siaDirectory, err)
			}

			files = append(files, f.Name())

			j.tg.Done()
		}
	}()
}
<|endoftext|>


<commit_before>// Copyright 2014 The Go 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 main

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"regexp"
	"runtime"
	"strings"
)

// Branch describes a Git branch.
type Branch struct {
	Name          string    // branch name
	loadedPending bool      // following fields are valid
	originBranch  string    // upstream origin branch
	commitsAhead  int       // number of commits ahead of origin branch
	commitsBehind int       // number of commits behind origin branch
	branchpoint   string    // latest commit hash shared with origin branch
	pending       []*Commit // pending commits, newest first (children before parents)
}

// A Commit describes a single pending commit on a Git branch.
type Commit struct {
	Hash      string // commit hash
	ShortHash string // abbreviated commit hash
	Parent    string // parent hash
	Merge     string // for merges, hash of commit being merged into Parent
	Message   string // commit message
	Subject   string // first line of commit message
	ChangeID  string // Change-Id in commit message ("" if missing)

	// For use by pending command.
	g         *GerritChange // associated Gerrit change data
	gerr      error         // error loading Gerrit data
	committed []string      // list of files in this commit
}

// CurrentBranch returns the current branch.
func CurrentBranch() *Branch {
	name := strings.TrimPrefix(trim(cmdOutput("git", "rev-parse", "--abbrev-ref", "HEAD")), "heads/")
	return &Branch{Name: name}
}

// DetachedHead reports whether branch b corresponds to a detached HEAD
// (does not have a real branch name).
func (b *Branch) DetachedHead() bool {
	return b.Name == "HEAD"
}

// OriginBranch returns the name of the origin branch that branch b tracks.
// The returned name is like "origin/master" or "origin/dev.garbage" or
// "origin/release-branch.go1.4".
func (b *Branch) OriginBranch() string {
	if b.DetachedHead() {
		// Detached head mode.
		// "origin/HEAD" is clearly false, but it should be easy to find when it
		// appears in other commands. Really any caller of OriginBranch
		// should check for detached head mode.
		return "origin/HEAD"
	}

	if b.originBranch != "" {
		return b.originBranch
	}
	argv := []string{"git", "rev-parse", "--abbrev-ref", b.Name + "@{u}"}
	cmd := exec.Command(argv[0], argv[1:]...)
	if runtime.GOOS == "windows" {
		// Workaround on windows. git for windows can't handle @{u} as same as
		// given. Disable glob for this command if running on Cygwin or MSYS2.
		envs := os.Environ()
		envs = append(envs, "CYGWIN=noglob "+os.Getenv("CYGWIN"))
		envs = append(envs, "MSYS=noglob "+os.Getenv("MSYS"))
		cmd.Env = envs
	}

	out, err := cmd.CombinedOutput()
	if err == nil && len(out) > 0 {
		b.originBranch = string(bytes.TrimSpace(out))
		return b.originBranch
	}

	// Have seen both "No upstream configured" and "no upstream configured".
	if strings.Contains(string(out), "upstream configured") {
		// Assume branch was created before we set upstream correctly.
		b.originBranch = "origin/master"
		return b.originBranch
	}
	fmt.Fprintf(stderr(), "%v\n%s\n", commandString(argv[0], argv[1:]), out)
	dief("%v", err)
	panic("not reached")
}

func (b *Branch) FullName() string {
	if b.Name != "HEAD" {
		return "refs/heads/" + b.Name
	}
	return b.Name
}

// IsLocalOnly reports whether b is a local work branch (only local, not known to remote server).
func (b *Branch) IsLocalOnly() bool {
	return "origin/"+b.Name != b.OriginBranch()
}

// HasPendingCommit reports whether b has any pending commits.
func (b *Branch) HasPendingCommit() bool {
	b.loadPending()
	return b.commitsAhead > 0
}

// Pending returns b's pending commits, newest first (children before parents).
func (b *Branch) Pending() []*Commit {
	b.loadPending()
	return b.pending
}

// Branchpoint returns an identifier for the latest revision
// common to both this branch and its upstream branch.
func (b *Branch) Branchpoint() string {
	b.loadPending()
	return b.branchpoint
}

func (b *Branch) loadPending() {
	if b.loadedPending {
		return
	}
	b.loadedPending = true

	// In case of early return.
	b.branchpoint = trim(cmdOutput("git", "rev-parse", "HEAD"))

	if b.DetachedHead() {
		return
	}

	// Note: --topo-order means child first, then parent.
	origin := b.OriginBranch()
	const numField = 5
	all := trim(cmdOutput("git", "log", "--topo-order", "--format=format:%H%x00%h%x00%P%x00%B%x00%s%x00", origin+".."+b.FullName(), "--"))
	fields := strings.Split(all, "\x00")
	if len(fields) < numField {
		return // nothing pending
	}
	for i, field := range fields {
		fields[i] = strings.TrimLeft(field, "\r\n")
	}
	foundMergeBranchpoint := false
	for i := 0; i+numField <= len(fields); i += numField {
		c := &Commit{
			Hash:      fields[i],
			ShortHash: fields[i+1],
			Parent:    strings.TrimSpace(fields[i+2]), // %P starts with \n for some reason
			Message:   fields[i+3],
			Subject:   fields[i+4],
		}
		if j := strings.Index(c.Parent, " "); j >= 0 {
			c.Parent, c.Merge = c.Parent[:j], c.Parent[j+1:]
			// Found merge point.
			// Merges break the invariant that the last shared commit (the branchpoint)
			// is the parent of the final commit in the log output.
			// If c.Parent is on the origin branch, then since we are reading the log
			// in (reverse) topological order, we know that c.Parent is the actual branchpoint,
			// even if we later see additional commits on a different branch leading down to
			// a lower location on the same origin branch.
			// Check c.Merge (the second parent) too, so we don't depend on the parent order.
			if strings.Contains(cmdOutput("git", "branch", "-a", "--contains", c.Parent), " "+origin+"\n") {
				foundMergeBranchpoint = true
				b.branchpoint = c.Parent
			}
			if strings.Contains(cmdOutput("git", "branch", "-a", "--contains", c.Merge), " "+origin+"\n") {
				foundMergeBranchpoint = true
				b.branchpoint = c.Merge
			}
		}
		for _, line := range lines(c.Message) {
			// Note: Keep going even if we find one, so that
			// we take the last Change-Id line, just in case
			// there is a commit message quoting another
			// commit message.
			// I'm not sure this can come up at all, but just in case.
			if strings.HasPrefix(line, "Change-Id: ") {
				c.ChangeID = line[len("Change-Id: "):]
			}
		}

		b.pending = append(b.pending, c)
		if !foundMergeBranchpoint {
			b.branchpoint = c.Parent
		}
	}
	b.commitsAhead = len(b.pending)
	b.commitsBehind = len(lines(cmdOutput("git", "log", "--format=format:x", b.FullName()+".."+b.OriginBranch(), "--")))
}

// Submitted reports whether some form of b's pending commit
// has been cherry picked to origin.
func (b *Branch) Submitted(id string) bool {
	if id == "" {
		return false
	}
	line := "Change-Id: " + id
	out := cmdOutput("git", "log", "-n", "1", "-F", "--grep", line, b.Name+".."+b.OriginBranch(), "--")
	return strings.Contains(out, line)
}

var stagedRE = regexp.MustCompile(`^[ACDMR]  `)

// HasStagedChanges reports whether the working directory contains staged changes.
func HasStagedChanges() bool {
	for _, s := range nonBlankLines(cmdOutput("git", "status", "-b", "--porcelain")) {
		if stagedRE.MatchString(s) {
			return true
		}
	}
	return false
}

var unstagedRE = regexp.MustCompile(`^.[ACDMR]`)

// HasUnstagedChanges reports whether the working directory contains unstaged changes.
func HasUnstagedChanges() bool {
	for _, s := range nonBlankLines(cmdOutput("git", "status", "-b", "--porcelain")) {
		if unstagedRE.MatchString(s) {
			return true
		}
	}
	return false
}

// LocalChanges returns a list of files containing staged, unstaged, and untracked changes.
// The elements of the returned slices are typically file names, always relative to the root,
// but there are a few alternate forms. First, for renaming or copying, the element takes
// the form `from -> to`. Second, in the case of files with names that contain unusual characters,
// the files (or the from, to fields of a rename or copy) are quoted C strings.
// For now, we expect the caller only shows these to the user, so these exceptions are okay.
func LocalChanges() (staged, unstaged, untracked []string) {
	for _, s := range lines(cmdOutput("git", "status", "-b", "--porcelain")) {
		if len(s) < 4 || s[2] != ' ' {
			continue
		}
		switch s[0] {
		case 'A', 'C', 'D', 'M', 'R':
			staged = append(staged, s[3:])
		case '?':
			untracked = append(untracked, s[3:])
		}
		switch s[1] {
		case 'A', 'C', 'D', 'M', 'R':
			unstaged = append(unstaged, s[3:])
		}
	}
	return
}

// LocalBranches returns a list of all known local branches.
// If the current directory is in detached HEAD mode, one returned
// branch will have Name == "HEAD" and DetachedHead() == true.
func LocalBranches() []*Branch {
	var branches []*Branch
	current := CurrentBranch()
	for _, s := range nonBlankLines(cmdOutput("git", "branch", "-q")) {
		s = strings.TrimSpace(s)
		if strings.HasPrefix(s, "* ") {
			// * marks current branch in output.
			// Normally the current branch has a name like any other,
			// but in detached HEAD mode the branch listing shows
			// a localized (translated) textual description instead of
			// a branch name. Avoid language-specific differences
			// by using CurrentBranch().Name for the current branch.
			// It detects detached HEAD mode in a more portable way.
			// (git rev-parse --abbrev-ref HEAD returns 'HEAD').
			s = current.Name
		}
		branches = append(branches, &Branch{Name: s})
	}
	return branches
}

func OriginBranches() []string {
	var branches []string
	for _, line := range nonBlankLines(cmdOutput("git", "branch", "-a", "-q")) {
		line = strings.TrimSpace(line)
		if i := strings.Index(line, " -> "); i >= 0 {
			line = line[:i]
		}
		name := strings.TrimSpace(strings.TrimPrefix(line, "* "))
		if strings.HasPrefix(name, "remotes/origin/") {
			branches = append(branches, strings.TrimPrefix(name, "remotes/"))
		}
	}
	return branches
}

// GerritChange returns the change metadata from the Gerrit server
// for the branch's pending change.
// The extra strings are passed to the Gerrit API request as o= parameters,
// to enable additional information. Typical values include "LABELS" and "CURRENT_REVISION".
// See https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html for details.
func (b *Branch) GerritChange(c *Commit, extra ...string) (*GerritChange, error) {
	if !b.HasPendingCommit() {
		return nil, fmt.Errorf("no changes pending")
	}
	id := fullChangeID(b, c)
	for i, x := range extra {
		if i == 0 {
			id += "?"
		} else {
			id += "&"
		}
		id += "o=" + x
	}
	return readGerritChange(id)
}

// CommitByRev finds a unique pending commit by its git <rev>.
// It dies if rev cannot be resolved to a commit or that commit is not
// pending on b using the action ("mail", "submit") in the failure message.
func (b *Branch) CommitByRev(action, rev string) *Commit {
	// Parse rev to a commit hash.
	hash, err := cmdOutputErr("git", "rev-parse", "--verify", rev+"^{commit}")
	if err != nil {
		msg := strings.TrimPrefix(trim(err.Error()), "fatal: ")
		dief("cannot %s: %s", action, msg)
	}
	hash = trim(hash)

	// Check that hash is a pending commit.
	var c *Commit
	for _, c1 := range b.Pending() {
		if c1.Hash == hash {
			c = c1
			break
		}
	}
	if c == nil {
		dief("cannot %s: commit hash %q not found in the current branch", action, hash)
	}
	return c
}

// DefaultCommit returns the default pending commit for this branch.
// It dies if there is not exactly one pending commit,
// using the action (e.g. "mail", "submit") and optional extra instructions
// in the failure message.
func (b *Branch) DefaultCommit(action, extra string) *Commit {
	work := b.Pending()
	if len(work) == 0 {
		dief("cannot %s: no changes pending", action)
	}
	if len(work) >= 2 {
		var buf bytes.Buffer
		for _, c := range work {
			fmt.Fprintf(&buf, "\n\t%s %s", c.ShortHash, c.Subject)
		}
		if extra != "" {
			extra = "; " + extra
		}
		dief("cannot %s: multiple changes pending%s:%s", action, extra, buf.String())
	}
	return work[0]
}

// ListFiles returns the list of files in a given commit.
func ListFiles(c *Commit) []string {
	return nonBlankLines(cmdOutput("git", "diff", "--name-only", c.Parent, c.Hash, "--"))
}

func cmdBranchpoint(args []string) {
	expectZeroArgs(args, "sync")
	fmt.Fprintf(stdout(), "%s\n", CurrentBranch().Branchpoint())
}

func cmdRebaseWork(args []string) {
	expectZeroArgs(args, "rebase-work")
	b := CurrentBranch()
	if HasStagedChanges() || HasUnstagedChanges() {
		dief("cannot rebase with uncommitted work")
	}
	if len(b.Pending()) == 0 {
		dief("no pending work")
	}
	run("git", "rebase", "-i", b.Branchpoint())
}
<commit_msg>git-codereview: avoid Gerrit timeout for missing Change-Id during pending<commit_after>// Copyright 2014 The Go 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 main

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"regexp"
	"runtime"
	"strings"
)

// Branch describes a Git branch.
type Branch struct {
	Name          string    // branch name
	loadedPending bool      // following fields are valid
	originBranch  string    // upstream origin branch
	commitsAhead  int       // number of commits ahead of origin branch
	commitsBehind int       // number of commits behind origin branch
	branchpoint   string    // latest commit hash shared with origin branch
	pending       []*Commit // pending commits, newest first (children before parents)
}

// A Commit describes a single pending commit on a Git branch.
type Commit struct {
	Hash      string // commit hash
	ShortHash string // abbreviated commit hash
	Parent    string // parent hash
	Merge     string // for merges, hash of commit being merged into Parent
	Message   string // commit message
	Subject   string // first line of commit message
	ChangeID  string // Change-Id in commit message ("" if missing)

	// For use by pending command.
	g         *GerritChange // associated Gerrit change data
	gerr      error         // error loading Gerrit data
	committed []string      // list of files in this commit
}

// CurrentBranch returns the current branch.
func CurrentBranch() *Branch {
	name := strings.TrimPrefix(trim(cmdOutput("git", "rev-parse", "--abbrev-ref", "HEAD")), "heads/")
	return &Branch{Name: name}
}

// DetachedHead reports whether branch b corresponds to a detached HEAD
// (does not have a real branch name).
func (b *Branch) DetachedHead() bool {
	return b.Name == "HEAD"
}

// OriginBranch returns the name of the origin branch that branch b tracks.
// The returned name is like "origin/master" or "origin/dev.garbage" or
// "origin/release-branch.go1.4".
func (b *Branch) OriginBranch() string {
	if b.DetachedHead() {
		// Detached head mode.
		// "origin/HEAD" is clearly false, but it should be easy to find when it
		// appears in other commands. Really any caller of OriginBranch
		// should check for detached head mode.
		return "origin/HEAD"
	}

	if b.originBranch != "" {
		return b.originBranch
	}
	argv := []string{"git", "rev-parse", "--abbrev-ref", b.Name + "@{u}"}
	cmd := exec.Command(argv[0], argv[1:]...)
	if runtime.GOOS == "windows" {
		// Workaround on windows. git for windows can't handle @{u} as same as
		// given. Disable glob for this command if running on Cygwin or MSYS2.
		envs := os.Environ()
		envs = append(envs, "CYGWIN=noglob "+os.Getenv("CYGWIN"))
		envs = append(envs, "MSYS=noglob "+os.Getenv("MSYS"))
		cmd.Env = envs
	}

	out, err := cmd.CombinedOutput()
	if err == nil && len(out) > 0 {
		b.originBranch = string(bytes.TrimSpace(out))
		return b.originBranch
	}

	// Have seen both "No upstream configured" and "no upstream configured".
	if strings.Contains(string(out), "upstream configured") {
		// Assume branch was created before we set upstream correctly.
		b.originBranch = "origin/master"
		return b.originBranch
	}
	fmt.Fprintf(stderr(), "%v\n%s\n", commandString(argv[0], argv[1:]), out)
	dief("%v", err)
	panic("not reached")
}

func (b *Branch) FullName() string {
	if b.Name != "HEAD" {
		return "refs/heads/" + b.Name
	}
	return b.Name
}

// IsLocalOnly reports whether b is a local work branch (only local, not known to remote server).
func (b *Branch) IsLocalOnly() bool {
	return "origin/"+b.Name != b.OriginBranch()
}

// HasPendingCommit reports whether b has any pending commits.
func (b *Branch) HasPendingCommit() bool {
	b.loadPending()
	return b.commitsAhead > 0
}

// Pending returns b's pending commits, newest first (children before parents).
func (b *Branch) Pending() []*Commit {
	b.loadPending()
	return b.pending
}

// Branchpoint returns an identifier for the latest revision
// common to both this branch and its upstream branch.
func (b *Branch) Branchpoint() string {
	b.loadPending()
	return b.branchpoint
}

func (b *Branch) loadPending() {
	if b.loadedPending {
		return
	}
	b.loadedPending = true

	// In case of early return.
	b.branchpoint = trim(cmdOutput("git", "rev-parse", "HEAD"))

	if b.DetachedHead() {
		return
	}

	// Note: --topo-order means child first, then parent.
	origin := b.OriginBranch()
	const numField = 5
	all := trim(cmdOutput("git", "log", "--topo-order", "--format=format:%H%x00%h%x00%P%x00%B%x00%s%x00", origin+".."+b.FullName(), "--"))
	fields := strings.Split(all, "\x00")
	if len(fields) < numField {
		return // nothing pending
	}
	for i, field := range fields {
		fields[i] = strings.TrimLeft(field, "\r\n")
	}
	foundMergeBranchpoint := false
	for i := 0; i+numField <= len(fields); i += numField {
		c := &Commit{
			Hash:      fields[i],
			ShortHash: fields[i+1],
			Parent:    strings.TrimSpace(fields[i+2]), // %P starts with \n for some reason
			Message:   fields[i+3],
			Subject:   fields[i+4],
		}
		if j := strings.Index(c.Parent, " "); j >= 0 {
			c.Parent, c.Merge = c.Parent[:j], c.Parent[j+1:]
			// Found merge point.
			// Merges break the invariant that the last shared commit (the branchpoint)
			// is the parent of the final commit in the log output.
			// If c.Parent is on the origin branch, then since we are reading the log
			// in (reverse) topological order, we know that c.Parent is the actual branchpoint,
			// even if we later see additional commits on a different branch leading down to
			// a lower location on the same origin branch.
			// Check c.Merge (the second parent) too, so we don't depend on the parent order.
			if strings.Contains(cmdOutput("git", "branch", "-a", "--contains", c.Parent), " "+origin+"\n") {
				foundMergeBranchpoint = true
				b.branchpoint = c.Parent
			}
			if strings.Contains(cmdOutput("git", "branch", "-a", "--contains", c.Merge), " "+origin+"\n") {
				foundMergeBranchpoint = true
				b.branchpoint = c.Merge
			}
		}
		for _, line := range lines(c.Message) {
			// Note: Keep going even if we find one, so that
			// we take the last Change-Id line, just in case
			// there is a commit message quoting another
			// commit message.
			// I'm not sure this can come up at all, but just in case.
			if strings.HasPrefix(line, "Change-Id: ") {
				c.ChangeID = line[len("Change-Id: "):]
			}
		}

		b.pending = append(b.pending, c)
		if !foundMergeBranchpoint {
			b.branchpoint = c.Parent
		}
	}
	b.commitsAhead = len(b.pending)
	b.commitsBehind = len(lines(cmdOutput("git", "log", "--format=format:x", b.FullName()+".."+b.OriginBranch(), "--")))
}

// Submitted reports whether some form of b's pending commit
// has been cherry picked to origin.
func (b *Branch) Submitted(id string) bool {
	if id == "" {
		return false
	}
	line := "Change-Id: " + id
	out := cmdOutput("git", "log", "-n", "1", "-F", "--grep", line, b.Name+".."+b.OriginBranch(), "--")
	return strings.Contains(out, line)
}

var stagedRE = regexp.MustCompile(`^[ACDMR]  `)

// HasStagedChanges reports whether the working directory contains staged changes.
func HasStagedChanges() bool {
	for _, s := range nonBlankLines(cmdOutput("git", "status", "-b", "--porcelain")) {
		if stagedRE.MatchString(s) {
			return true
		}
	}
	return false
}

var unstagedRE = regexp.MustCompile(`^.[ACDMR]`)

// HasUnstagedChanges reports whether the working directory contains unstaged changes.
func HasUnstagedChanges() bool {
	for _, s := range nonBlankLines(cmdOutput("git", "status", "-b", "--porcelain")) {
		if unstagedRE.MatchString(s) {
			return true
		}
	}
	return false
}

// LocalChanges returns a list of files containing staged, unstaged, and untracked changes.
// The elements of the returned slices are typically file names, always relative to the root,
// but there are a few alternate forms. First, for renaming or copying, the element takes
// the form `from -> to`. Second, in the case of files with names that contain unusual characters,
// the files (or the from, to fields of a rename or copy) are quoted C strings.
// For now, we expect the caller only shows these to the user, so these exceptions are okay.
func LocalChanges() (staged, unstaged, untracked []string) {
	for _, s := range lines(cmdOutput("git", "status", "-b", "--porcelain")) {
		if len(s) < 4 || s[2] != ' ' {
			continue
		}
		switch s[0] {
		case 'A', 'C', 'D', 'M', 'R':
			staged = append(staged, s[3:])
		case '?':
			untracked = append(untracked, s[3:])
		}
		switch s[1] {
		case 'A', 'C', 'D', 'M', 'R':
			unstaged = append(unstaged, s[3:])
		}
	}
	return
}

// LocalBranches returns a list of all known local branches.
// If the current directory is in detached HEAD mode, one returned
// branch will have Name == "HEAD" and DetachedHead() == true.
func LocalBranches() []*Branch {
	var branches []*Branch
	current := CurrentBranch()
	for _, s := range nonBlankLines(cmdOutput("git", "branch", "-q")) {
		s = strings.TrimSpace(s)
		if strings.HasPrefix(s, "* ") {
			// * marks current branch in output.
			// Normally the current branch has a name like any other,
			// but in detached HEAD mode the branch listing shows
			// a localized (translated) textual description instead of
			// a branch name. Avoid language-specific differences
			// by using CurrentBranch().Name for the current branch.
			// It detects detached HEAD mode in a more portable way.
			// (git rev-parse --abbrev-ref HEAD returns 'HEAD').
			s = current.Name
		}
		branches = append(branches, &Branch{Name: s})
	}
	return branches
}

func OriginBranches() []string {
	var branches []string
	for _, line := range nonBlankLines(cmdOutput("git", "branch", "-a", "-q")) {
		line = strings.TrimSpace(line)
		if i := strings.Index(line, " -> "); i >= 0 {
			line = line[:i]
		}
		name := strings.TrimSpace(strings.TrimPrefix(line, "* "))
		if strings.HasPrefix(name, "remotes/origin/") {
			branches = append(branches, strings.TrimPrefix(name, "remotes/"))
		}
	}
	return branches
}

// GerritChange returns the change metadata from the Gerrit server
// for the branch's pending change.
// The extra strings are passed to the Gerrit API request as o= parameters,
// to enable additional information. Typical values include "LABELS" and "CURRENT_REVISION".
// See https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html for details.
func (b *Branch) GerritChange(c *Commit, extra ...string) (*GerritChange, error) {
	if !b.HasPendingCommit() {
		return nil, fmt.Errorf("no changes pending")
	}
	if c.ChangeID == "" {
		return nil, fmt.Errorf("missing Change-Id")
	}
	id := fullChangeID(b, c)
	for i, x := range extra {
		if i == 0 {
			id += "?"
		} else {
			id += "&"
		}
		id += "o=" + x
	}
	return readGerritChange(id)
}

// CommitByRev finds a unique pending commit by its git <rev>.
// It dies if rev cannot be resolved to a commit or that commit is not
// pending on b using the action ("mail", "submit") in the failure message.
func (b *Branch) CommitByRev(action, rev string) *Commit {
	// Parse rev to a commit hash.
	hash, err := cmdOutputErr("git", "rev-parse", "--verify", rev+"^{commit}")
	if err != nil {
		msg := strings.TrimPrefix(trim(err.Error()), "fatal: ")
		dief("cannot %s: %s", action, msg)
	}
	hash = trim(hash)

	// Check that hash is a pending commit.
	var c *Commit
	for _, c1 := range b.Pending() {
		if c1.Hash == hash {
			c = c1
			break
		}
	}
	if c == nil {
		dief("cannot %s: commit hash %q not found in the current branch", action, hash)
	}
	return c
}

// DefaultCommit returns the default pending commit for this branch.
// It dies if there is not exactly one pending commit,
// using the action (e.g. "mail", "submit") and optional extra instructions
// in the failure message.
func (b *Branch) DefaultCommit(action, extra string) *Commit {
	work := b.Pending()
	if len(work) == 0 {
		dief("cannot %s: no changes pending", action)
	}
	if len(work) >= 2 {
		var buf bytes.Buffer
		for _, c := range work {
			fmt.Fprintf(&buf, "\n\t%s %s", c.ShortHash, c.Subject)
		}
		if extra != "" {
			extra = "; " + extra
		}
		dief("cannot %s: multiple changes pending%s:%s", action, extra, buf.String())
	}
	return work[0]
}

// ListFiles returns the list of files in a given commit.
func ListFiles(c *Commit) []string {
	return nonBlankLines(cmdOutput("git", "diff", "--name-only", c.Parent, c.Hash, "--"))
}

func cmdBranchpoint(args []string) {
	expectZeroArgs(args, "sync")
	fmt.Fprintf(stdout(), "%s\n", CurrentBranch().Branchpoint())
}

func cmdRebaseWork(args []string) {
	expectZeroArgs(args, "rebase-work")
	b := CurrentBranch()
	if HasStagedChanges() || HasUnstagedChanges() {
		dief("cannot rebase with uncommitted work")
	}
	if len(b.Pending()) == 0 {
		dief("no pending work")
	}
	run("git", "rebase", "-i", b.Branchpoint())
}
<|endoftext|>


<commit_before>package servers

import (
	val "github.com/asaskevich/govalidator"
	"github.com/ncodes/patchain"
	"github.com/ncodes/patchain/cockroach/tables"
	"github.com/ncodes/patchain/object"
	"github.com/ncodes/safehold/servers/common"
	"github.com/ncodes/safehold/servers/proto_rpc"
	"golang.org/x/crypto/bcrypt"
	"golang.org/x/net/context"
)

// validateIdentity validates a requested identity
func validateIdentity(req *proto_rpc.CreateIdentityMsg) []common.Error {
	var errs []common.Error
	if val.IsNull(req.Email) {
		errs = append(errs, common.Error{Code: common.CodeInvalidParam, Message: "Email is required", Field: "email"})
	}
	if !val.IsEmail(req.Email) {
		errs = append(errs, common.Error{Code: common.CodeInvalidParam, Message: "Email is not valid", Field: "email"})
	}
	if val.IsNull(req.Password) {
		errs = append(errs, common.Error{Code: common.CodeInvalidParam, Message: "Password is required", Field: "password"})
	}
	if len(req.Password) < 6 {
		errs = append(errs, common.Error{Code: common.CodeInvalidParam, Message: "Password is too short. Must be at least 6 characters long", Field: "password"})
	}
	return errs
}

// getSystemIdentity returns system identity or a response error
func (s *RPC) getSystemIdentity() (*tables.Object, error) {
	obj, err := s.object.GetLast(&tables.Object{Key: object.MakeIdentityKey(systemEmail)})
	if err != nil {
		if err == patchain.ErrNotFound {
			return nil, common.NewSingleAPIErr(400, "", "", "system identity not found", nil)
		}
		return nil, common.ServerError
	}
	return obj, nil
}

// CreateIdentity creates a new identity for object
func (s *RPC) CreateIdentity(ctx context.Context, req *proto_rpc.CreateIdentityMsg) (*proto_rpc.ObjectResponse, error) {

	// validate request
	if errs := validateIdentity(req); len(errs) > 0 {
		return nil, common.NewMultiAPIErr(400, "validation errors", errs)
	}

	systemIdentity, err := s.getSystemIdentity()
	if err != nil {
		logRPC.Errorf("%+v", err)
		return nil, err
	}

	objHandler := object.NewObject(s.db)

	// get existing identity
	existingIdentity, err := objHandler.GetLast(&tables.Object{OwnerID: systemIdentity.ID, QueryParams: patchain.KeyStartsWith(object.MakeIdentityKey(req.Email))})
	if err != nil {
		if err != patchain.ErrNotFound {
			return nil, common.ServerError
		}
	}

	// check if existing identity has been confirmed
	if err == nil {
		if existingIdentity.Ref3 == "confirmed" {
			return nil, common.NewSingleAPIErr(400, "used_email", "email", "Email is not available", nil)
		}
	}

	var numPartitions = int64(5)
	var newIdentity *tables.Object

	// create the identity and partitions
	var do = func() error {
		return s.db.Transact(func(txDB patchain.DB, commit patchain.CommitFunc, rollback patchain.RollbackFunc) error {

			var err error
			dbOpt := &patchain.UseDBOption{DB: txDB}
			passwordHash, _ := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)

			if req.Developer {
				newIdentity = object.MakeDeveloperIdentityObject(systemIdentity.ID, systemIdentity.ID, req.Email, string(passwordHash), true)
			} else {
				newIdentity = object.MakeIdentityObject(systemIdentity.ID, systemIdentity.ID, req.Email, string(passwordHash), true)
			}

			err = s.object.Put(newIdentity, dbOpt)
			if err != nil {
				return err
			}

			_, err = s.object.CreatePartitions(numPartitions, newIdentity.ID, systemIdentity.ID, dbOpt)
			if err != nil {
				return err
			}

			return nil
		})
	}

	err = objHandler.Retry(func(stopRetry func()) error { return do() })
	if err != nil {
		logRPC.Errorf("%+v", err)
		return nil, common.ServerError
	}

	// TODO: send confirmation notification to email

	resp, _ := NewObjectResponse("identity", newIdentity, nil)
	return resp, nil
}

// GetIdentity fetches an identity object
func (s *RPC) GetIdentity(ctx context.Context, req *proto_rpc.GetIdentityMsg) (*proto_rpc.ObjectResponse, error) {

	objHandler := object.NewObject(s.db)

	identity, err := objHandler.GetLast(&tables.Object{Key: object.MakeIdentityKey(req.ID)})
	if err != nil {
		if err == patchain.ErrNotFound {
			return nil, common.NewSingleAPIErr(404, "", "", "Identity not found", nil)
		}
	}

	resp, _ := NewObjectResponse("identity", identity, nil)
	return resp, nil
}
<commit_msg>Allow identities to be fetched by ID and Email<commit_after>package servers

import (
	"github.com/asaskevich/govalidator"
	val "github.com/asaskevich/govalidator"
	"github.com/ncodes/patchain"
	"github.com/ncodes/patchain/cockroach/tables"
	"github.com/ncodes/patchain/object"
	"github.com/ncodes/safehold/servers/common"
	"github.com/ncodes/safehold/servers/proto_rpc"
	"golang.org/x/crypto/bcrypt"
	"golang.org/x/net/context"
)

// validateIdentity validates a requested identity
func validateIdentity(req *proto_rpc.CreateIdentityMsg) []common.Error {
	var errs []common.Error
	if val.IsNull(req.Email) {
		errs = append(errs, common.Error{Code: common.CodeInvalidParam, Message: "Email is required", Field: "email"})
	}
	if !val.IsEmail(req.Email) {
		errs = append(errs, common.Error{Code: common.CodeInvalidParam, Message: "Email is not valid", Field: "email"})
	}
	if val.IsNull(req.Password) {
		errs = append(errs, common.Error{Code: common.CodeInvalidParam, Message: "Password is required", Field: "password"})
	}
	if len(req.Password) < 6 {
		errs = append(errs, common.Error{Code: common.CodeInvalidParam, Message: "Password is too short. Must be at least 6 characters long", Field: "password"})
	}
	return errs
}

// getSystemIdentity returns system identity or a response error
func (s *RPC) getSystemIdentity() (*tables.Object, error) {
	obj, err := s.object.GetLast(&tables.Object{Key: object.MakeIdentityKey(systemEmail)})
	if err != nil {
		if err == patchain.ErrNotFound {
			return nil, common.NewSingleAPIErr(400, "", "", "system identity not found", nil)
		}
		return nil, common.ServerError
	}
	return obj, nil
}

// CreateIdentity creates a new identity for object
func (s *RPC) CreateIdentity(ctx context.Context, req *proto_rpc.CreateIdentityMsg) (*proto_rpc.ObjectResponse, error) {

	// validate request
	if errs := validateIdentity(req); len(errs) > 0 {
		return nil, common.NewMultiAPIErr(400, "validation errors", errs)
	}

	systemIdentity, err := s.getSystemIdentity()
	if err != nil {
		logRPC.Errorf("%+v", err)
		return nil, err
	}

	objHandler := object.NewObject(s.db)

	// get existing identity
	existingIdentity, err := objHandler.GetLast(&tables.Object{OwnerID: systemIdentity.ID, QueryParams: patchain.KeyStartsWith(object.MakeIdentityKey(req.Email))})
	if err != nil {
		if err != patchain.ErrNotFound {
			return nil, common.ServerError
		}
	}

	// check if existing identity has been confirmed
	if err == nil {
		if existingIdentity.Ref3 == "confirmed" {
			return nil, common.NewSingleAPIErr(400, "used_email", "email", "Email is not available", nil)
		}
	}

	var numPartitions = int64(5)
	var newIdentity *tables.Object

	// create the identity and partitions
	var do = func() error {
		return s.db.Transact(func(txDB patchain.DB, commit patchain.CommitFunc, rollback patchain.RollbackFunc) error {

			var err error
			dbOpt := &patchain.UseDBOption{DB: txDB}
			passwordHash, _ := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)

			if req.Developer {
				newIdentity = object.MakeDeveloperIdentityObject(systemIdentity.ID, systemIdentity.ID, req.Email, string(passwordHash), true)
			} else {
				newIdentity = object.MakeIdentityObject(systemIdentity.ID, systemIdentity.ID, req.Email, string(passwordHash), true)
			}

			err = s.object.Put(newIdentity, dbOpt)
			if err != nil {
				return err
			}

			_, err = s.object.CreatePartitions(numPartitions, newIdentity.ID, systemIdentity.ID, dbOpt)
			if err != nil {
				return err
			}

			return nil
		})
	}

	err = objHandler.Retry(func(stopRetry func()) error { return do() })
	if err != nil {
		logRPC.Errorf("%+v", err)
		return nil, common.ServerError
	}

	// TODO: send confirmation notification to email

	resp, _ := NewObjectResponse("identity", newIdentity, nil)
	return resp, nil
}

// GetIdentity fetches an identity object
func (s *RPC) GetIdentity(ctx context.Context, req *proto_rpc.GetIdentityMsg) (*proto_rpc.ObjectResponse, error) {

	var err error
	var identity *tables.Object
	objHandler := object.NewObject(s.db)

	if govalidator.IsEmail(req.ID) {
		identity, err = objHandler.GetLast(&tables.Object{Key: object.MakeIdentityKey(req.ID)})
	} else {
		identity, err = objHandler.GetLast(&tables.Object{ID: req.ID, QueryParams: patchain.KeyStartsWith(object.IdentityPrefix)})
	}

	if err != nil {
		if err == patchain.ErrNotFound {
			return nil, common.NewSingleAPIErr(404, "", "", "Identity not found", nil)
		}
	}

	resp, _ := NewObjectResponse("identity", identity, nil)
	return resp, nil
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"strconv"
	"encoding/json"
	"github.com/hyperledger/fabric/core/chaincode/shim"
	"github.com/hyperledger/fabric/core/util"
)

type Chaincode struct { }

type ChaincodeFunctions struct {
	stub shim.ChaincodeStubInterface
}

func main() {
	err := shim.Start(new(Chaincode))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}

func (t Chaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	//fns := ChaincodeFunctions{stub}
	configJson := args[0]
	_ = args[1] // nonce to stop existing deal being returned
	_ = stub.PutState("dealConfig", []byte(configJson))
	_ = stub.PutState("dealStatus", []byte("draft")) // Possible Values [draft, open, closed, allocated]
	_ = stub.PutState("orderbook", []byte("{}"))
	return nil, nil
}

func (t Chaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("invoke is running " + function)
	fns := ChaincodeFunctions{stub}
	if function == "addOrder" {
		investor := args[0]
		ioi, err := strconv.ParseFloat(args[1], 64)
		if err != nil {
	        return nil, errors.New("Failed to parse " + args[1] + " as a float64")
    	}
		return fns.AddOrder(investor, ioi)
	} else if function == "allocateOrder" {
		investor := args[0]
		alloc, err := strconv.ParseFloat(args[1], 64)
		if err != nil {
	        return nil, errors.New("Failed to parse " + args[1] + " as a float64")
    	}
		return fns.AllocateOrder(investor, alloc)
	} else if function == "updateDealStatus" {
		status := args[0]
		return fns.UpdateDealStatus(status)
	} else if function == "confirmOrder" {
		investor := args[0]
		return fns.ConfirmOrder(investor)
	}
	fmt.Println("invoke did not find func: " + function)

	return nil, errors.New("Received unknown function invocation: " + function)
}

func (t Chaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("query is running " + function)
	fns := ChaincodeFunctions{stub}
	if function == "ping" {
		return fns.Ping()
	} else if function == "getDealConfig" {
		return fns.GetDealConfig()
	} else if function == "getOrder" {
		investor := args[0]
		return fns.GetOrder(investor)
	} else if function == "getOrderbook" {
		return fns.GetOrderbook()
	}
	fmt.Println("query did not find func: " + function)

	return nil, errors.New("Received unknown function query: " + function)
}

type DealConfig struct {
	Issuer 			string 		`json:"issuer"`
	Banks 			[]string 	`json:"banks"`
	BookStatus 		string 		`json:"bookStatus"`
	RequiredDocs	[]string	`json:"requiredDocs"`
	DocRegAddress 	string 		`json:"docRegAddress"`
}

type Order struct {
	Investor	string 		`json:"investor"`
	Ioi 		float64 	`json:"ioi"`
	Alloc 		float64		`json:"alloc"`
	Confirmed	bool		`json:"confirmed"`
}

// Public Functions

func (c ChaincodeFunctions) Ping() ([]byte, error) {
    return []byte("pong"), nil
}

func (c ChaincodeFunctions) GetDealConfig() ([]byte, error) {
	dealConfig, _ := c.stub.GetState("dealConfig")
	return dealConfig, nil
}

func (c ChaincodeFunctions) UpdateDealStatus(dealStatus string) ([]byte, error)  {
	dealConfig := c.getDealConfigFromBlockchain()
	dealConfig.BookStatus = dealStatus
	c.saveDealConfigToBlockchain(dealConfig)
	c.stub.SetEvent("Book Status Change", []byte("{\"status\":\"" + dealStatus + "\"}"))
	return nil, nil
}

func (c ChaincodeFunctions) AddOrder(investor string, ioi float64) ([]byte, error)  {
	dealConfig := c.getDealConfigFromBlockchain()
	if dealConfig.BookStatus != "open" {
		c.stub.SetEvent("Permission Denied", []byte("{\"reason\":\"book is not open\"}"))
		return nil, errors.New("Orders cannot be placed unless deal status is 'Open'")
	}
	if !c.checkInvestorHasRequiredDocs(dealConfig.DocRegAddress, investor, dealConfig.RequiredDocs) {
		c.stub.SetEvent("Permission Denied", []byte("{\"reason\":\"" + investor + " is not a QIB\"}"))
		return nil, errors.New("Order's cannot be placed without QIB status")
	}
	order := c.getOrderFromBlockChain(investor)
	if order.Investor == "" {
		order = Order{Investor: investor, Ioi: ioi, Alloc: 0.0, Confirmed: false}
	} else {
		order.Ioi = ioi
	}
	c.saveOrderToBlockChain(order)
	c.stub.SetEvent("Order Added", []byte("{\"investor\":\"" + investor + "\"}"))
	return nil, nil
}

func (c ChaincodeFunctions) ConfirmOrder(investor string) ([]byte, error) {
	dealConfig := c.getDealConfigFromBlockchain()
	if dealConfig.BookStatus != "allocated" {
		c.stub.SetEvent("Permission Denied", []byte("{\"reason\":\"book is not allocated\"}"))
		return nil, nil
	}
	order := c.getOrderFromBlockChain(investor)
	order.Confirmed = true
	c.saveOrderToBlockChain(order)
	c.stub.SetEvent("Order Confirmed", []byte("{\"investor\":\"" + investor + "\"}"))
	return nil, nil
}

func (c ChaincodeFunctions) GetOrder(investor string) ([]byte, error) {
	roleBytes, _ := c.stub.ReadCertAttribute("role")
	role := string(roleBytes)
	dealConfig := c.getDealConfigFromBlockchain()
	order := c.getOrderFromBlockChain(investor)
	if !canSeeAllocations(role, dealConfig) {
		order.Alloc = -1
	}
	orderJson, _ := json.Marshal(order)
	return []byte(orderJson), nil
}

func (c ChaincodeFunctions) GetOrderbook() ([]byte, error) {
	orderbookJson, _ := c.stub.GetState("orderbook")
	return []byte(orderbookJson), nil
}

func (c ChaincodeFunctions) AllocateOrder(investor string, alloc float64) ([]byte, error) {
	order := c.getOrderFromBlockChain(investor)
	order.Alloc = alloc
	c.saveOrderToBlockChain(order)
	c.stub.SetEvent("Order Allocated", []byte("{\"investor\":\"" + investor + "\"}"))
	return nil, nil
}

// Private Functions

func (c ChaincodeFunctions) getDealConfigFromBlockchain() DealConfig {
	dealConfigJson, _ := c.stub.GetState("dealConfig")
	var dealConfig DealConfig
	_ = json.Unmarshal(dealConfigJson, &dealConfig)
	return dealConfig
}

func (c ChaincodeFunctions) saveDealConfigToBlockchain(dealConfig DealConfig) {
	dealConfigJson, _ := json.Marshal(dealConfig)
	_ = c.stub.PutState("dealConfig", []byte(dealConfigJson))
}

func (c ChaincodeFunctions) getOrderAsJsonFromBlockchain(investor string) string {
	order := c.getOrderFromBlockChain(investor)
	orderJson, _ := json.Marshal(order)
	return string(orderJson)
}

func (c ChaincodeFunctions) getOrderFromBlockChain(investor string) Order {
	orderbook := c.getOrderbookFromBlockChain()
	return orderbook[investor]
}

func (c ChaincodeFunctions) saveOrderToBlockChain(order Order) {
	orderbook := c.getOrderbookFromBlockChain()
	orderbook[order.Investor] = order
	c.saveOrderbookToBlockChain(orderbook)
}

func (c ChaincodeFunctions) getOrderbookFromBlockChain() map[string]Order {
	orderbookJson, _ := c.stub.GetState("orderbook")
	var orderbook map[string]Order
	_ = json.Unmarshal(orderbookJson, &orderbook)
	return orderbook
}

func (c ChaincodeFunctions) saveOrderbookToBlockChain(orderbook map[string]Order) {
	orderbookJson, _ := json.Marshal(orderbook)
	_ = c.stub.PutState("orderbook", []byte(orderbookJson))
}

func (c ChaincodeFunctions) checkInvestorHasRequiredDocs(address string, company string, requiredDocs []string) bool {
	invokeArgs := util.ToChaincodeArgs("getDocs", company)
	docsJson, _ := c.stub.QueryChaincode(address, invokeArgs)
	var docs []string
	_ = json.Unmarshal(docsJson, &docs)
	for _, reqDoc := range requiredDocs {
		if !stringInSlice(reqDoc, docs) {
			return false
		}
	}
	return true
}

func stringInSlice(a string, list []string) bool {
    for _, b := range list {
        if b == a {
            return true
        }
    }
    return false
}

func canSeeAllocations(role string, dealConfig DealConfig) bool {
	if role != "investor" {
		return true
	} else if dealConfig.BookStatus == "draft" {
		return false
	} else if dealConfig.BookStatus == "open" {
		return false
	} else if dealConfig.BookStatus == "closed" {
		return false
	} else {
		return true
	}
}<commit_msg>batch check-in<commit_after>package main

import (
	"errors"
	"fmt"
	"strconv"
	"encoding/json"
	"github.com/hyperledger/fabric/core/chaincode/shim"
	"github.com/hyperledger/fabric/core/util"
)

type Chaincode struct { }

type ChaincodeFunctions struct {
	stub shim.ChaincodeStubInterface
}

func main() {
	err := shim.Start(new(Chaincode))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}

func (t Chaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	//fns := ChaincodeFunctions{stub}
	configJson := args[0]
	_ = args[1] // nonce to stop existing deal being returned
	_ = stub.PutState("dealConfig", []byte(configJson))
	_ = stub.PutState("dealStatus", []byte("draft")) // Possible Values [draft, open, closed, allocated]
	_ = stub.PutState("orderbook", []byte("{}"))
	return nil, nil
}

func (t Chaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("invoke is running " + function)
	fns := ChaincodeFunctions{stub}
	if function == "addOrder" {
		investor := args[0]
		ioi, err := strconv.ParseFloat(args[1], 64)
		if err != nil {
	        return nil, errors.New("Failed to parse " + args[1] + " as a float64")
    	}
		return fns.AddOrder(investor, ioi)
	} else if function == "allocateOrder" {
		investor := args[0]
		alloc, err := strconv.ParseFloat(args[1], 64)
		if err != nil {
	        return nil, errors.New("Failed to parse " + args[1] + " as a float64")
    	}
		return fns.AllocateOrder(investor, alloc)
	} else if function == "updateDealStatus" {
		status := args[0]
		return fns.UpdateDealStatus(status)
	} else if function == "confirmOrder" {
		investor := args[0]
		return fns.ConfirmOrder(investor)
	}
	fmt.Println("invoke did not find func: " + function)

	return nil, errors.New("Received unknown function invocation: " + function)
}

func (t Chaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("query is running " + function)
	fns := ChaincodeFunctions{stub}
	if function == "ping" {
		return fns.Ping()
	} else if function == "getDealConfig" {
		return fns.GetDealConfig()
	} else if function == "getOrder" {
		investor := args[0]
		return fns.GetOrder(investor)
	} else if function == "getOrderbook" {
		return fns.GetOrderbook()
	}
	fmt.Println("query did not find func: " + function)

	return nil, errors.New("Received unknown function query: " + function)
}

type DealConfig struct {
	Issuer 			string 		`json:"issuer"`
	Banks 			[]string 	`json:"banks"`
	BookStatus 		string 		`json:"bookStatus"`
	RequiredDocs	[]string	`json:"requiredDocs"`
	DocRegAddress 	string 		`json:"docRegAddress"`
}

type Order struct {
	Investor	string 		`json:"investor"`
	Ioi 		float64 	`json:"ioi"`
	Alloc 		float64		`json:"alloc"`
	Confirmed	bool		`json:"confirmed"`
}

// Public Functions

func (c ChaincodeFunctions) Ping() ([]byte, error) {
    return []byte("pong"), nil
}

func (c ChaincodeFunctions) GetDealConfig() ([]byte, error) {
	dealConfig, _ := c.stub.GetState("dealConfig")
	return dealConfig, nil
}

func (c ChaincodeFunctions) UpdateDealStatus(dealStatus string) ([]byte, error)  {
	dealConfig := c.getDealConfigFromBlockchain()
	dealConfig.BookStatus = dealStatus
	c.saveDealConfigToBlockchain(dealConfig)
	c.stub.SetEvent("Book Status Change", []byte("{\"status\":\"" + dealStatus + "\"}"))
	return nil, nil
}

func (c ChaincodeFunctions) AddOrder(investor string, ioi float64) ([]byte, error)  {
	dealConfig := c.getDealConfigFromBlockchain()
	if dealConfig.BookStatus != "open" {
		c.stub.SetEvent("Permission Denied", []byte("{\"reason\":\"book is not open\"}"))
		return nil, errors.New("Orders cannot be placed unless deal status is 'Open'")
	}
	hasReqDocs, reqDoc := c.checkInvestorHasRequiredDocs(dealConfig.DocRegAddress, investor, dealConfig.RequiredDocs)
	if !hasReqDocs {
		c.stub.SetEvent("Permission Denied", []byte("{\"reason\":\"" + investor + " does not have " + reqDoc +  "\"}"))
		return nil, errors.New("Order's cannot be placed without QIB status")
	}
	order := c.getOrderFromBlockChain(investor)
	if order.Investor == "" {
		order = Order{Investor: investor, Ioi: ioi, Alloc: 0.0, Confirmed: false}
	} else {
		order.Ioi = ioi
	}
	c.saveOrderToBlockChain(order)
	c.stub.SetEvent("Order Added", []byte("{\"investor\":\"" + investor + "\"}"))
	return nil, nil
}

func (c ChaincodeFunctions) ConfirmOrder(investor string) ([]byte, error) {
	dealConfig := c.getDealConfigFromBlockchain()
	if dealConfig.BookStatus != "allocated" {
		c.stub.SetEvent("Permission Denied", []byte("{\"reason\":\"book is not allocated\"}"))
		return nil, nil
	}
	order := c.getOrderFromBlockChain(investor)
	order.Confirmed = true
	c.saveOrderToBlockChain(order)
	c.stub.SetEvent("Order Confirmed", []byte("{\"investor\":\"" + investor + "\"}"))
	return nil, nil
}

func (c ChaincodeFunctions) GetOrder(investor string) ([]byte, error) {
	roleBytes, _ := c.stub.ReadCertAttribute("role")
	role := string(roleBytes)
	dealConfig := c.getDealConfigFromBlockchain()
	order := c.getOrderFromBlockChain(investor)
	if !canSeeAllocations(role, dealConfig) {
		order.Alloc = -1
	}
	orderJson, _ := json.Marshal(order)
	return []byte(orderJson), nil
}

func (c ChaincodeFunctions) GetOrderbook() ([]byte, error) {
	orderbookJson, _ := c.stub.GetState("orderbook")
	return []byte(orderbookJson), nil
}

func (c ChaincodeFunctions) AllocateOrder(investor string, alloc float64) ([]byte, error) {
	order := c.getOrderFromBlockChain(investor)
	order.Alloc = alloc
	c.saveOrderToBlockChain(order)
	c.stub.SetEvent("Order Allocated", []byte("{\"investor\":\"" + investor + "\"}"))
	return nil, nil
}

// Private Functions

func (c ChaincodeFunctions) getDealConfigFromBlockchain() DealConfig {
	dealConfigJson, _ := c.stub.GetState("dealConfig")
	var dealConfig DealConfig
	_ = json.Unmarshal(dealConfigJson, &dealConfig)
	return dealConfig
}

func (c ChaincodeFunctions) saveDealConfigToBlockchain(dealConfig DealConfig) {
	dealConfigJson, _ := json.Marshal(dealConfig)
	_ = c.stub.PutState("dealConfig", []byte(dealConfigJson))
}

func (c ChaincodeFunctions) getOrderAsJsonFromBlockchain(investor string) string {
	order := c.getOrderFromBlockChain(investor)
	orderJson, _ := json.Marshal(order)
	return string(orderJson)
}

func (c ChaincodeFunctions) getOrderFromBlockChain(investor string) Order {
	orderbook := c.getOrderbookFromBlockChain()
	return orderbook[investor]
}

func (c ChaincodeFunctions) saveOrderToBlockChain(order Order) {
	orderbook := c.getOrderbookFromBlockChain()
	orderbook[order.Investor] = order
	c.saveOrderbookToBlockChain(orderbook)
}

func (c ChaincodeFunctions) getOrderbookFromBlockChain() map[string]Order {
	orderbookJson, _ := c.stub.GetState("orderbook")
	var orderbook map[string]Order
	_ = json.Unmarshal(orderbookJson, &orderbook)
	return orderbook
}

func (c ChaincodeFunctions) saveOrderbookToBlockChain(orderbook map[string]Order) {
	orderbookJson, _ := json.Marshal(orderbook)
	_ = c.stub.PutState("orderbook", []byte(orderbookJson))
}

func (c ChaincodeFunctions) checkInvestorHasRequiredDocs(address string, company string,
		requiredDocs []string) (bool, string) {
	invokeArgs := util.ToChaincodeArgs("getDocs", company)
	docsJson, _ := c.stub.QueryChaincode(address, invokeArgs)
	var docs []string
	_ = json.Unmarshal(docsJson, &docs)
	for _, reqDoc := range requiredDocs {
		if !stringInSlice(reqDoc, docs) {
			return false, reqDoc
		}
	}
	return true, ""
}

func stringInSlice(a string, list []string) bool {
    for _, b := range list {
        if b == a {
            return true
        }
    }
    return false
}

func canSeeAllocations(role string, dealConfig DealConfig) bool {
	if role != "investor" {
		return true
	} else if dealConfig.BookStatus == "draft" {
		return false
	} else if dealConfig.BookStatus == "open" {
		return false
	} else if dealConfig.BookStatus == "closed" {
		return false
	} else {
		return true
	}
}<|endoftext|>