<commit_before>package main

import (
	"io/ioutil"
	"regexp"
	"strconv"
	"strings"
	"fmt"
)

func Identify(filename string) {
	content, err := ioutil.ReadFile(filename)
	ChkErr(err)
	text := string(content)

	// put all flags/restricts, or effects, on one line
	re, err := regexp.Compile(`([[:upper:]]{2})\n([[:upper:]]{2})`)
	ChkErr(err)
	text = re.ReplaceAllString(text, "$1 $2")

	// put enchant info on one line
	re, err = regexp.Compile(`\n(Duration)`)
	ChkErr(err)
	text = re.ReplaceAllString(text, " $1")

	// put all resists on same line:
	re, err = regexp.Compile(
		`\n(    [[:alpha:] ]{6}:[[:blank:]]{3,4}[[:digit:]]{1,2}% )`)
	ChkErr(err)
	text = re.ReplaceAllString(text, "$1")

	// put first wand/staff/scroll/potion spell on one line:
	re, err = regexp.Compile(`(spell[s]? of:)\n`)
	ChkErr(err)
	text = re.ReplaceAllString(text, "$1 ")

	// put remaining scroll/potion spells on same line:
	re, err = regexp.Compile(`\n([[:lower:]])`)
	ChkErr(err)
	text = re.ReplaceAllString(text, ", $1")

	items := strings.Split(text, "\n\n")

	// initialize regex checks
	var m [][]string
	chkName, err := regexp.Compile(
		// Name 'a huge boar skull'
		`Name '([[:print:]]+)'`)
	ChkErr(err)
	chkKey, err := regexp.Compile(
		// Keyword 'skull boar', Item type: ARMOR
		`Keyword '([[:print:]]+)', Item type: ([[:word:]]+)`)
	ChkErr(err)
	chkWorn, err := regexp.Compile(
		// Item can be worn on:  HEAD
		`Item can be worn on: ([[:print:]]+)`)
	ChkErr(err)
	chkEff, err := regexp.Compile(
		// Item will give you following abilities:  NOBITS
		`Item will give you following abilities: ([[:print:]]+)`)
	ChkErr(err)
	chkFlag, err := regexp.Compile(
		// Item is: NOBITSNOBITS
		`Item is: ([[:print:]]+)`)
	ChkErr(err)
	chkRest, err := regexp.Compile(
		// NO-THIEF ANTI-ANTIPALADIN
		`[NO|ANTI]-`)
	ChkErr(err)
	chkWtval, err := regexp.Compile(
		// Weight: 2, Value: 0
		`Weight: ([[:digit:]]+), Value: ([[:digit:]]+)`)
	ChkErr(err)
	chkAC, err := regexp.Compile(
		// AC-apply is 8
		`AC-apply is ([[:digit:]]+)`)
	ChkErr(err)
	chkAttr, err := regexp.Compile(
		//     Affects : HITROLL By 2
		`Affects : ([[:print:]]+) [B|b]y ([[:digit:]-]+)`)
	ChkErr(err)

	chkDice, err := regexp.Compile(
		// Damage Dice are '2D6' // old weapon dice
		`Damage Dice are '([[:digit:]D]+)'`)
	ChkErr(err)
	chkWeap, err := regexp.Compile(
		// Type: Morningstar Class: Simple // new weapon, type/class
		`Type: ([[:print:]]+) Class: ([[:print:]]+)`)
	ChkErr(err)
	chkCrit, err := regexp.Compile(
		// Damage:  2D5  Crit Range: 5%  Crit Bonus: 2x // new weapon, dice/crit/multi
		`Damage: [ ]?([[:digit:]D]+) [ ]?Crit Range: ([[:digit:]]+)% [ ]?Crit Bonus: ([[:digit:]]+)x`)
	ChkErr(err)
	chkEnch, err := regexp.Compile(
		// Type: Holy             Damage: 100% Frequency: 100% Modifier: 0 Duration: 0 // enchantment
		`Type: ([[:print:]]+) Damage: ([[:digit:]]+)% Frequency: ([[:digit:]]+)[ ]?% Modifier: ([[:digit:]]+)`)
	ChkErr(err)
	chkPage, err := regexp.Compile(
		// Total Pages: 300 // spellbook
		`Total Pages: ([[:digit:]]+)`)
	ChkErr(err)
	chkPsp, err := regexp.Compile(
		// Has 700 capacity, charged with 700 points. // psp crystal
		`Has ([[:digit:]]+) capacity, charged with [[:digit:]]+ points.`)
	ChkErr(err)
	chkPois, err := regexp.Compile(
		// Poison affects as ray of enfeeblement at level 25. // type, level
		`Poison affects as ([[:print:]]+) at level ([[:digit:]]+).`)
	ChkErr(err)
	chkApps, err := regexp.Compile(
		// 1 applications remaining with 3 hits per application. // poison apps
		`([[:digit:]]+) applications remaining with ([[:digit:]]+) hits per application.`)
	ChkErr(err)
	chkInstr, err := regexp.Compile(
		// Instrument Type: Drums, Quality: 8, Stutter: 7, Min Level: 1 // instrument
		`Instrument Type: ([[:print:]]+), Quality: ([[:digit:]]+), Stutter: ([[:digit:]]+), Min Level: ([[:digit:]]+)`)
	ChkErr(err)
	chkCharg, err := regexp.Compile(
		// Has 99 charges, with 99 charges left. // wand/staff
		`Has ([[:digit:]]+) charges, with ([[:digit:]]+) charges left.`)
	ChkErr(err)
	chkWand, err := regexp.Compile(
		// Level 35 spells of: protection from good, protection from evil // potion/scroll
		`Level ([[:digit:]]+) spells of: ([[:print:]]+)`)
	ChkErr(err)
	chkPot, err := regexp.Compile(
		// Level 1 spell of: airy water // staff/wand
		`Level ([[:digit:]]+) spell of: ([[:print:]]+)`)
	ChkErr(err)
	chkCont, err := regexp.Compile(
		// Can hold 50 more lbs. // container
		`Can hold ([[:digit:]]+) more lbs.`)
	ChkErr(err)
	chkWtless, err := regexp.Compile(
		// Can hold 600 more lbs with 300lbs weightless. // container
		`Can hold ([[:digit:]]+) more lbs with ([[:digit:]]+)lbs weightless.`)
	ChkErr(err)

	for _, item := range items {
		// initialize item variables
		full_stats, item_name, keywords, item_type := "", "", "", ""
		weight, c_value := -1, -1
		var item_slots, item_effects, flags, item_flags, item_restricts []string
		var item_attribs, item_specials [][]string

		full_stats = item
		lines := strings.Split(item, "\n")
		var unmatch []string

		for _, line := range lines {
			switch {
			case chkName.MatchString(line):
				m = chkName.FindAllStringSubmatch(line, -1)
				item_name = m[0][1]
			case chkKey.MatchString(line):
				m = chkKey.FindAllStringSubmatch(line, -1)
				keywords = m[0][1]
				item_type = m[0][2]
			case chkWorn.MatchString(line):
				m = chkWorn.FindAllStringSubmatch(line, -1)
				item_slots = strings.Fields(m[0][1])
			case chkEff.MatchString(line):
				m = chkEff.FindAllStringSubmatch(line, -1)
				item_effects = strings.Fields(m[0][1])
			case chkFlag.MatchString(line):
				m = chkFlag.FindAllStringSubmatch(line, -1)
				flags = strings.Fields(m[0][1])
				for _, flag := range flags {
					if chkRest.MatchString(flag) {
						item_restricts = append(item_restricts, flag)
					} else {
						item_flags = append(item_flags, flag)
					}
				}
			case chkWtval.MatchString(line):
				m = chkWtval.FindAllStringSubmatch(line, -1)
				weight, err = strconv.Atoi(m[0][1])
				ChkErr(err)
				c_value, err = strconv.Atoi(m[0][2])
				ChkErr(err)
			case chkAC.MatchString(line):
				m = chkAC.FindAllStringSubmatch(line, -1)
				item_specials = append(item_specials, []string{item_type, "ac", m[0][1]})
			case chkAttr.MatchString(line):
				m = chkAttr.FindAllStringSubmatch(line, -1)
				item_attribs = append(item_attribs, []string{m[0][1], m[0][2]})
			case chkDice.MatchString(line):
				m = chkDice.FindAllStringSubmatch(line, -1)
			case chkWeap.MatchString(line):
				m = chkWeap.FindAllStringSubmatch(line, -1)
			case chkCrit.MatchString(line):
				m = chkCrit.FindAllStringSubmatch(line, -1)
			case chkEnch.MatchString(line):
				m = chkEnch.FindAllStringSubmatch(line, -1)
			case chkPsp.MatchString(line):
				m = chkPsp.FindAllStringSubmatch(line, -1)
			case chkPage.MatchString(line):
				m = chkPage.FindAllStringSubmatch(line, -1)
			case chkPois.MatchString(line):
				m = chkPois.FindAllStringSubmatch(line, -1)
			case chkApps.MatchString(line):
				m = chkApps.FindAllStringSubmatch(line, -1)
			case chkInstr.MatchString(line):
				m = chkInstr.FindAllStringSubmatch(line, -1)
			case chkCharg.MatchString(line):
				m = chkCharg.FindAllStringSubmatch(line, -1)
			case chkWand.MatchString(line):
				m = chkWand.FindAllStringSubmatch(line, -1)
			case chkPot.MatchString(line):
				m = chkPot.FindAllStringSubmatch(line, -1)
			case chkCont.MatchString(line):
				m = chkCont.FindAllStringSubmatch(line, -1)
			case chkWtless.MatchString(line):
				m = chkWtless.FindAllStringSubmatch(line, -1)
			default:
				unmatch = append(unmatch, line)
			}
		}
		// back to full item
		fmt.Printf("Name: %s\nKeywords: %s\nType: %s\n",
			item_name, keywords, item_type)
		fmt.Printf("Weight: %d\nValue: %d\n", weight, c_value)
		for _, slot := range item_slots {
			fmt.Printf("Slot: %s\n", slot)
		}
		for _, eff := range item_effects {
			if eff != "NOBITS" && eff != "GROUP_CACHED" {
				fmt.Printf("Effect: %s\n", eff)
			}
		}
		for _, flag := range item_flags {
			if flag != "NOBITS" && flag != "NOBITSNOBITS" {
				fmt.Printf("Flag: %s\n", flag)
			}
		}
		for _, rest := range item_restricts {
			fmt.Printf("Restrict: %s\n", rest)
		}
		for _, attr := range item_attribs {
			fmt.Printf("Attrib: %s, Value: %s\n", attr[0], attr[1])
		}
		for _, spec := range item_specials {
			fmt.Printf("Special: Type: %s, Abbr: %s, Value: %s\n", spec[0], spec[1], spec[2])
		}
		for _, um := range unmatch {
			if !strings.Contains(um, "Can affect you as :") &&
				!strings.Contains(um, "Enchantments:") &&
				!strings.Contains(um, "Zone:") &&
				!strings.Contains(um, "You feel informed:") {
				fmt.Println("Unmatched: ", um)
			}
		}
		_ = full_stats
		fmt.Print("\n----------\n\n")
	}
}
<commit_msg>Lots more regex work<commit_after>package main

import (
	"io/ioutil"
	"regexp"
	"strconv"
	"strings"
	"fmt"
)

