package buildfile import ( "bufio" "errors" "io" "strings" ) var ErrInvalidSyntax = errors.New("invalid instruction format") var ErrUnknownInstruction = errors.New("unknown instruction") type instruction_type byte const ( // INSTALL one or more package(s) INSTALL instruction_type = iota // UPDATE all installed packages candidates UPDATE // REMOVE one or more package(s) REMOVE // SERVICE management (enable, disable, start, stop, restart, reload) SERVICE // CONF edits configuration files CONF ) // instruction is self-explanatory type instruction struct { Type instruction_type // Sub command instruction-type-specific Sub []string Args string } // Reader is the buildfile reader type Reader struct { // linux distribution to run on distribution string Content []*instruction } // NewReader creates a new reader for the specified build file and linux distribution func NewReader(distro string, buildfile io.Reader) (*Reader, error) { r := &Reader{ distribution: distro, Content: make([]*instruction, 0), } // read each line l, reader := 0, bufio.NewReader(buildfile) for { l++ line, err := reader.ReadString('\n') if err == io.EOF { break } else if err != nil { return nil, LineError{l, err} } line = strings.Trim(line, " \t\n") // check line base syntax 'cmd args...' if len(line) < 5 || len(strings.Trim(line[0:3], " ")) < 3 || line[1] == ' ' || line[3] != ' ' { return nil, LineError{l, ErrInvalidSyntax} } // build instruction from line inst := &instruction{ Type: INSTALL, Sub: make([]string, 0), Args: line[4:], } switch line[0:3] { case "ins": inst.Type = INSTALL case "upd": inst.Type = UPDATE case "del": inst.Type = REMOVE case "ser": inst.Type = SERVICE case "cnf": inst.Type = CONF default: return nil, LineError{l, ErrUnknownInstruction} } r.Content = append(r.Content, inst) } return r, nil }