func Identify(filename string) {
	content, err := ioutil.ReadFile(filename)
	ChkErr(err)
	text := string(content)

	// put all flags/restricts, or effects, on one line
	re, err := regexp.Compile(`([[:upper:]]{2})\n([[:upper:]]{2})`)
	ChkErr(err)
	text = re.ReplaceAllString(text, "$1 $2")

	// put enchant info on one line
	re, err = regexp.Compile(`\n(Duration)`)
	ChkErr(err)
	text = re.ReplaceAllString(text, " $1")

	// put all resists on same line:
	re, err = regexp.Compile(
		`\n(    [[:alpha:] ]{6}:[[:blank:]]{3,4}[[:digit:]]{1,2}% )`)
	ChkErr(err)
	text = re.ReplaceAllString(text, "$1")

	// put first wand/staff/scroll/potion spell on one line:
	re, err = regexp.Compile(`(spell[s]? of:)\n`)
	ChkErr(err)
	text = re.ReplaceAllString(text, "$1 ")

	// put remaining scroll/potion spells on same line:
	re, err = regexp.Compile(`\n([[:lower:]])`)
	ChkErr(err)
	text = re.ReplaceAllString(text, ", $1")

	items := strings.Split(text, "\n\n")

	// initialize regex checks
	var m []string
	chkName, err := regexp.Compile(
		// Name 'a huge boar skull'
		`Name '([[:print:]]+)'`)
	ChkErr(err)
	chkKey, err := regexp.Compile(
		// Keyword 'skull boar', Item type: ARMOR
		`Keyword '([[:print:]]+)', Item type: ([[:word:]]+)`)
	ChkErr(err)
	chkWorn, err := regexp.Compile(
		// Item can be worn on:  HEAD
		`Item can be worn on: ([[:print:]]+)`)
	ChkErr(err)
	chkEff, err := regexp.Compile(
		// Item will give you following abilities:  NOBITS
		`Item will give you following abilities: ([[:print:]]+)`)
	ChkErr(err)
	chkFlag, err := regexp.Compile(
		// Item is: NOBITSNOBITS
		`Item is: ([[:print:]]+)`)
	ChkErr(err)
	chkRest, err := regexp.Compile(
		// NO-THIEF ANTI-ANTIPALADIN
		`[NO|ANTI]-`)
	ChkErr(err)
	chkWtval, err := regexp.Compile(
		// Weight: 2, Value: 0
		`Weight: ([[:digit:]]+), Value: ([[:digit:]]+)`)
	ChkErr(err)
	chkAC, err := regexp.Compile(
		// AC-apply is 8
		`AC-apply is ([[:digit:]]+)`)
	ChkErr(err)

	chkAttr, err := regexp.Compile(
		//     Affects : HITROLL By 2
		`Affects : ([[:print:]]+) [B|b]y ([[:digit:]-]+)`)
	ChkErr(err)
	chkEnch, err := regexp.Compile(
		// Type: Holy             Damage: 100% Frequency: 100% Modifier: 0 Duration: 0 // enchantment
		`Type: ([[:print:]]+) Damage: ([[:digit:]]+)% Frequency: ([[:digit:]]+)[ ]?% Modifier: ([[:digit:]]+) Duration: ([[:digit:]]+)`)
	ChkErr(err)
	chkResis, err := regexp.Compile(
		// Resists: Fire : 5% Cold : 5% Elect : 5% Acid : 5% Poison: 5% Psi : 5%
		//     Unarmd:    2% Slash :    2% Bludgn:    2% Pierce:    2%
		//     Fire  :   10% Mental:    5%
		`([[:alpha:] ]{6}):[ ]{3,4}([[:digit:]]{1,2})% `)
	ChkErr(err)

	// item specials
	chkDice, err := regexp.Compile(
		// Damage Dice are '2D6' // old weapon dice
		`Damage Dice are '([[:digit:]D]+)'`)
	ChkErr(err)
	chkWeap, err := regexp.Compile(
		// Type: Morningstar Class: Simple // new weapon, type/class
		`Type: ([[:print:]]+) Class: ([[:print:]]+)`)
	ChkErr(err)
	chkCrit, err := regexp.Compile(
		// Damage:  2D5  Crit Range: 5%  Crit Bonus: 2x // new weapon, dice/crit/multi
		`Damage: [ ]?([[:digit:]D]+) [ ]?Crit Range: ([[:digit:]]+)% [ ]?Crit Bonus: ([[:digit:]]+)x`)
	ChkErr(err)
	chkPage, err := regexp.Compile(
		// Total Pages: 300 // spellbook
		`Total Pages: ([[:digit:]]+)`)
	ChkErr(err)
	chkPsp, err := regexp.Compile(
		// Has 700 capacity, charged with 700 points. // psp crystal
		`Has ([[:digit:]]+) capacity, charged with [[:digit:]]+ points.`)
	ChkErr(err)
	chkPois, err := regexp.Compile(
		// Poison affects as ray of enfeeblement at level 25. // type, level
		`Poison affects as ([[:print:]]+) at level ([[:digit:]]+).`)
	ChkErr(err)
	chkApps, err := regexp.Compile(
		// 1 applications remaining with 3 hits per application. // poison apps
		`([[:digit:]]+) applications remaining with ([[:digit:]]+) hits per application.`)
	ChkErr(err)
	chkInstr, err := regexp.Compile(
		// Instrument Type: Drums, Quality: 8, Stutter: 7, Min Level: 1 // instrument
		`Instrument Type: ([[:print:]]+), Quality: ([[:digit:]]+), Stutter: ([[:digit:]]+), Min Level: ([[:digit:]]+)`)
	ChkErr(err)
	chkCharg, err := regexp.Compile(
		// Has 99 charges, with 99 charges left. // wand/staff
		`Has ([[:digit:]]+) charges, with ([[:digit:]]+) charges left.`)
	ChkErr(err)
	chkPot, err := regexp.Compile(
		// Level 35 spells of: protection from good, protection from evil // potion/scroll
		`Level ([[:digit:]]+) spells of: ([[:print:]]+)([, [[:print:]]+])?([, [[:print:]]+])?`)
	ChkErr(err)
	chkWand, err := regexp.Compile(
		// Level 1 spell of: airy water // staff/wand
		`Level ([[:digit:]]+) spell of: ([[:print:]]+)`)
	ChkErr(err)
	chkCont, err := regexp.Compile(
		// Can hold 50 more lbs. // container
		`Can hold ([[:digit:]]+) more lbs.`)
	ChkErr(err)
	chkWtless, err := regexp.Compile(
		// Can hold 600 more lbs with 300lbs weightless. // container
		`Can hold ([[:digit:]]+) more lbs with ([[:digit:]]+)lbs weightless.`)
	ChkErr(err)

	for _, item := range items {
		// initialize item variables
		full_stats, item_name, keywords, item_type := "", "", "", ""
		weight, c_value := -1, -1
		var item_slots, item_effects, flags, item_flags, item_restricts []string
		var item_attribs, item_specials, item_enchants, item_resists [][]string

		full_stats = item
		lines := strings.Split(item, "\n")
		var unmatch []string

		for _, line := range lines {
			switch {
			case chkName.MatchString(line):
				m = chkName.FindStringSubmatch(line)
				item_name = m[1]
			case chkKey.MatchString(line):
				m = chkKey.FindStringSubmatch(line)
				keywords = m[1]
				item_type = m[2]
			case chkWorn.MatchString(line):
				m = chkWorn.FindStringSubmatch(line)
				item_slots = strings.Fields(m[1])
			case chkEff.MatchString(line):
				m = chkEff.FindStringSubmatch(line)
				item_effects = strings.Fields(m[1])
			case chkFlag.MatchString(line):
				m = chkFlag.FindStringSubmatch(line)
				flags = strings.Fields(m[1])
				for _, flag := range flags {
					if chkRest.MatchString(flag) {
						item_restricts = append(item_restricts, flag)
					} else {
						item_flags = append(item_flags, flag)
					}
				}
			case chkWtval.MatchString(line):
				m = chkWtval.FindStringSubmatch(line)
				weight, err = strconv.Atoi(m[1])
				ChkErr(err)
				c_value, err = strconv.Atoi(m[2])
				ChkErr(err)
			case chkAttr.MatchString(line):
				m = chkAttr.FindStringSubmatch(line)
				item_attribs = append(item_attribs, []string{m[1], m[2]})
			case chkResis.MatchString(line):
				resis := chkResis.FindAllStringSubmatch(line, -1)
				for _, res := range resis {
					item_resists = append(item_resists,[]string{
						strings.TrimSpace(res[1]), res[2]})
				}
			case chkEnch.MatchString(line):
				m = chkEnch.FindStringSubmatch(line)
				item_enchants = append(item_enchants, []string{
					strings.TrimSpace(m[1]), m[2], m[3], m[4], m[5]})
			case chkAC.MatchString(line):
				m = chkAC.FindStringSubmatch(line)
				item_specials = append(item_specials, []string{item_type, "ac", m[1]})
			case chkDice.MatchString(line):
				m = chkDice.FindStringSubmatch(line)
				item_specials = append(item_specials, []string{item_type, "dice", m[1]})
			case chkWeap.MatchString(line):
				m = chkWeap.FindStringSubmatch(line)
				item_specials = append(item_specials, []string{item_type, "type", m[1]})
				item_specials = append(item_specials, []string{item_type, "class", m[2]})
			case chkCrit.MatchString(line):
				m = chkCrit.FindStringSubmatch(line)
				item_specials = append(item_specials, []string{item_type, "dice", m[1]})
				item_specials = append(item_specials, []string{item_type, "crit", m[2]})
				item_specials = append(item_specials, []string{item_type, "multi", m[3]})
			case chkPsp.MatchString(line):
				m = chkPsp.FindStringSubmatch(line)
				item_specials = append(item_specials, []string{item_type, "psp", m[1]})
			case chkPage.MatchString(line):
				m = chkPage.FindStringSubmatch(line)
				item_specials = append(item_specials, []string{item_type, "pages", m[1]})
			case chkPois.MatchString(line):
				m = chkPois.FindStringSubmatch(line)
				item_specials = append(item_specials, []string{item_type, "type", m[1]})
				item_specials = append(item_specials, []string{item_type, "level", m[2]})
			case chkApps.MatchString(line):
				m = chkApps.FindStringSubmatch(line)
				item_specials = append(item_specials, []string{item_type, "apps", m[1]})
				item_specials = append(item_specials, []string{item_type, "hits", m[2]})
			case chkInstr.MatchString(line):
				m = chkInstr.FindStringSubmatch(line)
				item_specials = append(item_specials, []string{item_type, "type", m[1]})
				item_specials = append(item_specials, []string{item_type, "quality", m[2]})
				item_specials = append(item_specials, []string{item_type, "stutter", m[3]})
				item_specials = append(item_specials, []string{item_type, "min_level", m[4]})
			case chkCharg.MatchString(line):
				m = chkCharg.FindStringSubmatch(line)
				item_specials = append(item_specials, []string{item_type, "charges", m[1]})
				//item_specials = append(item_specials, []string{item_type, "cur_char", m[2]})
			case chkWand.MatchString(line):
				m = chkWand.FindStringSubmatch(line)
				item_specials = append(item_specials, []string{item_type, "level", m[1]})
				item_specials = append(item_specials, []string{item_type, "spell", m[2]})
			case chkPot.MatchString(line):
				m = chkPot.FindStringSubmatch(line)
				item_specials = append(item_specials, []string{item_type, "level", m[1]})
				item_specials = append(item_specials, []string{item_type, "spell1", m[2]})
				if len(m[0]) == 4 {
					item_specials = append(item_specials, []string{item_type, "spell2", m[3]})
				} else if len(m[0]) == 5 {
					item_specials = append(item_specials, []string{item_type, "spell2", m[3]})
					item_specials = append(item_specials, []string{item_type, "spell3", m[4]})
				}
			case chkCont.MatchString(line):
				m = chkCont.FindStringSubmatch(line)
				item_specials = append(item_specials, []string{item_type, "holds", m[1]})
			case chkWtless.MatchString(line):
				m = chkWtless.FindStringSubmatch(line)
				item_specials = append(item_specials, []string{item_type, "holds", m[1]})
				item_specials = append(item_specials, []string{item_type, "wtless", m[2]})
			default:
				unmatch = append(unmatch, line)
			}
		}
		// back to full item
		fmt.Printf("Name: %s\nKeywords: %s\nType: %s\n",
			item_name, keywords, item_type)
		fmt.Printf("Weight: %d\nValue: %d\n", weight, c_value)
		for _, slot := range item_slots {
			fmt.Printf("Slot: %s\n", slot)
		}
		for _, eff := range item_effects {
			if eff != "NOBITS" && eff != "GROUP_CACHED" {
				fmt.Printf("Effect: %s\n", eff)
			}
		}
		for _, flag := range item_flags {
			if flag != "NOBITS" && flag != "NOBITSNOBITS" {
				fmt.Printf("Flag: %s\n", flag)
			}
		}
		for _, rest := range item_restricts {
			fmt.Printf("Restrict: %s\n", rest)
		}
		for _, attr := range item_attribs {
			fmt.Printf("Attrib: %s, Value: %s\n", attr[0], attr[1])
		}
		for _, spec := range item_specials {
			fmt.Printf("Special: Type: %s, Abbr: %s, Value: %s\n", spec[0], spec[1], spec[2])
		}
		for _, ench := range item_enchants {
			fmt.Printf("Enchant: Name: %s, Dam_Pct: %s, Freq_Pct: %s, Sv_Mod: %s, Duration: %s\n",
				ench[0], ench[1], ench[2], ench[3], ench[4])
		}
		for _, res := range item_resists {
			fmt.Printf("Resist: Name: %s, Value: %s\n", res[0], res[1])
		}
		for _, um := range unmatch {
			if !strings.Contains(um, "Can affect you as :") &&
				!strings.Contains(um, "Enchantments:") &&
				!strings.Contains(um, "Zone:") &&
				!strings.Contains(um, "You feel informed:") {
				fmt.Println("Unmatched: ", um)
			}
		}
		_ = full_stats
		fmt.Print("\n----------\n\n")
	}
}
<|endoftext|>


<commit_before>package patreon

import (
	"encoding/json"
	"fmt"
)

type Includes struct {
	Items []interface{}
}

func (i *Includes) UnmarshalJSON(b []byte) error {
	var items []*json.RawMessage
	if err := json.Unmarshal(b, &items); err != nil {
		return err
	}

	count := len(items)
	i.Items = make([]interface{}, count)

	s := struct {
		Type string `json:"type"`
	}{}

	for idx, raw := range items {
		if err := json.Unmarshal(*raw, &s); err != nil {
			return err
		}

		var obj interface{}

		// Depending on the type, we can run json.Unmarshal again on the same byte slice
		// But this time, we'll pass in the appropriate struct instead of a map
		if s.Type == "user" {
			obj = &User{}
		} else if s.Type == "reward" {
			obj = &Reward{}
		} else if s.Type == "goal" {
			obj = &Goal{}
		} else {
			return fmt.Errorf("unsupported type %s", s.Type)
		}

		if err := json.Unmarshal(*raw, obj); err != nil {
			return err
		}

		i.Items[idx] = obj
	}

	return nil
}
<commit_msg>Parse campaign includes<commit_after>package patreon

import (
	"encoding/json"
	"fmt"
)

type Includes struct {
	Items []interface{}
}

func (i *Includes) UnmarshalJSON(b []byte) error {
	var items []*json.RawMessage
	if err := json.Unmarshal(b, &items); err != nil {
		return err
	}

	count := len(items)
	i.Items = make([]interface{}, count)

	s := struct {
		Type string `json:"type"`
	}{}

	for idx, raw := range items {
		if err := json.Unmarshal(*raw, &s); err != nil {
			return err
		}

		var obj interface{}

		// Depending on the type, we can run json.Unmarshal again on the same byte slice
		// But this time, we'll pass in the appropriate struct instead of a map
		if s.Type == "user" {
			obj = &User{}
		} else if s.Type == "reward" {
			obj = &Reward{}
		} else if s.Type == "goal" {
			obj = &Goal{}
		} else if s.Type == "campaign" {
			obj = &Campaign{}
		} else {
			return fmt.Errorf("unsupported type %s", s.Type)
		}

		if err := json.Unmarshal(*raw, obj); err != nil {
			return err
		}

		i.Items[idx] = obj
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2017 The nvim-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 server

import (
	"context"
	"os"
	"time"

	"github.com/neovim/go-client/nvim"
	"github.com/pkg/errors"
	"github.com/zchee/nvim-go/src/logger"
	"go.uber.org/zap"
)

type Server struct {
	*nvim.Nvim
	errc chan error
}

func NewServer(pctx context.Context) (*Server, error) {
	const envNvimListenAddress = "NVIM_LISTEN_ADDRESS"

	addr := os.Getenv(envNvimListenAddress)
	if addr == "" {
		return nil, errors.Errorf("%s not set", envNvimListenAddress)
	}

	zapLogf := func(format string, a ...interface{}) {
		logger.FromContext(pctx).Named("server").Info("", zap.Any(format, a))
	}

	ctx, cancel := context.WithTimeout(pctx, 5*time.Second)
	defer cancel()

	n, err := nvim.Dial(addr, nvim.DialContext(ctx), nvim.DialServe(false), nvim.DialLogf(zapLogf))
	if err != nil {
		return nil, err
	}

	return &Server{
		Nvim: n,
		errc: make(chan error, 1),
	}, nil
}

func (s *Server) Serve() {
	s.errc <- s.Nvim.Serve()
}

func (s *Server) Close() error {
	err := s.Nvim.Close()

	var errServe error
	select {
	case errServe = <-s.errc:
	case <-time.After(10 * time.Second):
		errServe = errors.New("nvim: Serve did not exit")
	}
	if err == nil {
		err = errServe
	}

	return err
}
<commit_msg>server: add retrying Dial connection<commit_after>// Copyright 2017 The nvim-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 server

import (
	"context"
	"os"
	"time"

	"github.com/neovim/go-client/nvim"
	"github.com/pkg/errors"
	"github.com/zchee/nvim-go/src/logger"
	"go.uber.org/zap"
)

type Server struct {
	*nvim.Nvim
	errc chan error
}

func NewServer(pctx context.Context) (*Server, error) {
	log := logger.FromContext(pctx).Named("server")

	const envNvimListenAddress = "NVIM_LISTEN_ADDRESS"
	addr := os.Getenv(envNvimListenAddress)
	if addr == "" {
		return nil, errors.Errorf("%s not set", envNvimListenAddress)
	}

	zapLogf := func(format string, a ...interface{}) {
		log.Info("", zap.Any(format, a))
	}

	ctx, cancel := context.WithTimeout(pctx, 1*time.Second)
	defer cancel()

	var n *nvim.Nvim
	var tempDelay time.Duration
	for {
		var err error
		n, err = nvim.Dial(addr, nvim.DialContext(ctx), nvim.DialServe(false), nvim.DialLogf(zapLogf))
		if err != nil {
			if tempDelay == 0 {
				tempDelay = 5 * time.Millisecond
			} else {
				tempDelay *= 2
			}
			if max := 1 * time.Second; tempDelay > max {
				tempDelay = max
			}
			log.Info("Dial error", zap.Error(err), zap.Duration("retrying in", tempDelay))
			timer := time.NewTimer(tempDelay)
			select {
			case <-timer.C:
			}
			continue
		}
		tempDelay = 0

		return &Server{
			Nvim: n,
			errc: make(chan error, 1),
		}, nil
	}
}

func (s *Server) Serve() {
	s.errc <- s.Nvim.Serve()
}

func (s *Server) Close() error {
	err := s.Nvim.Close()

	var errServe error
	select {
	case errServe = <-s.errc:
	case <-time.After(10 * time.Second):
		errServe = errors.New("nvim: Serve did not exit")
	}
	if err == nil {
		err = errServe
	}

	return err
}
<|endoftext|>


<commit_before>// Copyright 2015 ThoughtWorks, Inc.

// This file is part of Gauge.

// Gauge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Gauge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Gauge.  If not, see <http://www.gnu.org/licenses/>.

package main

import (
	"log"

	"strings"

	"io/ioutil"
	"os"
	"path/filepath"

	"math"

	"html/template"

	"github.com/getgauge/common"
	"github.com/getgauge/gauge/cmd"
	"github.com/russross/blackfriday"
	"github.com/spf13/cobra"
	"github.com/spf13/cobra/doc"
)

const (
	maxDescLength = 46
	maxLineLength = 77
)

type link struct {
	Class string
	Link  string
	Name  string
}

type text struct {
	name    string
	content string
}

var indexTemplate, _ = template.New("test").Parse(`

{{ range . }}

{{ .Name }}

{{ end }}

`)

type writer struct {
	text string
}

func (w *writer) Write(b []byte) (int, error) {
	w.text += string(b)
	return 0, nil
}

func main() {
	mdPath := filepath.Join("_man", "md")
	htmlPath := filepath.Join("_man", "html")
	createDir(mdPath)
	createDir(htmlPath)
	if err := genMarkdownManPages(mdPath); err != nil {
		log.Fatal(err.Error())
	}
	texts := indentText(mdPath)
	links := getLinks(texts)
	for _, t := range texts {
		name := strings.TrimSuffix(t.name, filepath.Ext(t.name)) + ".html"
		var newLinks []link
		for _, l := range links {
			if l.Link == name {
				newLinks = append(newLinks, link{Name: l.Name, Link: l.Link, Class: "active"})
			} else {
				newLinks = append(newLinks, l)
			}
		}
		page := strings.Replace(html, "", prepareIndex(newLinks), -1)
		output := strings.Replace(page, "", string(blackfriday.MarkdownCommon([]byte(t.content))), -1)
		ioutil.WriteFile(filepath.Join(htmlPath, name), []byte(output), 0644)
	}
	log.Printf("HTML man pages are available in %s dir\n", htmlPath)
}
func createDir(p string) {
	if err := os.MkdirAll(p, common.NewDirectoryPermissions); err != nil {
		log.Fatal(err.Error())
	}
}

func genMarkdownManPages(out string) error {
	if err := doc.GenMarkdownTree(setupCmd(), out); err != nil {
		return err
	}
	log.Printf("Added markdown man pages to `%s`\n", out)
	return nil
}

func setupCmd() *cobra.Command {
	cmd.GaugeCmd.Short = "A light-weight cross-platform test automation tool"
	cmd.GaugeCmd.Long = "Gauge is a light-weight cross-platform test automation tool with the ability to author test cases in the business language."
	return cmd.GaugeCmd
}

func getLinks(texts []text) (links []link) {
	for _, t := range texts {
		name := strings.TrimSuffix(t.name, filepath.Ext(t.name))
		links = append(links, link{Class: "", Name: strings.Replace(name, "_", " ", -1), Link: name + ".html"})
	}
	return
}

func prepareIndex(links []link) string {
	w := &writer{}
	err := indexTemplate.Execute(w, links)
	if err != nil {
		log.Fatalf(err.Error())
	}
	return w.text
}

func indentText(p string) (texts []text) {
	filepath.Walk(p, func(path string, info os.FileInfo, err error) error {
		if strings.HasSuffix(info.Name(), ".md") {
			bytes, err := ioutil.ReadFile(path)
			if err != nil {
				return err
			}
			var lines []string
			for _, l := range strings.Split(string(bytes), string("\n")) {
				tLine := strings.TrimSpace(l)
				if strings.HasPrefix(tLine, "-") && len(tLine) > maxLineLength {
					lines = append(lines, indentFlag(l, tLine)...)
				} else {
					lines = append(lines, strings.Replace(l, ".md", ".html", -1))
				}
			}
			texts = append(texts, text{name: info.Name(), content: strings.Join(lines, "\n")})
		}
		return nil
	})
	return
}

func indentFlag(line, tLine string) (lines []string) {
	words := strings.Split(tLine, "  ")
	desc := strings.TrimSpace(words[len(words)-1])
	dWords := strings.Split(desc, " ")
	times := math.Ceil(float64(len(desc)) / maxDescLength)
	for i := 0; float64(i) < times; i++ {
		till := 0
		length := 0
		for i, v := range dWords {
			length += len(v)
			if length > maxDescLength {
				till = i - 1
				break
			}
			if i == len(dWords)-1 {
				till = len(dWords)
			}
		}
		if len(dWords) == 0 {
			continue
		}
		prefix := strings.Replace(line, desc, strings.Join(dWords[:till], " "), -1)
		if i != 0 {
			prefix = strings.Repeat(" ", strings.Index(line, desc)) + strings.Join(dWords[:till], " ")
		}
		lines = append(lines, prefix)
		dWords = dWords[till:]
	}
	return
}

const html = `
<!DOCTYPE html>

    <title>Gauge - Manual</title>
    <link href="https://gauge.org/assets/images/favicons/favicon.ico" rel="shortcut icon" type="image/ico" />

Complete documentation is available here.

`
<commit_msg>theming manpage to have gauge colours<commit_after>// Copyright 2015 ThoughtWorks, Inc.

// This file is part of Gauge.

// Gauge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Gauge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Gauge.  If not, see <http://www.gnu.org/licenses/>.

package main

import (
	"log"

	"strings"

	"io/ioutil"
	"os"
	"path/filepath"

	"math"

	"html/template"

	"github.com/getgauge/common"
	"github.com/getgauge/gauge/cmd"
	"github.com/russross/blackfriday"
	"github.com/spf13/cobra"
	"github.com/spf13/cobra/doc"
)

const (
	maxDescLength = 46
	maxLineLength = 77
)

type link struct {
	Class string
	Link  string
	Name  string
}

type text struct {
	name    string
	content string
}

var indexTemplate, _ = template.New("test").Parse(`

{{ range . }}

{{ .Name }}

{{ end }}

`)

type writer struct {
	text string
}

func (w *writer) Write(b []byte) (int, error) {
	w.text += string(b)
	return 0, nil
}

func main() {
	mdPath := filepath.Join("_man", "md")
	htmlPath := filepath.Join("_man", "html")
	createDir(mdPath)
	createDir(htmlPath)
	if err := genMarkdownManPages(mdPath); err != nil {
		log.Fatal(err.Error())
	}
	texts := indentText(mdPath)
	links := getLinks(texts)
	for _, t := range texts {
		name := strings.TrimSuffix(t.name, filepath.Ext(t.name)) + ".html"
		var newLinks []link
		for _, l := range links {
			if l.Link == name {
				newLinks = append(newLinks, link{Name: l.Name, Link: l.Link, Class: "active"})
			} else {
				newLinks = append(newLinks, l)
			}
		}
		page := strings.Replace(html, "", prepareIndex(newLinks), -1)
		output := strings.Replace(page, "", string(blackfriday.MarkdownCommon([]byte(t.content))), -1)
		ioutil.WriteFile(filepath.Join(htmlPath, name), []byte(output), 0644)
	}
	log.Printf("HTML man pages are available in %s dir\n", htmlPath)
}
func createDir(p string) {
	if err := os.MkdirAll(p, common.NewDirectoryPermissions); err != nil {
		log.Fatal(err.Error())
	}
}

func genMarkdownManPages(out string) error {
	if err := doc.GenMarkdownTree(setupCmd(), out); err != nil {
		return err
	}
	log.Printf("Added markdown man pages to `%s`\n", out)
	return nil
}

func setupCmd() *cobra.Command {
	cmd.GaugeCmd.Short = "A light-weight cross-platform test automation tool"
	cmd.GaugeCmd.Long = "Gauge is a light-weight cross-platform test automation tool with the ability to author test cases in the business language."
	return cmd.GaugeCmd
}

func getLinks(texts []text) (links []link) {
	for _, t := range texts {
		name := strings.TrimSuffix(t.name, filepath.Ext(t.name))
		links = append(links, link{Class: "", Name: strings.Replace(name, "_", " ", -1), Link: name + ".html"})
	}
	return
}

func prepareIndex(links []link) string {
	w := &writer{}
	err := indexTemplate.Execute(w, links)
	if err != nil {
		log.Fatalf(err.Error())
	}
	return w.text
}

func indentText(p string) (texts []text) {
	filepath.Walk(p, func(path string, info os.FileInfo, err error) error {
		if strings.HasSuffix(info.Name(), ".md") {
			bytes, err := ioutil.ReadFile(path)
			if err != nil {
				return err
			}
			var lines []string
			for _, l := range strings.Split(string(bytes), string("\n")) {
				tLine := strings.TrimSpace(l)
				if strings.HasPrefix(tLine, "-") && len(tLine) > maxLineLength {
					lines = append(lines, indentFlag(l, tLine)...)
				} else {
					lines = append(lines, strings.Replace(l, ".md", ".html", -1))
				}
			}
			texts = append(texts, text{name: info.Name(), content: strings.Join(lines, "\n")})
		}
		return nil
	})
	return
}

func indentFlag(line, tLine string) (lines []string) {
	words := strings.Split(tLine, "  ")
	desc := strings.TrimSpace(words[len(words)-1])
	dWords := strings.Split(desc, " ")
	times := math.Ceil(float64(len(desc)) / maxDescLength)
	for i := 0; float64(i) < times; i++ {
		till := 0
		length := 0
		for i, v := range dWords {
			length += len(v)
			if length > maxDescLength {
				till = i - 1
				break
			}
			if i == len(dWords)-1 {
				till = len(dWords)
			}
		}
		if len(dWords) == 0 {
			continue
		}
		prefix := strings.Replace(line, desc, strings.Join(dWords[:till], " "), -1)
		if i != 0 {
			prefix = strings.Repeat(" ", strings.Index(line, desc)) + strings.Join(dWords[:till], " ")
		}
		lines = append(lines, prefix)
		dWords = dWords[till:]
	}
	return
}

const html = `
<!DOCTYPE html>

    <title>Gauge - Manual</title>
    <link href="https://gauge.org/assets/images/favicons/favicon.ico" rel="shortcut icon" type="image/ico" />

Complete documentation is available here.

`
<|endoftext|>


<commit_before>package grader

import (
	"archive/tar"
	"bufio"
	"compress/gzip"
	"errors"
	"fmt"
	"github.com/omegaup/quark/common"
	git "gopkg.in/libgit2/git2go.v22"
	"io"
	"net/http"
	"os"
	"path"
)

type GraderInput struct {
	common.BaseInput
	repositoryPath string
}

type GraderInputFactory struct {
	run    *common.Run
	config *common.Config
}

func NewGraderInputFactory(run *common.Run, config *common.Config) common.InputFactory {
	return &GraderInputFactory{
		run:    run,
		config: config,
	}
}

func (factory *GraderInputFactory) NewInput(mgr *common.InputManager) common.Input {
	return &GraderInput{
		BaseInput: *common.NewBaseInput(factory.run.InputHash, mgr,
			path.Join(factory.config.Grader.RuntimePath,
				"cache", fmt.Sprintf("%s.tar.gz", factory.run.InputHash))),
		repositoryPath: path.Join(factory.config.Grader.RuntimePath,
			"problems.git", factory.run.Problem.Name),
	}
}

func (input *GraderInput) Transmit(w http.ResponseWriter) error {
	hash, err := input.getStoredHash()
	if err != nil {
		return err
	}
	fd, err := os.Open(input.Path())
	if err != nil {
		return err
	}
	defer fd.Close()
	w.Header().Add("Content-SHA1", hash)
	fmt.Println(hash)
	w.WriteHeader(http.StatusOK)
	_, err = io.Copy(w, fd)
	return err
}

func (input *GraderInput) getStoredHash() (string, error) {
	hashFd, err := os.Open(fmt.Sprintf("%s.sha1", input.Path()))
	if err != nil {
		return "", err
	}
	defer hashFd.Close()
	scanner := bufio.NewScanner(hashFd)
	scanner.Split(bufio.ScanWords)
	if !scanner.Scan() {
		if scanner.Err() != nil {
			return "", scanner.Err()
		}
		return "", io.ErrUnexpectedEOF
	}
	return scanner.Text(), nil
}

func (input *GraderInput) Verify() error {
	stat, err := os.Stat(input.Path())
	if err != nil {
		return err
	}
	hash, err := common.Sha1sum(input.Path())
	if err != nil {
		return err
	}
	storedHash, err := input.getStoredHash()
	if err != nil {
		return err
	}
	if storedHash != fmt.Sprintf("%0x", hash) {
		return errors.New("Hash verification failed")
	}

	input.Commit(stat.Size())
	return nil
}

func (input *GraderInput) CreateArchive() error {
	if err := os.MkdirAll(path.Dir(input.Path()), 0755); err != nil {
		return err
	}
	tmpPath := fmt.Sprintf("%s.tmp", input.Path())
	defer os.Remove(tmpPath)
	if err := input.createArchiveFromGit(tmpPath); err != nil {
		return err
	}

	stat, err := os.Stat(tmpPath)
	if err != nil {
		return err
	}

	hash, err := common.Sha1sum(tmpPath)
	if err != nil {
		return err
	}

	hashFd, err := os.Create(fmt.Sprintf("%s.sha1", input.Path()))
	if err != nil {
		return err
	}
	defer hashFd.Close()

	if _, err := fmt.Fprintf(hashFd, "%0x *%s\n", hash, path.Base(input.Path())); err != nil {
		return err
	}

	if err := os.Rename(tmpPath, input.Path()); err != nil {
		return err
	}

	input.Commit(stat.Size())
	return nil
}

func (input *GraderInput) DeleteArchive() error {
	os.Remove(fmt.Sprintf("%s.tmp", input.Path()))
	os.Remove(fmt.Sprintf("%s.sha1", input.Path()))
	return os.Remove(input.Path())
}

func (input *GraderInput) createArchiveFromGit(archivePath string) error {
	repository, err := git.OpenRepository(input.repositoryPath)
	if err != nil {
		return err
	}
	defer repository.Free()

	treeOid, err := git.NewOid(input.Hash())
	if err != nil {
		return err
	}

	tree, err := repository.LookupTree(treeOid)
	if err != nil {
		return err
	}
	defer tree.Free()
	odb, err := repository.Odb()
	if err != nil {
		return err
	}
	defer odb.Free()

	tmpFd, err := os.Create(archivePath)
	if err != nil {
		return err
	}
	defer tmpFd.Close()

	gz := gzip.NewWriter(tmpFd)
	defer gz.Close()

	archive := tar.NewWriter(gz)
	defer archive.Close()

	var walkErr error = nil
	tree.Walk(func(parent string, entry *git.TreeEntry) int {
		switch entry.Type {
		case git.ObjectTree:
			hdr := &tar.Header{
				Name:     path.Join(parent, entry.Name),
				Typeflag: tar.TypeDir,
				Mode:     0755,
				Size:     0,
			}
			if walkErr = archive.WriteHeader(hdr); walkErr != nil {
				return -1
			}
		case git.ObjectBlob:
			blob, walkErr := repository.LookupBlob(entry.Id)
			if walkErr != nil {
				return -1
			}
			defer blob.Free()

			hdr := &tar.Header{
				Name:     path.Join(parent, entry.Name),
				Typeflag: tar.TypeReg,
				Mode:     0644,
				Size:     blob.Size(),
			}
			if walkErr = archive.WriteHeader(hdr); walkErr != nil {
				return -1
			}

			stream, err := odb.NewReadStream(entry.Id)
			if err == nil {
				defer stream.Free()
				if _, walkErr := io.Copy(archive, stream); walkErr != nil {
					return -1
				}
			} else {
				// That particular object cannot be streamed. Allocate the blob in
				// memory and write it to the archive.
				if _, walkErr := archive.Write(blob.Contents()); walkErr != nil {
					return -1
				}
			}
		}
		return 0
	})

	return walkErr
}
<commit_msg>Avoid stdout spam<commit_after>package grader

import (
	"archive/tar"
	"bufio"
	"compress/gzip"
	"errors"
	"fmt"
	"github.com/omegaup/quark/common"
	git "gopkg.in/libgit2/git2go.v22"
	"io"
	"net/http"
	"os"
	"path"
)

type GraderInput struct {
	common.BaseInput
	repositoryPath string
}

type GraderInputFactory struct {
	run    *common.Run
	config *common.Config
}

func NewGraderInputFactory(run *common.Run, config *common.Config) common.InputFactory {
	return &GraderInputFactory{
		run:    run,
		config: config,
	}
}

func (factory *GraderInputFactory) NewInput(mgr *common.InputManager) common.Input {
	return &GraderInput{
		BaseInput: *common.NewBaseInput(factory.run.InputHash, mgr,
			path.Join(factory.config.Grader.RuntimePath,
				"cache", fmt.Sprintf("%s.tar.gz", factory.run.InputHash))),
		repositoryPath: path.Join(factory.config.Grader.RuntimePath,
			"problems.git", factory.run.Problem.Name),
	}
}

func (input *GraderInput) Transmit(w http.ResponseWriter) error {
	hash, err := input.getStoredHash()
	if err != nil {
		return err
	}
	fd, err := os.Open(input.Path())
	if err != nil {
		return err
	}
	defer fd.Close()
	w.Header().Add("Content-SHA1", hash)
	w.WriteHeader(http.StatusOK)
	_, err = io.Copy(w, fd)
	return err
}

func (input *GraderInput) getStoredHash() (string, error) {
	hashFd, err := os.Open(fmt.Sprintf("%s.sha1", input.Path()))
	if err != nil {
		return "", err
	}
	defer hashFd.Close()
	scanner := bufio.NewScanner(hashFd)
	scanner.Split(bufio.ScanWords)
	if !scanner.Scan() {
		if scanner.Err() != nil {
			return "", scanner.Err()
		}
		return "", io.ErrUnexpectedEOF
	}
	return scanner.Text(), nil
}

func (input *GraderInput) Verify() error {
	stat, err := os.Stat(input.Path())
	if err != nil {
		return err
	}
	hash, err := common.Sha1sum(input.Path())
	if err != nil {
		return err
	}
	storedHash, err := input.getStoredHash()
	if err != nil {
		return err
	}
	if storedHash != fmt.Sprintf("%0x", hash) {
		return errors.New("Hash verification failed")
	}

	input.Commit(stat.Size())
	return nil
}

func (input *GraderInput) CreateArchive() error {
	if err := os.MkdirAll(path.Dir(input.Path()), 0755); err != nil {
		return err
	}
	tmpPath := fmt.Sprintf("%s.tmp", input.Path())
	defer os.Remove(tmpPath)
	if err := input.createArchiveFromGit(tmpPath); err != nil {
		return err
	}

	stat, err := os.Stat(tmpPath)
	if err != nil {
		return err
	}

	hash, err := common.Sha1sum(tmpPath)
	if err != nil {
		return err
	}

	hashFd, err := os.Create(fmt.Sprintf("%s.sha1", input.Path()))
	if err != nil {
		return err
	}
	defer hashFd.Close()

	if _, err := fmt.Fprintf(hashFd, "%0x *%s\n", hash, path.Base(input.Path())); err != nil {
		return err
	}

	if err := os.Rename(tmpPath, input.Path()); err != nil {
		return err
	}

	input.Commit(stat.Size())
	return nil
}

func (input *GraderInput) DeleteArchive() error {
	os.Remove(fmt.Sprintf("%s.tmp", input.Path()))
	os.Remove(fmt.Sprintf("%s.sha1", input.Path()))
	return os.Remove(input.Path())
}

func (input *GraderInput) createArchiveFromGit(archivePath string) error {
	repository, err := git.OpenRepository(input.repositoryPath)
	if err != nil {
		return err
	}
	defer repository.Free()

	treeOid, err := git.NewOid(input.Hash())
	if err != nil {
		return err
	}

	tree, err := repository.LookupTree(treeOid)
	if err != nil {
		return err
	}
	defer tree.Free()
	odb, err := repository.Odb()
	if err != nil {
		return err
	}
	defer odb.Free()

	tmpFd, err := os.Create(archivePath)
	if err != nil {
		return err
	}
	defer tmpFd.Close()

	gz := gzip.NewWriter(tmpFd)
	defer gz.Close()

	archive := tar.NewWriter(gz)
	defer archive.Close()

	var walkErr error = nil
	tree.Walk(func(parent string, entry *git.TreeEntry) int {
		switch entry.Type {
		case git.ObjectTree:
			hdr := &tar.Header{
				Name:     path.Join(parent, entry.Name),
				Typeflag: tar.TypeDir,
				Mode:     0755,
				Size:     0,
			}
			if walkErr = archive.WriteHeader(hdr); walkErr != nil {
				return -1
			}
		case git.ObjectBlob:
			blob, walkErr := repository.LookupBlob(entry.Id)
			if walkErr != nil {
				return -1
			}
			defer blob.Free()

			hdr := &tar.Header{
				Name:     path.Join(parent, entry.Name),
				Typeflag: tar.TypeReg,
				Mode:     0644,
				Size:     blob.Size(),
			}
			if walkErr = archive.WriteHeader(hdr); walkErr != nil {
				return -1
			}

			stream, err := odb.NewReadStream(entry.Id)
			if err == nil {
				defer stream.Free()
				if _, walkErr := io.Copy(archive, stream); walkErr != nil {
					return -1
				}
			} else {
				// That particular object cannot be streamed. Allocate the blob in
				// memory and write it to the archive.
				if _, walkErr := archive.Write(blob.Contents()); walkErr != nil {
					return -1
				}
			}
		}
		return 0
	})

	return walkErr
}
<|endoftext|>


<commit_before>/*
   这是一个自己用的构建工具，一个一个的构建太麻烦了。
   这里主要整合编译，打包相应平台的
*/

package main

import (
	"archive/zip"
	"compress/flate"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"runtime"
	"strings"
)

func main() {

	switch runtime.GOOS {
	case "windows":
		windowsPkg()

	case "linux":
		linuxPkg()

	case "darwin":
		darwinPkg()
	}
}

func windowsPkg() {

	fmt.Println("编译rproxy-win64-GUI")
	if executeBash("build-win64-GUI.bat") == nil {
		fmt.Println("打包rproxy-win64-GUI")
		createZipFile("rproxy-win64-GUI.zip", true)
	}
	fmt.Println("------------------------------")

	fmt.Println("编译rproxy-win64")
	if executeBash("build-win64.bat") == nil {
		fmt.Println("打包rproxy-win64")
		createZipFile("rproxy-win64.zip", false)
	}
	fmt.Println("------------------------------")

	fmt.Println("编译rproxy-win32-GUI")
	if executeBash("build-win32-GUI.bat") == nil {
		fmt.Println("打包rproxy-win32-GUI")
		createZipFile("rproxy-win32-GUI.zip", true)
	}
	fmt.Println("------------------------------")

	fmt.Println("编译rproxy-win32")
	if executeBash("build-win32.bat") == nil {
		fmt.Println("打包rproxy-win32")
		createZipFile("rproxy-win32.zip", false)
	}
}

func linuxPkg() {

	fmt.Println("编译rproxy-linux64-GUI")
	if executeBash("build-linux64-GUI.sh") == nil {
		fmt.Println("打包rproxy-linux64-GUI")
		createZipFile("rproxy-linux64-GUI.zip", true)
	}
	fmt.Println("------------------------------")

	fmt.Println("编译rproxy-linux64")
	if executeBash("build-linux64.sh") == nil {
		fmt.Println("打包rproxy-linux64")
		createZipFile("rproxy-linux64.zip", false)
	}
	fmt.Println("------------------------------")

	fmt.Println("编译rproxy-linux32")
	if executeBash("build-linux32.sh") == nil {
		fmt.Println("打包rproxy-linux32")
		createZipFile("rproxy-linux32.zip", false)
	}
}

func darwinPkg() {

	fmt.Println("编译rproxy-darwin64")
	if executeBash("build-darwin64.sh") == nil {
		fmt.Println("打包rproxy-darwin64")
		createZipFile("rproxy-darwin64.zip", false)
	}
	fmt.Println("------------------------------")

	fmt.Println("编译rproxy-darwin32-GUI")
	if executeBash("build-darwin32-GUI.sh") == nil {
		fmt.Println("打包rproxy-darwin32-GUI")
		createZipFile("rproxy-darwin32-GUI.zip", true, true)
	}
	fmt.Println("------------------------------")

	fmt.Println("编译rproxy-darwin32")
	if executeBash("build-darwin32.sh") == nil {
		fmt.Println("打包rproxy-darwin32")
		createZipFile("rproxy-darwin32.zip", false)
	}
}

func executeBash(fileName string) error {
	var cmd *exec.Cmd
	switch runtime.GOOS {
	case "windows":
		cmd = exec.Command("cmd.exe", "/c", fileName)
	default:
		cmd = exec.Command("sh", "./"+fileName)
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
	}

	err := cmd.Run()
	if err != nil {
		fmt.Println("执行错误：", err)
	}
	return err
}

func createZipFile(zipFileName string, isGUI bool, isDarwin32 ...bool) error {
	f, err := os.Create(zipFileName)
	if err != nil {
		return err
	}
	defer f.Close()
	zw := zip.NewWriter(f)
	defer zw.Close()

	zw.RegisterCompressor(zip.Deflate,
		func(out io.Writer) (io.WriteCloser, error) {
			return flate.NewWriter(out, flate.BestCompression)
		})

	compressFile := func(fileName, aliasName string) error {
		ff, err := os.Open(fileName)
		if err != nil {
			return err
		}
		defer ff.Close()
		info, _ := ff.Stat()
		header, err := zip.FileInfoHeader(info)
		header.Method = zip.Deflate
		if aliasName != "" {
			header.Name = aliasName
		} else {
			header.Name = info.Name()
		}

		wr, err := zw.CreateHeader(header)
		if err != nil {
			return err
		}
		_, err = io.Copy(wr, ff)
		if err != nil {
			return err
		}
		return nil
	}

	// 复制文档和配置
	compressFile("../README.md", "")
	compressFile("../conf/config.cfg", "conf/config.cfg")
	compressFile("../conf/confighttps.cfg", "conf/confighttps.cfg")

	// 复制可执行文件
	exeExt := ""
	if runtime.GOOS == "windows" {
		exeExt = ".exe"
	}
	fnSuffix := ""
	if isGUI {
		fnSuffix = "_GUI"
	}

	if len(isDarwin32) == 0 {
		compressFile("../rproxy"+fnSuffix+exeExt, "rproxy"+exeExt)
	}

	// 复制动态链接库
	if isGUI {
		switch runtime.GOOS {
		case "windows":
			liblclPath := "F:\\Golang\\src\\github.com\\ying32\\govcl\\Librarys\\liblcl"
			if runtime.GOARCH == "386" {
				compressFile(liblclPath+"\\win32\\liblcl.dll", "")
			} else if runtime.GOARCH == "amd64" {
				compressFile(liblclPath+"\\win64\\liblcl.dll", "")
			}
		case "linux":
			if runtime.GOARCH == "amd64" {
				compressFile("/usr/lib/liblcl.so", "")
			}
		case "darwin":

			// 产生一个app
			pkgMacOSApp("../rproxy_GUI")

			compressFile("./rproxy.app/Contents/PkgInfo", "rproxy.app/Contents/PkgInfo")
			compressFile("./rproxy.app/Contents/Info.plist", "rproxy.app/Contents/Info.plist")
			compressFile("./rproxy.app/Contents/Resources/rproxy.icns", "rproxy.app/Contents/Resources/rproxy.icns")
			compressFile("./rproxy.app/Contents/MacOS/rproxy", "rproxy.app/Contents/MacOS/rproxy")
			compressFile("./rproxy.app/Contents/MacOS/liblcl.dylib", "rproxy.app/Contents/MacOS/liblcl.dylib")

		}
	}

	//zw.Flush()

	return nil
}

// --- macOS下的

const (
	infoplist = `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>zh_CN</string>
	<key>CFBundleExecutable</key>
	<string>%s</string>
	<key>CFBundleName</key>
	<string>%s</string>
	<key>CFBundleIdentifier</key>
	<string>ying32.%s</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleSignature</key>
	<string>proj</string>
	<key>CFBundleShortVersionString</key>
	<string>0.1</string>
	<key>CFBundleVersion</key>
	<string>1</string>
	<key>CSResourcesFileMapped</key>
	<true/>
	<key>CFBundleIconFile</key>
	<string>%s.icns</string>
	<key>CFBundleDocumentTypes</key>
	<array>
		<dict>
			<key>CFBundleTypeRole</key>
			<string>Viewer</string>
			<key>CFBundleTypeExtensions</key>
			<array>
				<string>*</string>
			</array>
			<key>CFBundleTypeOSTypes</key>
			<array>
				<string>fold</string>
				<string>disk</string>
				<string>****</string>
			</array>
		</dict>
	</array>
	<key>NSHighResolutionCapable</key>
	<true/>
    <key>NSHumanReadableCopyright</key>
	<string>copyright 2017-2018 ying32.com</string>
</dict>
</plist>`
)

var (
	pkgInfo = []byte{0x41, 0x50, 0x50, 0x4C, 0x3F, 0x3F, 0x3F, 0x3F, 0x0D, 0x0A}
)

func copyFile(src, dest string) error {
	filedest, err := os.Create(dest)
	if err != nil {
		return err
	}
	defer filedest.Close()
	filesrc, err := os.Open(src)
	if err != nil {
		return err
	}
	defer filesrc.Close()
	_, err = io.Copy(filedest, filesrc)
	return err
}

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

func getdylib() string {
	env := os.Getenv("GOPATH")
	if env == "" {
		return ""
	}
	for _, s := range strings.Split(env, ":") {
		s += "/bin/liblcl.dylib"
		if fileExists(s) {
			return s
		}
	}
	return ""
}

func pkgMacOSApp(exeFileName string) error {

	execName := "rproxy"
	macContentsDir := execName + ".app/Contents"
	macOSDir := macContentsDir + "/MacOS"
	macResources := macContentsDir + "/Resources"
	execFile := macOSDir + "/" + execName
	if !fileExists(macOSDir) {
		if err := os.MkdirAll(macOSDir, 0755); err != nil {
			return err
		}
	}

	if !fileExists(macResources) {
		os.MkdirAll(macResources, 0755)
	}

	copyFile("../imgs/rproxy.icns", macResources+"/rproxy.icns")

	liblclFileName := macOSDir + "/liblcl.dylib"
	if !fileExists(liblclFileName) {
		libFileName := getdylib()
		if fileExists(libFileName) {
			copyFile(libFileName, liblclFileName)
		}
	}

	plistFileName := macContentsDir + "/Info.plist"
	if !fileExists(plistFileName) {
		ioutil.WriteFile(plistFileName, []byte(fmt.Sprintf(infoplist, execName, execName, execName, execName)), 0666)
	}

	pkgInfoFileName := macContentsDir + "/PkgInfo"
	if !fileExists(pkgInfoFileName) {
		ioutil.WriteFile(pkgInfoFileName, pkgInfo, 0666)
	}

	copyFile(exeFileName, execFile)
	os.Chmod(execFile, 0755)

	return nil
}
<commit_msg>移除darwin32-GUI编译并添加darwin64-GUI支持<commit_after>/*
   这是一个自己用的构建工具，一个一个的构建太麻烦了。
   这里主要整合编译，打包相应平台的
*/

package main

import (
	"archive/zip"
	"compress/flate"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"runtime"
	"strings"
)

func main() {

	switch runtime.GOOS {
	case "windows":
		windowsPkg()

	case "linux":
		linuxPkg()

	case "darwin":
		darwinPkg()
	}
}

func windowsPkg() {

	fmt.Println("编译rproxy-win64-GUI")
	if executeBash("build-win64-GUI.bat") == nil {
		fmt.Println("打包rproxy-win64-GUI")
		createZipFile("rproxy-win64-GUI.zip", true)
	}
	fmt.Println("------------------------------")

	fmt.Println("编译rproxy-win64")
	if executeBash("build-win64.bat") == nil {
		fmt.Println("打包rproxy-win64")
		createZipFile("rproxy-win64.zip", false)
	}
	fmt.Println("------------------------------")

	fmt.Println("编译rproxy-win32-GUI")
	if executeBash("build-win32-GUI.bat") == nil {
		fmt.Println("打包rproxy-win32-GUI")
		createZipFile("rproxy-win32-GUI.zip", true)
	}
	fmt.Println("------------------------------")

	fmt.Println("编译rproxy-win32")
	if executeBash("build-win32.bat") == nil {
		fmt.Println("打包rproxy-win32")
		createZipFile("rproxy-win32.zip", false)
	}
}

func linuxPkg() {

	fmt.Println("编译rproxy-linux64-GUI")
	if executeBash("build-linux64-GUI.sh") == nil {
		fmt.Println("打包rproxy-linux64-GUI")
		createZipFile("rproxy-linux64-GUI.zip", true)
	}
	fmt.Println("------------------------------")

	fmt.Println("编译rproxy-linux64")
	if executeBash("build-linux64.sh") == nil {
		fmt.Println("打包rproxy-linux64")
		createZipFile("rproxy-linux64.zip", false)
	}
	fmt.Println("------------------------------")

	fmt.Println("编译rproxy-linux32")
	if executeBash("build-linux32.sh") == nil {
		fmt.Println("打包rproxy-linux32")
		createZipFile("rproxy-linux32.zip", false)
	}
}

func darwinPkg() {

	fmt.Println("编译rproxy-darwin64-GUI")
	if executeBash("build-darwin64-GUI.sh") == nil {
		fmt.Println("打包rproxy-darwin64-GUI")
		createZipFile("rproxy-darwin64-GUI.zip", true, true)
	}
	fmt.Println("------------------------------")

	fmt.Println("编译rproxy-darwin64")
	if executeBash("build-darwin64.sh") == nil {
		fmt.Println("打包rproxy-darwin64")
		createZipFile("rproxy-darwin64.zip", false)
	}
	fmt.Println("------------------------------")

	//fmt.Println("编译rproxy-darwin32-GUI")
	//if executeBash("build-darwin32-GUI.sh") == nil {
	//	fmt.Println("打包rproxy-darwin32-GUI")
	//	createZipFile("rproxy-darwin32-GUI.zip", true, true)
	//}
	//fmt.Println("------------------------------")

	fmt.Println("编译rproxy-darwin32")
	if executeBash("build-darwin32.sh") == nil {
		fmt.Println("打包rproxy-darwin32")
		createZipFile("rproxy-darwin32.zip", false)
	}
}

func executeBash(fileName string) error {
	var cmd *exec.Cmd
	switch runtime.GOOS {
	case "windows":
		cmd = exec.Command("cmd.exe", "/c", fileName)
	default:
		cmd = exec.Command("sh", "./"+fileName)
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
	}

	err := cmd.Run()
	if err != nil {
		fmt.Println("执行错误：", err)
	}
	return err
}

func createZipFile(zipFileName string, isGUI bool, isDarwinApp ...bool) error {
	f, err := os.Create(zipFileName)
	if err != nil {
		return err
	}
	defer f.Close()
	zw := zip.NewWriter(f)
	defer zw.Close()

	zw.RegisterCompressor(zip.Deflate,
		func(out io.Writer) (io.WriteCloser, error) {
			return flate.NewWriter(out, flate.BestCompression)
		})

	compressFile := func(fileName, aliasName string) error {
		ff, err := os.Open(fileName)
		if err != nil {
			return err
		}
		defer ff.Close()
		info, _ := ff.Stat()
		header, err := zip.FileInfoHeader(info)
		header.Method = zip.Deflate
		if aliasName != "" {
			header.Name = aliasName
		} else {
			header.Name = info.Name()
		}

		wr, err := zw.CreateHeader(header)
		if err != nil {
			return err
		}
		_, err = io.Copy(wr, ff)
		if err != nil {
			return err
		}
		return nil
	}

	// 复制文档和配置
	compressFile("../README.md", "")
	compressFile("../conf/config.cfg", "conf/config.cfg")
	compressFile("../conf/confighttps.cfg", "conf/confighttps.cfg")

	// 复制可执行文件
	exeExt := ""
	if runtime.GOOS == "windows" {
		exeExt = ".exe"
	}
	fnSuffix := ""
	if isGUI {
		fnSuffix = "_GUI"
	}

	if len(isDarwinApp) == 0 {
		compressFile("../rproxy"+fnSuffix+exeExt, "rproxy"+exeExt)
	}

	// 复制动态链接库
	if isGUI {
		switch runtime.GOOS {
		case "windows":
			liblclPath := "F:\\Golang\\src\\github.com\\ying32\\govcl\\Librarys\\liblcl"
			if runtime.GOARCH == "386" {
				compressFile(liblclPath+"\\win32\\liblcl.dll", "")
			} else if runtime.GOARCH == "amd64" {
				compressFile(liblclPath+"\\win64\\liblcl.dll", "")
			}
		case "linux":
			if runtime.GOARCH == "amd64" {
				compressFile("/usr/lib/liblcl.so", "")
			}
		case "darwin":

			// 产生一个app
			pkgMacOSApp("../rproxy_GUI")

			compressFile("./rproxy.app/Contents/PkgInfo", "rproxy.app/Contents/PkgInfo")
			compressFile("./rproxy.app/Contents/Info.plist", "rproxy.app/Contents/Info.plist")
			compressFile("./rproxy.app/Contents/Resources/rproxy.icns", "rproxy.app/Contents/Resources/rproxy.icns")
			compressFile("./rproxy.app/Contents/MacOS/rproxy", "rproxy.app/Contents/MacOS/rproxy")
			compressFile("./rproxy.app/Contents/MacOS/liblcl.dylib", "rproxy.app/Contents/MacOS/liblcl.dylib")

		}
	}

	//zw.Flush()

	return nil
}

// --- macOS下的

const (
	infoplist = `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>zh_CN</string>
	<key>CFBundleExecutable</key>
	<string>%s</string>
	<key>CFBundleName</key>
	<string>%s</string>
	<key>CFBundleIdentifier</key>
	<string>ying32.%s</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleSignature</key>
	<string>proj</string>
	<key>CFBundleShortVersionString</key>
	<string>0.1</string>
	<key>CFBundleVersion</key>
	<string>1</string>
	<key>CSResourcesFileMapped</key>
	<true/>
	<key>CFBundleIconFile</key>
	<string>%s.icns</string>
	<key>CFBundleDocumentTypes</key>
	<array>
		<dict>
			<key>CFBundleTypeRole</key>
			<string>Viewer</string>
			<key>CFBundleTypeExtensions</key>
			<array>
				<string>*</string>
			</array>
			<key>CFBundleTypeOSTypes</key>
			<array>
				<string>fold</string>
				<string>disk</string>
				<string>****</string>
			</array>
		</dict>
	</array>
	<key>NSHighResolutionCapable</key>
	<true/>
    <key>NSHumanReadableCopyright</key>
	<string>copyright 2017-2018 ying32.com</string>
</dict>
</plist>`
)

var (
	pkgInfo = []byte{0x41, 0x50, 0x50, 0x4C, 0x3F, 0x3F, 0x3F, 0x3F, 0x0D, 0x0A}
)

func copyFile(src, dest string) error {
	filedest, err := os.Create(dest)
	if err != nil {
		return err
	}
	defer filedest.Close()
	filesrc, err := os.Open(src)
	if err != nil {
		return err
	}
	defer filesrc.Close()
	_, err = io.Copy(filedest, filesrc)
	return err
}

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

func getdylib() string {
	env := os.Getenv("GOPATH")
	if env == "" {
		return ""
	}
	for _, s := range strings.Split(env, ":") {
		s += "/bin/liblcl.dylib"
		if fileExists(s) {
			return s
		}
	}
	return ""
}

func pkgMacOSApp(exeFileName string) error {

	execName := "rproxy"
	macContentsDir := execName + ".app/Contents"
	macOSDir := macContentsDir + "/MacOS"
	macResources := macContentsDir + "/Resources"
	execFile := macOSDir + "/" + execName
	if !fileExists(macOSDir) {
		if err := os.MkdirAll(macOSDir, 0755); err != nil {
			return err
		}
	}

	if !fileExists(macResources) {
		os.MkdirAll(macResources, 0755)
	}

	copyFile("../imgs/rproxy.icns", macResources+"/rproxy.icns")

	liblclFileName := macOSDir + "/liblcl.dylib"
	if !fileExists(liblclFileName) {
		libFileName := getdylib()
		if fileExists(libFileName) {
			copyFile(libFileName, liblclFileName)
		}
	}

	plistFileName := macContentsDir + "/Info.plist"
	if !fileExists(plistFileName) {
		ioutil.WriteFile(plistFileName, []byte(fmt.Sprintf(infoplist, execName, execName, execName, execName)), 0666)
	}

	pkgInfoFileName := macContentsDir + "/PkgInfo"
	if !fileExists(pkgInfoFileName) {
		ioutil.WriteFile(pkgInfoFileName, pkgInfo, 0666)
	}

	copyFile(exeFileName, execFile)
	os.Chmod(execFile, 0755)

	return nil
}
<|endoftext|>


<commit_before>package chain

import (
	"sort"

	"github.com/btcboost/copernicus/conf"
	"github.com/btcboost/copernicus/model/blockindex"
	"github.com/btcboost/copernicus/model/chainparams"
	"github.com/btcboost/copernicus/model/consensus"
	"github.com/btcboost/copernicus/model/pow"
	"github.com/btcboost/copernicus/model/script"
	"github.com/btcboost/copernicus/model/versionbits"
	"github.com/btcboost/copernicus/persist/global"
	"github.com/btcboost/copernicus/util"
	"gopkg.in/eapache/queue.v1"
)

// Chain An in-memory blIndexed chain of blocks.
type Chain struct {
	active      []*blockindex.BlockIndex
	branch      []*blockindex.BlockIndex
	waitForTx   map[util.Hash]*blockindex.BlockIndex
	orphan      map[util.Hash][]*blockindex.BlockIndex  // preHash : *index
	indexMap    map[util.Hash]*blockindex.BlockIndex  // selfHash :*index
	newestBlock *blockindex.BlockIndex
	receiveID   uint64
	params      *chainparams.BitcoinParams
}

var globalChain *Chain

func GetInstance() *Chain {
	if globalChain == nil {
		panic("globalChain do not init")
	}
	return globalChain
}

func InitGlobalChain(cfg *conf.Configuration){
	if globalChain == nil {
		globalChain = NewChain()
		globalChain.params = &chainparams.TestNet3Params
	}
}
func NewChain() *Chain {

	return NewFakeChain()
	//return &Chain{}
}
func (c *Chain)GetParams() *chainparams.BitcoinParams {
	return c.params
}
func (c *Chain)InitLoad(indexMap map[util.Hash]*blockindex.BlockIndex, branch  []*blockindex.BlockIndex){
	c.indexMap = indexMap
	c.branch =  branch
}
// Genesis Returns the blIndex entry for the genesis block of this chain,
// or nullptr if none.
func (c *Chain) Genesis() *blockindex.BlockIndex {
	if len(c.active) > 0 {
		return c.active[0]
	}

	return nil
}

func (c *Chain) AddReceivedID(){
	c.receiveID += 1
}
func (c *Chain) GetReceivedID() uint64{
	return c.receiveID
}

//find blockindex from blockIndexMap
func (c *Chain) FindBlockIndex(hash util.Hash) *blockindex.BlockIndex {
	bi, ok := c.indexMap[hash]
	if ok {
		return bi
	}

	return nil
}

// Tip Returns the blIndex entry for the tip of this chain, or nullptr if none.
func (c *Chain) Tip() *blockindex.BlockIndex {
	if len(c.active) > 0 {
		return c.active[len(c.active)-1]
	}

	return nil
}

func (c *Chain) TipHeight() int32 {
	if len(c.active) > 0 {
		return c.active[len(c.active)-1].Height
	}

	return 0
}

func (c *Chain) GetSpendHeight(hash *util.Hash) int32{
	index, _ := c.indexMap[*hash]
	return index.Height + 1
}

func (c *Chain) GetBlockScriptFlags(pindex *blockindex.BlockIndex) uint32 {
	// TODO: AssertLockHeld(cs_main);
	// var sc sync.RWMutex
	// sc.Lock()
	// defer sc.Unlock()

	// BIP16 didn't become active until Apr 1 2012
	nBIP16SwitchTime := 1333238400
	fStrictPayToScriptHash := int(pindex.GetBlockTime()) >= nBIP16SwitchTime
	param := c.params
	var flags uint32

	if fStrictPayToScriptHash {
		flags = script.ScriptVerifyP2SH
	} else {
		flags = script.ScriptVerifyNone
	}

	// Start enforcing the DERSIG (BIP66) rule
	if pindex.Height >= param.BIP66Height {
		flags |= script.ScriptVerifyDersig
	}

	// Start enforcing CHECKLOCKTIMEVERIFY (BIP65) rule
	if pindex.Height >= param.BIP65Height {
		flags |= script.ScriptVerifyCheckLockTimeVerify
	}

	// Start enforcing BIP112 (CHECKSEQUENCEVERIFY) using versionbits logic.
	if versionbits.VersionBitsState(pindex.Prev, param, consensus.DeploymentCSV, versionbits.VBCache) == versionbits.ThresholdActive {
		flags |= script.ScriptVerifyCheckSequenceVerify
	}
	// If the UAHF is enabled, we start accepting replay protected txns
	if chainparams.IsUAHFEnabled(pindex.Height) {
		flags |= script.ScriptVerifyStrictEnc
		flags |= script.ScriptEnableSigHashForkId
	}

	// If the Cash HF is enabled, we start rejecting transaction that use a high
	// s in their signature. We also make sure that signature that are supposed
	// to fail (for instance in multisig or other forms of smart contracts) are
	// null.
	if pindex.IsCashHFEnabled(param) {
		flags |= script.ScriptVerifyLowS
		flags |= script.ScriptVerifyNullFail
	}

	return flags
}

// GetSpecIndex Returns the blIndex entry at a particular height in this chain, or nullptr
// if no such height exists.
func (c *Chain) GetIndex(height int32) *blockindex.BlockIndex {
	if height < 0 || height >= int32(len(c.active)) {
		return nil
	}

	return c.active[height]
}

// Equal Compare two chains efficiently.
func (c *Chain) Equal(dst *Chain) bool {
	return len(c.active) == len(dst.active) &&
		c.active[len(c.active)-1] == dst.active[len(dst.active)-1]
}

// Contains /** Efficiently check whether a block is present in this chain
func (c *Chain) Contains(index *blockindex.BlockIndex) bool {
	return c.GetIndex(index.Height) == index
}

// Next Find the successor of a block in this chain, or nullptr if the given
// index is not found or is the tip.
func (c *Chain) Next(index *blockindex.BlockIndex) *blockindex.BlockIndex {
	if c.Contains(index) {
		return c.GetIndex(index.Height + 1)
	}
	return nil
}

// Height Return the maximal height in the chain. Is equal to chain.Tip() ?
// chain.Tip()->nHeight : -1.
func (c *Chain) Height() int32 {
	return int32(len(c.active) - 1)
}

// SetTip Set/initialize a chain with a given tip.
func (c *Chain) SetTip(index *blockindex.BlockIndex) {
	if index == nil {
		c.active = []*blockindex.BlockIndex{}
		return
	}

	tmp := make([]*blockindex.BlockIndex, index.Height+1)
	copy(tmp, c.active)
	c.active = tmp
	for index != nil && c.active[index.Height] != index {
		c.active[index.Height] = index
		index = index.Prev
	}
}

func (c *Chain) GetAncestor(height int32) *blockindex.BlockIndex {
	// todo
	return nil
}

func (ch *Chain) GetLocator(index *blockindex.BlockIndex) *BlockLocator {
	step := 1
	blockHashList := make([]util.Hash, 0, 32)
	if index == nil {
		index = ch.Tip()
	}
	for {
		blockHashList = append(blockHashList, *index.GetBlockHash())
		if index.Height == 0 {
			break
		}
		height := index.Height - int32(step)
		if height < 0 {
			height = 0
		}
		if ch.Contains(index) {
			index = ch.GetIndex(height)
		} else {
			index = ch.GetAncestor(height)
		}
		if len(blockHashList) > 10 {
			step *= 2
		}
	}
	return NewBlockLocator(blockHashList)
}

// FindFork Find the last common block between this chain and a block blIndex entry.
func (chain *Chain) FindFork(blIndex *blockindex.BlockIndex) *blockindex.BlockIndex {
	if blIndex == nil {
		return nil
	}

	if blIndex.Height > chain.Height() {
		blIndex = blIndex.GetAncestor(chain.Height())
	}

	for blIndex != nil && !chain.Contains(blIndex) {
		blIndex = blIndex.Prev
	}
	return blIndex
}

// FindEarliestAtLeast Find the earliest block with timestamp equal or greater than the given.
func (chain *Chain) FindEarliestAtLeast(time int64) *blockindex.BlockIndex {

	return nil
}

func (chain *Chain) ActiveBest(bi *blockindex.BlockIndex) error {

	return nil
}

func (chain *Chain) RemoveFromBranch(bis []*blockindex.BlockIndex) {

}

//find blockindex'parent in branch
func (c *Chain) ParentInBranch(pindex *blockindex.BlockIndex) bool {
	for _, bi := range c.branch{
		bh := pindex.Header
		if bi.GetBlockHash().IsEqual(&bh.HashPrevBlock) {
			return true
		}
	}
	return false
}
//find blockindex in branch
func (c *Chain) InBranch(pindex *blockindex.BlockIndex) bool {
	for _, bi := range c.branch{
		bh := pindex.GetBlockHash()
		if bi.GetBlockHash().IsEqual(bh) {
			return true
		}
	}
	return false
}
func (c *Chain) insertToBranch(bis *blockindex.BlockIndex) {
	c.branch = append(c.branch, bis)
	sort.SliceStable(c.branch, func(i, j int) bool {
		jWork := c.branch[j].ChainWork
		return c.branch[i].ChainWork.Cmp(&jWork) == -1
	})
}
func (c *Chain) AddToBranch(bis *blockindex.BlockIndex) {

	q := queue.New()
	q.Add(bis)
	// Recursively process any descendant blocks that now may be eligible to
	// be connected.
	for q.Length() > 0 {
		qindex := q.Remove()
		pindex := qindex.(*blockindex.BlockIndex)
		if !pindex.IsGenesis() {
			pindex.ChainTxCount += pindex.Prev.ChainTxCount
		} else {
			pindex.ChainTxCount = pindex.TxCount
		}
		pindex.SequenceID = c.GetReceivedID()
		c.AddReceivedID()
		// todo if pindex's work is less then tip's work
		// if c.Tip() == nil || (c.Tip() !=nil && pindex.ChainWork.Cmp(&c.Tip().ChainWork)<=1) {
		//
		// }
		if !c.InBranch(pindex){
			c.insertToBranch(pindex)
		}
		preHash := pindex.GetBlockHash()
		childList, ok := c.orphan[*preHash]
		if ok{
			for child := range childList{
				q.Add(child)
			}
			delete(c.orphan, *preHash)
		}
	}
}

func (c *Chain) FindMostWorkChain() *blockindex.BlockIndex {
	if len(c.branch)>0{
		return c.branch[len(c.branch)-1]
	}
	return nil
}

func (c *Chain) AddToIndexMap(bi *blockindex.BlockIndex) error {
	// We assign the sequence id to blocks only when the full data is available,
	// to avoid miners withholding blocks but broadcasting headers, to get a
	// competitive advantage.
	bi.SequenceID = 0
	hash := bi.GetBlockHash()
	c.indexMap[*hash] = bi
	bh := bi.Header
	pre, ok := c.indexMap[bh.HashPrevBlock]
	if ok{
		bi.Prev = pre
		bi.Height = pre.Height+1
		bi.BuildSkip()
	}
	bi.TimeMax = bi.Header.Time
	blockProof := pow.GetBlockProof(bi)
	bi.ChainWork = *blockProof
	if pre != nil {
		 if pre.TimeMax > bi.TimeMax{
		 	bi.TimeMax = pre.TimeMax
		 }
		bi.ChainWork = *bi.ChainWork.Add(&bi.ChainWork,&pre.ChainWork)
	}
	bi.AddStatus(blockindex.BlockValidTree)
	gPersist := global.GetInstance()
	gPersist.AddDirtyBlockIndex(*bi.GetBlockHash(), bi)
	return nil
}

func (c *Chain) AddToOrphan(bi *blockindex.BlockIndex) error {
	bh := bi.Header
	childList, ok := c.orphan[bh.HashPrevBlock]
	if !ok{
		childList = make([]*blockindex.BlockIndex,0,1)
	}
	childList = append(childList, bi)
	c.orphan[bh.HashPrevBlock] = childList
	return nil
}
<commit_msg>fix chain.GetAncestor<commit_after>package chain

import (
	"sort"

	"github.com/btcboost/copernicus/conf"
	"github.com/btcboost/copernicus/model/blockindex"
	"github.com/btcboost/copernicus/model/chainparams"
	"github.com/btcboost/copernicus/model/consensus"
	"github.com/btcboost/copernicus/model/pow"
	"github.com/btcboost/copernicus/model/script"
	"github.com/btcboost/copernicus/model/versionbits"
	"github.com/btcboost/copernicus/persist/global"
	"github.com/btcboost/copernicus/util"
	"gopkg.in/eapache/queue.v1"
)

// Chain An in-memory blIndexed chain of blocks.
type Chain struct {
	active      []*blockindex.BlockIndex
	branch      []*blockindex.BlockIndex
	waitForTx   map[util.Hash]*blockindex.BlockIndex
	orphan      map[util.Hash][]*blockindex.BlockIndex  // preHash : *index
	indexMap    map[util.Hash]*blockindex.BlockIndex  // selfHash :*index
	newestBlock *blockindex.BlockIndex
	receiveID   uint64
	params      *chainparams.BitcoinParams
}

var globalChain *Chain

func GetInstance() *Chain {
	if globalChain == nil {
		panic("globalChain do not init")
	}
	return globalChain
}

func InitGlobalChain(cfg *conf.Configuration){
	if globalChain == nil {
		globalChain = NewChain()
		globalChain.params = &chainparams.TestNet3Params
	}
}
func NewChain() *Chain {

	return NewFakeChain()
	//return &Chain{}
}
func (c *Chain)GetParams() *chainparams.BitcoinParams {
	return c.params
}
func (c *Chain)InitLoad(indexMap map[util.Hash]*blockindex.BlockIndex, branch  []*blockindex.BlockIndex){
	c.indexMap = indexMap
	c.branch =  branch
}
// Genesis Returns the blIndex entry for the genesis block of this chain,
// or nullptr if none.
func (c *Chain) Genesis() *blockindex.BlockIndex {
	if len(c.active) > 0 {
		return c.active[0]
	}

	return nil
}

func (c *Chain) AddReceivedID(){
	c.receiveID += 1
}
func (c *Chain) GetReceivedID() uint64{
	return c.receiveID
}

//find blockindex from blockIndexMap
func (c *Chain) FindBlockIndex(hash util.Hash) *blockindex.BlockIndex {
	bi, ok := c.indexMap[hash]
	if ok {
		return bi
	}

	return nil
}

// Tip Returns the blIndex entry for the tip of this chain, or nullptr if none.
func (c *Chain) Tip() *blockindex.BlockIndex {
	if len(c.active) > 0 {
		return c.active[len(c.active)-1]
	}

	return nil
}

func (c *Chain) TipHeight() int32 {
	if len(c.active) > 0 {
		return c.active[len(c.active)-1].Height
	}

	return 0
}

func (c *Chain) GetSpendHeight(hash *util.Hash) int32{
	index, _ := c.indexMap[*hash]
	return index.Height + 1
}

func (c *Chain) GetBlockScriptFlags(pindex *blockindex.BlockIndex) uint32 {
	// TODO: AssertLockHeld(cs_main);
	// var sc sync.RWMutex
	// sc.Lock()
	// defer sc.Unlock()

	// BIP16 didn't become active until Apr 1 2012
	nBIP16SwitchTime := 1333238400
	fStrictPayToScriptHash := int(pindex.GetBlockTime()) >= nBIP16SwitchTime
	param := c.params
	var flags uint32

	if fStrictPayToScriptHash {
		flags = script.ScriptVerifyP2SH
	} else {
		flags = script.ScriptVerifyNone
	}

	// Start enforcing the DERSIG (BIP66) rule
	if pindex.Height >= param.BIP66Height {
		flags |= script.ScriptVerifyDersig
	}

	// Start enforcing CHECKLOCKTIMEVERIFY (BIP65) rule
	if pindex.Height >= param.BIP65Height {
		flags |= script.ScriptVerifyCheckLockTimeVerify
	}

	// Start enforcing BIP112 (CHECKSEQUENCEVERIFY) using versionbits logic.
	if versionbits.VersionBitsState(pindex.Prev, param, consensus.DeploymentCSV, versionbits.VBCache) == versionbits.ThresholdActive {
		flags |= script.ScriptVerifyCheckSequenceVerify
	}
	// If the UAHF is enabled, we start accepting replay protected txns
	if chainparams.IsUAHFEnabled(pindex.Height) {
		flags |= script.ScriptVerifyStrictEnc
		flags |= script.ScriptEnableSigHashForkId
	}

	// If the Cash HF is enabled, we start rejecting transaction that use a high
	// s in their signature. We also make sure that signature that are supposed
	// to fail (for instance in multisig or other forms of smart contracts) are
	// null.
	if pindex.IsCashHFEnabled(param) {
		flags |= script.ScriptVerifyLowS
		flags |= script.ScriptVerifyNullFail
	}

	return flags
}

// GetSpecIndex Returns the blIndex entry at a particular height in this chain, or nullptr
// if no such height exists.
func (c *Chain) GetIndex(height int32) *blockindex.BlockIndex {
	if height < 0 || height >= int32(len(c.active)) {
		return nil
	}

	return c.active[height]
}

// Equal Compare two chains efficiently.
func (c *Chain) Equal(dst *Chain) bool {
	return len(c.active) == len(dst.active) &&
		c.active[len(c.active)-1] == dst.active[len(dst.active)-1]
}

// Contains /** Efficiently check whether a block is present in this chain
func (c *Chain) Contains(index *blockindex.BlockIndex) bool {
	return c.GetIndex(index.Height) == index
}

// Next Find the successor of a block in this chain, or nullptr if the given
// index is not found or is the tip.
func (c *Chain) Next(index *blockindex.BlockIndex) *blockindex.BlockIndex {
	if c.Contains(index) {
		return c.GetIndex(index.Height + 1)
	}
	return nil
}

// Height Return the maximal height in the chain. Is equal to chain.Tip() ?
// chain.Tip()->nHeight : -1.
func (c *Chain) Height() int32 {
	return int32(len(c.active) - 1)
}

// SetTip Set/initialize a chain with a given tip.
func (c *Chain) SetTip(index *blockindex.BlockIndex) {
	if index == nil {
		c.active = []*blockindex.BlockIndex{}
		return
	}

	tmp := make([]*blockindex.BlockIndex, index.Height+1)
	copy(tmp, c.active)
	c.active = tmp
	for index != nil && c.active[index.Height] != index {
		c.active[index.Height] = index
		index = index.Prev
	}
}

// get ancestor from active chain
func (c *Chain) GetAncestor(height int32) *blockindex.BlockIndex {
	if len(c.active) >= int(height){
		return c.active[height]
	}
	return nil
}

func (ch *Chain) GetLocator(index *blockindex.BlockIndex) *BlockLocator {
	step := 1
	blockHashList := make([]util.Hash, 0, 32)
	if index == nil {
		index = ch.Tip()
	}
	for {
		blockHashList = append(blockHashList, *index.GetBlockHash())
		if index.Height == 0 {
			break
		}
		height := index.Height - int32(step)
		if height < 0 {
			height = 0
		}
		if ch.Contains(index) {
			index = ch.GetIndex(height)
		} else {
			index = index.GetAncestor(height)
		}
		if len(blockHashList) > 10 {
			step *= 2
		}
	}
	return NewBlockLocator(blockHashList)
}

// FindFork Find the last common block between this chain and a block blIndex entry.
func (chain *Chain) FindFork(blIndex *blockindex.BlockIndex) *blockindex.BlockIndex {
	if blIndex == nil {
		return nil
	}

	if blIndex.Height > chain.Height() {
		blIndex = blIndex.GetAncestor(chain.Height())
	}

	for blIndex != nil && !chain.Contains(blIndex) {
		blIndex = blIndex.Prev
	}
	return blIndex
}

// FindEarliestAtLeast Find the earliest block with timestamp equal or greater than the given.
func (chain *Chain) FindEarliestAtLeast(time int64) *blockindex.BlockIndex {

	return nil
}

func (chain *Chain) ActiveBest(bi *blockindex.BlockIndex) error {

	return nil
}

func (chain *Chain) RemoveFromBranch(bis []*blockindex.BlockIndex) {

}

//find blockindex'parent in branch
func (c *Chain) ParentInBranch(pindex *blockindex.BlockIndex) bool {
	for _, bi := range c.branch{
		bh := pindex.Header
		if bi.GetBlockHash().IsEqual(&bh.HashPrevBlock) {
			return true
		}
	}
	return false
}
//find blockindex in branch
func (c *Chain) InBranch(pindex *blockindex.BlockIndex) bool {
	for _, bi := range c.branch{
		bh := pindex.GetBlockHash()
		if bi.GetBlockHash().IsEqual(bh) {
			return true
		}
	}
	return false
}
func (c *Chain) insertToBranch(bis *blockindex.BlockIndex) {
	c.branch = append(c.branch, bis)
	sort.SliceStable(c.branch, func(i, j int) bool {
		jWork := c.branch[j].ChainWork
		return c.branch[i].ChainWork.Cmp(&jWork) == -1
	})
}
func (c *Chain) AddToBranch(bis *blockindex.BlockIndex) {

	q := queue.New()
	q.Add(bis)
	// Recursively process any descendant blocks that now may be eligible to
	// be connected.
	for q.Length() > 0 {
		qindex := q.Remove()
		pindex := qindex.(*blockindex.BlockIndex)
		if !pindex.IsGenesis() {
			pindex.ChainTxCount += pindex.Prev.ChainTxCount
		} else {
			pindex.ChainTxCount = pindex.TxCount
		}
		pindex.SequenceID = c.GetReceivedID()
		c.AddReceivedID()
		// todo if pindex's work is less then tip's work
		// if c.Tip() == nil || (c.Tip() !=nil && pindex.ChainWork.Cmp(&c.Tip().ChainWork)<=1) {
		//
		// }
		if !c.InBranch(pindex){
			c.insertToBranch(pindex)
		}
		preHash := pindex.GetBlockHash()
		childList, ok := c.orphan[*preHash]
		if ok{
			for child := range childList{
				q.Add(child)
			}
			delete(c.orphan, *preHash)
		}
	}
}

func (c *Chain) FindMostWorkChain() *blockindex.BlockIndex {
	if len(c.branch)>0{
		return c.branch[len(c.branch)-1]
	}
	return nil
}

func (c *Chain) AddToIndexMap(bi *blockindex.BlockIndex) error {
	// We assign the sequence id to blocks only when the full data is available,
	// to avoid miners withholding blocks but broadcasting headers, to get a
	// competitive advantage.
	bi.SequenceID = 0
	hash := bi.GetBlockHash()
	c.indexMap[*hash] = bi
	bh := bi.Header
	pre, ok := c.indexMap[bh.HashPrevBlock]
	if ok{
		bi.Prev = pre
		bi.Height = pre.Height+1
		bi.BuildSkip()
	}
	bi.TimeMax = bi.Header.Time
	blockProof := pow.GetBlockProof(bi)
	bi.ChainWork = *blockProof
	if pre != nil {
		 if pre.TimeMax > bi.TimeMax{
		 	bi.TimeMax = pre.TimeMax
		 }
		bi.ChainWork = *bi.ChainWork.Add(&bi.ChainWork,&pre.ChainWork)
	}
	bi.AddStatus(blockindex.BlockValidTree)
	gPersist := global.GetInstance()
	gPersist.AddDirtyBlockIndex(*bi.GetBlockHash(), bi)
	return nil
}

func (c *Chain) AddToOrphan(bi *blockindex.BlockIndex) error {
	bh := bi.Header
	childList, ok := c.orphan[bh.HashPrevBlock]
	if !ok{
		childList = make([]*blockindex.BlockIndex,0,1)
	}
	childList = append(childList, bi)
	c.orphan[bh.HashPrevBlock] = childList
	return nil
}
<|endoftext|>


<commit_before>package builder

// nginx
const (
	NginxVersion           = "1.21.6"
	NginxDownloadURLPrefix = "https://nginx.org/download"
)

// pcre
const (
	PcreVersion           = "10.40"
	PcreDownloadURLPrefix = "https://github.com/PhilipHazel/pcre2/releases/download"
)

// openssl
const (
	OpenSSLVersion           = "1.1.1n"
	OpenSSLDownloadURLPrefix = "https://www.openssl.org/source"
)

// libressl
const (
	LibreSSLVersion           = "3.4.2"
	LibreSSLDownloadURLPrefix = "https://ftp.openbsd.org/pub/OpenBSD/LibreSSL"
)

// zlib
const (
	ZlibVersion           = "1.2.12"
	ZlibDownloadURLPrefix = "https://zlib.net"
)

// openResty
const (
	OpenRestyVersion           = "1.19.9.1"
	OpenRestyDownloadURLPrefix = "https://openresty.org/download"
)

// tengine
const (
	TengineVersion           = "2.3.3"
	TengineDownloadURLPrefix = "https://tengine.taobao.org/download"
)

// component enumerations
const (
	ComponentNginx = iota
	ComponentOpenResty
	ComponentTengine
	ComponentPcre
	ComponentOpenSSL
	ComponentLibreSSL
	ComponentZlib
	ComponentMax
)
<commit_msg>bumped default libressl version to 3.4.3.<commit_after>package builder

// nginx
const (
	NginxVersion           = "1.21.6"
	NginxDownloadURLPrefix = "https://nginx.org/download"
)

// pcre
const (
	PcreVersion           = "10.40"
	PcreDownloadURLPrefix = "https://github.com/PhilipHazel/pcre2/releases/download"
)

// openssl
const (
	OpenSSLVersion           = "1.1.1n"
	OpenSSLDownloadURLPrefix = "https://www.openssl.org/source"
)

// libressl
const (
	LibreSSLVersion           = "3.4.3"
	LibreSSLDownloadURLPrefix = "https://ftp.openbsd.org/pub/OpenBSD/LibreSSL"
)

// zlib
const (
	ZlibVersion           = "1.2.12"
	ZlibDownloadURLPrefix = "https://zlib.net"
)

// openResty
const (
	OpenRestyVersion           = "1.19.9.1"
	OpenRestyDownloadURLPrefix = "https://openresty.org/download"
)

// tengine
const (
	TengineVersion           = "2.3.3"
	TengineDownloadURLPrefix = "https://tengine.taobao.org/download"
)

// component enumerations
const (
	ComponentNginx = iota
	ComponentOpenResty
	ComponentTengine
	ComponentPcre
	ComponentOpenSSL
	ComponentLibreSSL
	ComponentZlib
	ComponentMax
)
<|endoftext|>


<commit_before>package builder

import (
	"html/template"

	"github.com/aymerick/kowa/models"
	"github.com/microcosm-cc/bluemonday"
	"github.com/russross/blackfriday"
)

// Builder for posts pages
type PostsBuilder struct {
	*NodeBuilderBase

	posts []*PostNodeContentPair
}

// Post content for template
type PostContent struct {
	Date  string
	Cover string
	Title string
	Body  template.HTML
	Url   string
}

// Post with associated Node Content
type PostNodeContentPair struct {
	post        *models.Post
	nodeContent *PostContent
}

// Post list content for template
type PostListContent struct {
	Title   string
	Tagline string

	Posts    []*PostContent
	PrevPage string
	NextPage string
}

func init() {
	RegisterNodeBuilder(KIND_POSTS, NewPostsBuilder)
}

// Instanciate a new builder
func NewPostsBuilder(siteBuilder *SiteBuilder) NodeBuilder {
	return &PostsBuilder{
		NodeBuilderBase: &NodeBuilderBase{
			nodeKind:    KIND_POST,
			siteBuilder: siteBuilder,
		},
	}
}

func NewPostNodeContentPair(post *models.Post, nodeContent *PostContent) *PostNodeContentPair {
	return &PostNodeContentPair{
		post:        post,
		nodeContent: nodeContent,
	}
}

// NodeBuilder
func (builder *PostsBuilder) Load() {
	builder.loadPosts()
	builder.loadPostsLists()
}

// Build all posts
func (builder *PostsBuilder) loadPosts() {
	for _, post := range *builder.site().FindAllPosts() {
		builder.loadPost(post)
	}
}

// Build post page
func (builder *PostsBuilder) loadPost(post *models.Post) {
	node := builder.newNode()
	node.fillUrl(post.Slug())

	node.Title = post.Title
	node.Meta = &NodeMeta{
		Description: "", // @todo !!!
	}

	postContent := builder.NewPostContent(post, node)

	node.Content = postContent

	builder.addNode(node)

	builder.posts = append(builder.posts, NewPostNodeContentPair(post, postContent))
}

// Instanciate a new post content
func (builder *PostsBuilder) NewPostContent(post *models.Post, node *Node) *PostContent {
	result := &PostContent{
		Date:  post.CreatedAt.Format("02/01/06"),
		Title: post.Title,
		Url:   node.Url,
	}

	cover := post.FindCover()
	if cover != nil {
		result.Cover = builder.addImage(cover, models.MEDIUM_KIND)
	}

	html := blackfriday.MarkdownCommon([]byte(post.Body))
	result.Body = template.HTML(bluemonday.UGCPolicy().SanitizeBytes(html))

	return result
}

// Build posts list pages
func (builder *PostsBuilder) loadPostsLists() {
	if len(builder.posts) > 0 {
		// @todo pagination
		node := builder.newNodeForKind(KIND_POSTS)
		node.fillUrl(KIND_POSTS)

		title := "Posts"
		tagline := "" // @todo

		node.Title = title
		node.Meta = &NodeMeta{Description: tagline}
		node.Content = &PostListContent{
			Title:   title,
			Tagline: tagline,
			Posts:   computesPostContents(builder.posts),
		}
		node.InNavBar = true
		node.NavBarOrder = 5

		builder.addNode(node)
	}
}

func computesPostContents(posts []*PostNodeContentPair) []*PostContent {
	postContents := []*PostContent{}

	for _, postNodeContent := range posts {
		postContents = append(postContents, postNodeContent.nodeContent)
	}

	return postContents
}
<commit_msg>builder: prefix post url with /posts/<commit_after>package builder

import (
	"html/template"
	"path"

	"github.com/microcosm-cc/bluemonday"
	"github.com/russross/blackfriday"

	"github.com/aymerick/kowa/models"
)

// Builder for posts pages
type PostsBuilder struct {
	*NodeBuilderBase

	posts []*PostNodeContentPair
}

// Post content for template
type PostContent struct {
	Date  string
	Cover string
	Title string
	Body  template.HTML
	Url   string
}

// Post with associated Node Content
type PostNodeContentPair struct {
	post        *models.Post
	nodeContent *PostContent
}

// Post list content for template
type PostListContent struct {
	Title   string
	Tagline string

	Posts []*PostContent
	// PrevPage string
	// NextPage string
}

func init() {
	RegisterNodeBuilder(KIND_POSTS, NewPostsBuilder)
}

// Instanciate a new builder
func NewPostsBuilder(siteBuilder *SiteBuilder) NodeBuilder {
	return &PostsBuilder{
		NodeBuilderBase: &NodeBuilderBase{
			nodeKind:    KIND_POST,
			siteBuilder: siteBuilder,
		},
	}
}

func NewPostNodeContentPair(post *models.Post, nodeContent *PostContent) *PostNodeContentPair {
	return &PostNodeContentPair{
		post:        post,
		nodeContent: nodeContent,
	}
}

// NodeBuilder
func (builder *PostsBuilder) Load() {
	builder.loadPosts()
	builder.loadPostsLists()
}

// Build all posts
func (builder *PostsBuilder) loadPosts() {
	for _, post := range *builder.site().FindAllPosts() {
		builder.loadPost(post)
	}
}

// Build post page
func (builder *PostsBuilder) loadPost(post *models.Post) {
	node := builder.newNode()
	node.fillUrl(path.Join("posts", post.Slug())) // @todo i18n

	node.Title = post.Title
	node.Meta = &NodeMeta{
		Description: "", // @todo !!!
	}

	postContent := builder.NewPostContent(post, node)

	node.Content = postContent

	builder.addNode(node)

	builder.posts = append(builder.posts, NewPostNodeContentPair(post, postContent))
}

// Instanciate a new post content
func (builder *PostsBuilder) NewPostContent(post *models.Post, node *Node) *PostContent {
	result := &PostContent{
		Date:  post.CreatedAt.Format("02/01/06"),
		Title: post.Title,
		Url:   node.Url,
	}

	cover := post.FindCover()
	if cover != nil {
		result.Cover = builder.addImage(cover, models.MEDIUM_KIND)
	}

	html := blackfriday.MarkdownCommon([]byte(post.Body))
	result.Body = template.HTML(bluemonday.UGCPolicy().SanitizeBytes(html))

	return result
}

// Build posts list pages
func (builder *PostsBuilder) loadPostsLists() {
	if len(builder.posts) > 0 {
		// @todo pagination
		node := builder.newNodeForKind(KIND_POSTS)
		node.fillUrl(KIND_POSTS)

		title := "Posts"
		tagline := "" // @todo

		node.Title = title
		node.Meta = &NodeMeta{Description: tagline}
		node.Content = &PostListContent{
			Title:   title,
			Tagline: tagline,
			Posts:   computesPostContents(builder.posts),
		}
		node.InNavBar = true
		node.NavBarOrder = 5

		builder.addNode(node)
	}
}

func computesPostContents(posts []*PostNodeContentPair) []*PostContent {
	postContents := []*PostContent{}

	for _, postNodeContent := range posts {
		postContents = append(postContents, postNodeContent.nodeContent)
	}

	return postContents
}
<|endoftext|>


<commit_before>package pane

import (
	"github.com/chrisseto/sux/pansi"
	"github.com/nsf/termbox-go"
	"log"
)

func (p *Pane) handleEscapeCode(c *pansi.AnsiEscapeCode) {
	switch c.Type {
	case pansi.SetGraphicMode:
		p.SetGraphicMode(c.Values)
	case pansi.CursorPosition:
		if len(c.Values) == 0 {
			p.cx, p.cy = 0, 0
		} else {
			p.cx, p.cy = c.Values[1]-1, c.Values[0]-1
		}
	case pansi.CursorUp:
		p.cy--
	case pansi.CursorDown:
		p.cy++
	case pansi.CursorBackward:
		p.cx--
	case pansi.CursorForward:
		p.cx++
	case pansi.VPA:
		if len(c.Values) == 0 {
			p.cy = 0
		} else {
			p.cy = c.Values[0] - 1
		}
	case pansi.EraseLine:
		row := p.screen.Row(p.cy)
		for i := p.cx; i < len(*row); i++ {
			(*row)[i] = termbox.Cell{' ', p.fg, p.bg}
		}
	case pansi.EraseDisplay:
		p.Clear()
	default:
		log.Printf("Doing nothing with %+v\n", *c)
	}
}

func (p *Pane) SetGraphicMode(vals []int) {
	for i := 0; i < len(vals); i++ {
		switch vals[i] {
		case 0:
			p.fg, p.bg = 8, 1
		case 1:
			p.fg |= termbox.AttrBold
		case 7:
			p.fg, p.bg = p.bg, p.fg
		case 38:
			i++
			switch vals[i] {
			case 5:
				i++
				p.fg = termbox.Attribute(vals[i] + 1)
			case 2:
				i += 3 //TODO
			}
		case 39:
			p.fg = termbox.ColorWhite
		case 48:
			i++
			switch vals[i] {
			case 5:
				i++
				p.bg = termbox.Attribute(vals[i] + 1)
			case 2:
				i += 3 //TODO
			}
		case 49:
			p.bg = termbox.ColorBlack
		}
	}
}
<commit_msg>Add default behavior for SGM<commit_after>package pane

import (
	"github.com/chrisseto/sux/pansi"
	"github.com/nsf/termbox-go"
	"log"
)

func (p *Pane) handleEscapeCode(c *pansi.AnsiEscapeCode) {
	switch c.Type {
	case pansi.SetGraphicMode:
		p.SetGraphicMode(c.Values)
	case pansi.CursorPosition:
		if len(c.Values) == 0 {
			p.cx, p.cy = 0, 0
		} else {
			p.cx, p.cy = c.Values[1]-1, c.Values[0]-1
		}
	case pansi.CursorUp:
		p.cy--
	case pansi.CursorDown:
		p.cy++
	case pansi.CursorBackward:
		p.cx--
	case pansi.CursorForward:
		p.cx++
	case pansi.VPA:
		if len(c.Values) == 0 {
			p.cy = 0
		} else {
			p.cy = c.Values[0] - 1
		}
	case pansi.EraseLine:
		row := p.screen.Row(p.cy)
		for i := p.cx; i < len(*row); i++ {
			(*row)[i] = termbox.Cell{' ', p.fg, p.bg}
		}
	case pansi.EraseDisplay:
		p.Clear()
	default:
		log.Printf("Doing nothing with %+v\n", *c)
	}
}

func (p *Pane) SetGraphicMode(vals []int) {
	if len(vals) == 0 {
		p.fg, p.bg = 8, 1
		return
	}
	for i := 0; i < len(vals); i++ {
		switch vals[i] {
		case 0:
			p.fg, p.bg = 8, 1
		case 1:
			p.fg |= termbox.AttrBold
		case 7:
			p.fg, p.bg = p.bg, p.fg
		case 38:
			i++
			switch vals[i] {
			case 5:
				i++
				p.fg = termbox.Attribute(vals[i] + 1)
			case 2:
				i += 3 //TODO
			}
		case 39:
			p.fg = termbox.ColorWhite
		case 48:
			i++
			switch vals[i] {
			case 5:
				i++
				p.bg = termbox.Attribute(vals[i] + 1)
			case 2:
				i += 3 //TODO
			}
		case 49:
			p.bg = termbox.ColorBlack
		}
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 The ivi developers. All rights reserved.
// Project site: https://github.com/gotmc/ivi
// Use of this source code is governed by a MIT-style license that
// can be found in the LICENSE.txt file for the project.

package ivi

import (
	"errors"
	"regexp"
)

type Inherent struct {
	inst Instrument
	InherentBase
}

type InherentBase struct {
	ClassSpecMajorVersion     int
	ClassSpecMinorVersion     int
	ClassSpecRevision         string
	GroupCapabilities         string
	SupportedInstrumentModels []string
	IDNString                 string
}

func NewInherent(inst Instrument, base InherentBase) Inherent {
	return Inherent{
		inst:         inst,
		InherentBase: base,
	}
}

// FirmwardRevision queries the instrument and returns the firmware revision of
// the instrument. FirmwareRevision is the getter for the read-only inherent
// attribute Instrument Firmware Revision described in Section 5.18 of IVI-3.2:
// Inherent Capabilities Specification.
func (inherent *Inherent) FirmwareRevision() (string, error) {
	return inherent.parseIdentification("fwr")
}

// InstrumentManufacturer queries the instrument and returns the manufacturer
// of the instrument. InstrumentManufacturer is the getter for the read-only
// inherent attribute Instrument Manufacturer described in Section 5.19 of
// IVI-3.2: Inherent Capabilities Specification.
func (inherent *Inherent) InstrumentManufacturer() (string, error) {
	return inherent.parseIdentification("mfr")
}

// InstrumentModel queries the instrument and returns the model of the
// instrument.  InstrumentModel is the getter for the read-only inherent
// attribute Instrument Model described in Section 5.20 of IVI-3.2: Inherent
// Capabilities Specification.
func (inherent *Inherent) InstrumentModel() (string, error) {
	return inherent.parseIdentification("model")
}

func (inherent *Inherent) Reset() error {
	_, err := inherent.inst.WriteString("*RST\n")
	return err
}

func (inherent *Inherent) Clear() error {
	_, err := inherent.inst.WriteString("*CLS\n")
	return err
}

// Disable places the instrument in a quiescent state as quickly as possible.
// Disable provides the method described in Section 6.4 of IVI-3.2: Inherent
// Capabilities Specification.
func (inherent *Inherent) Disable() error {
	// FIXME(mdr): Implement!!!!
	return errors.New("disable is not yet implemented.")
}

func (inherent *Inherent) parseIdentification(part string) (string, error) {
	s, err := inherent.inst.Query("*IDN?\n")
	if err != nil {
		return "", err
	}
	re := regexp.MustCompile(inherent.IDNString)
	res := re.FindStringSubmatch(s)
	subexpNames := re.SubexpNames()
	matchMap := map[string]string{}
	for i, n := range res {
		matchMap[subexpNames[i]] = string(n)
	}
	return matchMap[part], nil
}
<commit_msg>Add InstrumentSerialNumber to inherent.go<commit_after>// Copyright (c) 2017 The ivi developers. All rights reserved.
// Project site: https://github.com/gotmc/ivi
// Use of this source code is governed by a MIT-style license that
// can be found in the LICENSE.txt file for the project.

package ivi

import (
	"errors"
	"regexp"
)

type Inherent struct {
	inst Instrument
	InherentBase
}

type InherentBase struct {
	ClassSpecMajorVersion     int
	ClassSpecMinorVersion     int
	ClassSpecRevision         string
	GroupCapabilities         string
	SupportedInstrumentModels []string
	IDNString                 string
}

func NewInherent(inst Instrument, base InherentBase) Inherent {
	return Inherent{
		inst:         inst,
		InherentBase: base,
	}
}

// FirmwardRevision queries the instrument and returns the firmware revision of
// the instrument. FirmwareRevision is the getter for the read-only inherent
// attribute Instrument Firmware Revision described in Section 5.18 of IVI-3.2:
// Inherent Capabilities Specification.
func (inherent *Inherent) FirmwareRevision() (string, error) {
	return inherent.parseIdentification("fwr")
}

// InstrumentManufacturer queries the instrument and returns the manufacturer
// of the instrument. InstrumentManufacturer is the getter for the read-only
// inherent attribute Instrument Manufacturer described in Section 5.19 of
// IVI-3.2: Inherent Capabilities Specification.
func (inherent *Inherent) InstrumentManufacturer() (string, error) {
	return inherent.parseIdentification("mfr")
}

// InstrumentModel queries the instrument and returns the model of the
// instrument.  InstrumentModel is the getter for the read-only inherent
// attribute Instrument Model described in Section 5.20 of IVI-3.2: Inherent
// Capabilities Specification.
func (inherent *Inherent) InstrumentModel() (string, error) {
	return inherent.parseIdentification("model")
}

// InstrumentSerialNumber queries the instrument and returns the S/N of the
// instrument.
func (inherent *Inherent) InstrumentSerialNumber() (string, error) {
	return inherent.parseIdentification("sn")
}

func (inherent *Inherent) Reset() error {
	_, err := inherent.inst.WriteString("*RST\n")
	return err
}

func (inherent *Inherent) Clear() error {
	_, err := inherent.inst.WriteString("*CLS\n")
	return err
}

// Disable places the instrument in a quiescent state as quickly as possible.
// Disable provides the method described in Section 6.4 of IVI-3.2: Inherent
// Capabilities Specification.
func (inherent *Inherent) Disable() error {
	// FIXME(mdr): Implement!!!!
	return errors.New("disable is not yet implemented.")
}

func (inherent *Inherent) parseIdentification(part string) (string, error) {
	s, err := inherent.inst.Query("*IDN?\n")
	if err != nil {
		return "", err
	}
	re := regexp.MustCompile(inherent.IDNString)
	res := re.FindStringSubmatch(s)
	subexpNames := re.SubexpNames()
	matchMap := map[string]string{}
	for i, n := range res {
		matchMap[subexpNames[i]] = string(n)
	}
	return matchMap[part], nil
}
<|endoftext|>


<commit_before>// Copyright 2012 Christian Neumann. All rights reserved.
// Use of this source code is governed by a BSD license
// that can be found in the COPYING file.

/*
Package worker implements operations to manage and communicate with a worker
process that processes incoming requests for some node type.
*/
package worker
<commit_msg>Remove old copyright information.<commit_after>/*
Package worker implements operations to manage and communicate with a worker
process that processes incoming requests for some node type.
*/
package worker
<|endoftext|>