func pageShow(w http.ResponseWriter, r *http.Request, p httprouter.Params) *httphelper.HandlerError { l := httphelper.NewHandlerLogEntry(r) etype := p.ByName("type") project := p.ByName("project") l.Debug("Type: ", etype) l.Debug("Project: ", project) projects, err := helper.ProjectNamesFromArgs(dataStore, []string{project}, false) if err != nil { return httphelper.NewHandlerErrorDef(errgo.Notef(err, "can not get list of projects")) } err = dataStore.PopulateProjects(&projects) if err != nil { return httphelper.NewHandlerErrorDef(errgo.Notef(err, "can not populate projects with entries")) } buffer := new(bytes.Buffer) formatting.Projects(buffer, "Entries", 0, &projects) err = asciiDoctor(buffer, w) if err != nil { return httphelper.NewHandlerErrorDef(errgo.Notef(err, "can not format entries with asciidoctor")) } return nil }
func ParseTodo(values []string) (Todo, error) { if len(values) != 4 { return Todo{}, errgo.New("entry with the type todo needs exactly four fields") } etype, err := ParseEntryType(values[0]) if err != nil { return Todo{}, errgo.Notef(err, "can not parse entry type") } if etype != EntryTypeTodo { return Todo{}, errgo.New("tried to parse a todo but got the entry type " + etype.String()) } timestamp, err := time.Parse(TimeStampFormat, values[1]) if err != nil { return Todo{}, errgo.Notef(err, "can not parse timestamp") } active, err := strconv.ParseBool(values[2]) if err != nil { return Todo{}, errgo.Notef(err, "can not parse active state") } return Todo{Active: active, TimeStamp: timestamp, Value: values[3]}, nil }
func runCmdAddNote(cmd *cobra.Command, args []string) error { project, timestamp, value, err := helper.ArgsToEntryValues(args, flagAddTimeStamp, flagAddTimeStampRaw) if err != nil { return errgo.Notef(err, "can not convert args to entry usable values") } buffer := new(bytes.Buffer) if value != "-" { buffer.WriteString(value) } // If there is something piped in over stdin append it to the already set // value stat, _ := os.Stdin.Stat() if (stat.Mode() & os.ModeCharDevice) == 0 { io.Copy(buffer, os.Stdin) } note := data.Note{ Value: buffer.String(), TimeStamp: timestamp, } err = helper.RecordEntry(flagDataDir, project, note, flagAddAutoCommit) if err != nil { errgo.Notef(err, "can not record note to store") } return nil }
func (db *DBFiles) Put(values []string, key ...string) error { record := record{ values: values, key: key, basedir: db.BaseDir, } _, err := os.Stat(record.basedir) if os.IsNotExist(err) { err := db.Structure.Create(record.basedir) if err != nil { return errgo.Notef(err, "can not create structure") } } file, err := db.Structure.File(record.basedir, db.Driver, record.key) if err != nil { return errgo.Notef(err, "can not open file") } defer file.Close() err = db.Driver.Write(file, record.values) if err != nil { return errgo.Notef(err, "can not write values") } var data []byte io.ReadFull(file, data) log.Debug("Data: ", string(data)) log.Debug("finished writing record: ", record) return err }
func Listen(datadir, binding string, loglevel log.Level) error { var err error dataStore, err = helper.DefaultStore(datadir) if err != nil { return errgo.Notef(err, "can not get data store") } router := httprouter.New() // Router handler router.MethodNotAllowed = httphelper.HandlerLoggerHTTP(httphelper.PageRouterMethodNotAllowed) router.NotFound = httphelper.HandlerLoggerHTTP(httphelper.PageRouterNotFound) // Root and Favicon router.GET("/", httphelper.HandlerLoggerRouter(pageRoot)) router.GET("/favicon.ico", httphelper.HandlerLoggerRouter(pageFavicon)) // Show router.GET("/show/:type/", httphelper.HandlerLoggerRouter(pageShow)) router.GET("/show/:type/:project", httphelper.HandlerLoggerRouter(pageShow)) log.Info("Listening on ", binding) err = http.ListenAndServe(binding, router) if err != nil { return errgo.Notef(err, "can not listen to binding") } return nil }
// ProjectNamesFromArgs will return all projects or all projects with // subprojects if the length of the args is not 0. func ProjectNamesFromArgs(store store.Store, args []string, showarchive bool) (data.Projects, error) { projects, err := store.ListProjects(showarchive) if err != nil { return data.Projects{}, errgo.Notef(err, "can not get list of projects") } log.Debug("Args: ", args) out := data.NewProjects() if len(args) == 0 { out = projects } else { for _, arg := range args { name, err := data.ParseProjectName(arg) if err != nil { return data.Projects{}, errgo.Notef(err, "can not parse project name") } items := projects.List(data.Project{Name: name}) for _, item := range items { out.Add(item) } } } return out, nil }
func parseDockerPort(input string, dp *Port) error { s := strings.Split(input, "/") switch len(s) { case 1: dp.Port = s[0] dp.Protocol = protocolTCP case 2: dp.Port = s[0] dp.Protocol = s[1] default: return errgo.Newf("Invalid format, must be either <port> or <port>/<prot>, got '%s'", input) } if parsedPort, err := strconv.Atoi(dp.Port); err != nil { return errgo.Notef(err, "Port must be a number, got '%s'", dp.Port) } else if parsedPort < 1 || parsedPort > 65535 { return errgo.Notef(err, "Port must be a number between 1 and 65535, got '%s'", dp.Port) } switch dp.Protocol { case "": return errgo.Newf("Protocol must not be empty.") case protocolUDP, protocolTCP: return nil default: return errgo.Newf("Unknown protocol: '%s' in '%s'", dp.Protocol, input) } }
func TestNotef(t *testing.T) { err0 := errgo.WithCausef(nil, someErr, "foo") //err TestNotef#0 err := errgo.Notef(err0, "bar") //err TestNotef#1 checkErr(t, err, err0, "bar: foo", "[{$TestNotef#1$: bar} {$TestNotef#0$: foo}]", err) err = errgo.Notef(nil, "bar") //err TestNotef#2 checkErr(t, err, nil, "bar", "[{$TestNotef#2$: bar}]", err) }
func (*errorsSuite) TestNotef(c *gc.C) { err0 := errgo.WithCausef(nil, someErr, "foo") //err TestNotef#0 err := errgo.Notef(err0, "bar") //err TestNotef#1 checkErr(c, err, err0, "bar: foo", "[{$TestNotef#1$: bar} {$TestNotef#0$: foo}]", err) err = errgo.Notef(nil, "bar") //err TestNotef#2 checkErr(c, err, nil, "bar", "[{$TestNotef#2$: bar}]", err) }
func main() { if FlagLogFile != "" { logfile, err := os.OpenFile(FlagLogFile, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0644) if err != nil { log.Fatal(errgo.Notef(err, "can not open logfile for writing")) } defer logfile.Close() log.SetOutput(logfile) } log.Info("Starting buchführung api v", BuildVersion, " +", BuildTime) err := initDatabase() if err != nil { log.Fatal(errgo.Notef(err, "can not initialize database")) } go func() { router := httprouter.New() // Router handler router.MethodNotAllowed = httphelper.HandlerLoggerHTTP(httphelper.PageRouterMethodNotAllowed) router.NotFound = httphelper.HandlerLoggerHTTP(httphelper.PageRouterNotFound) // Root and Favicon router.GET("/", httphelper.HandlerLoggerRouter(pageRoot)) router.GET("/favicon.ico", httphelper.HandlerLoggerRouter(httphelper.PageMinimalFavicon)) // API v0 // Accounts router.POST("/api/v0/account/add", httphelper.HandlerLoggerRouter(pageAPIV0AccountAdd)) router.GET("/api/v0/account/get/byid/:id", httphelper.HandlerLoggerRouter(pageAPIV0AccountGetByID)) router.GET("/api/v0/account/get/byname/:name", httphelper.HandlerLoggerRouter(pageAPIV0AccountGetByName)) router.GET("/api/v0/account/list", httphelper.HandlerLoggerRouter(pageAPIV0AccountList)) // Transactions router.POST("/api/v0/transaction/add", httphelper.HandlerLoggerRouter(pageAPIV0TransactionAdd)) router.GET("/api/v0/transaction/get/byid/:id", httphelper.HandlerLoggerRouter(pageAPIV0TransactionGetByID)) router.GET("/api/v0/transaction/list", httphelper.HandlerLoggerRouter(pageAPIV0TransactionList)) log.Info("Start serving api on ", FlagBindingAPI) log.Fatal(http.ListenAndServe(FlagBindingAPI, router)) }() go func() { if FlagBindingMetrics != "" { log.Info("Starting Metrics", FlagBindingMetrics) http.Handle("/metrics", prometheus.Handler()) http.ListenAndServe(FlagBindingMetrics, nil) } }() log.Debug("Waiting for interrupt signal") httphelper.WaitForStopSignal() log.Info("Stopping") }
func PageMinimalFavicon(w http.ResponseWriter, r *http.Request, p httprouter.Params) *HandlerError { raw, err := Asset("data/favicon.ico") if err != nil { return NewHandlerErrorDef(errgo.Notef(err, "can not read raw page")) } _, err = w.Write(raw) if err != nil { return NewHandlerErrorDef(errgo.Notef(err, "can not write raw data to responsewriter")) } return nil }
func getAssetTemplate(asset string) (*template.Template, error) { rawtmpl, err := Asset(asset) if err != nil { return nil, errgo.Notef(err, "can not get asset: "+asset) } tmpl, err := template.New(asset).Parse(string(rawtmpl)) if err != nil { return nil, errgo.Notef(err, "can not parse template for asset: "+asset) } return tmpl, nil }
func pageFavicon(w http.ResponseWriter, r *http.Request, p httprouter.Params) *httphelper.HandlerError { raw, err := Asset("templates/trivago-folder.ico") if err != nil { return httphelper.NewHandlerErrorDef(errgo.Notef(err, "can not read raw page")) } _, err = w.Write(raw) if err != nil { return httphelper.NewHandlerErrorDef(errgo.Notef(err, "can not write raw data to responsewriter")) } return nil }
func runWeb(cmd *cobra.Command, args []string) error { level, err := log.ParseLevel(flagLogLevel) if err != nil { return errgo.Notef(err, "can not parse loglevel from flag") } err = web.Listen(flagDataDir, flagWebBinding, level) if err != nil { return errgo.Notef(err, "can not start web listener") } return nil }
func (db DBFiles) Get(key ...string) ([][]string, error) { file, err := db.Structure.File(db.BaseDir, db.Driver, key) if err != nil { return nil, errgo.Notef(err, "can not open file") } values, err := db.Driver.Read(file) if err != nil { return nil, errgo.Notef(err, "can not read values") } return values, nil }
func main() { flag.StringVar(&flagDataDir, "datadir", ".lablog", "the path to the datadir to use as the source of files.") flag.StringVar(&flagOutDir, "outdir", "output", "the path to the output directroy in which the converted files will be saved.") flag.Parse() log.Debug("DataDir: ", flagDataDir) log.Debug("OutDir: ", flagOutDir) dbread := dbfiles.New() dbread.Structure = dbfiles.NewFlat() dbread.BaseDir = flagDataDir readKeys, err := dbread.Keys() if err != nil { log.Fatal(errgo.Notef(err, "can not get keys from datadir")) } store, err := store.NewFolderStore(flagOutDir) if err != nil { log.Fatal(errgo.Notef(err, "can not create new store")) } for _, key := range readKeys { log.Info("Converting key '", strings.Join(key, "."), "'") project, err := data.ParseProjectName(strings.Join(key, data.ProjectNameSepperator)) if err != nil { log.Warning(errgo.Notef(err, "can not convert key to project name")) continue } log.Debug("Project: ", project) values, err := dbread.Get(key...) if err != nil { log.Warning(errgo.Notef(err, "can not get values for key '"+strings.Join(key, ".")+"'")) continue } log.Debug("Values: ", values) err = convertValues(store, project, values) if err != nil { log.Warning(errgo.Notef(err, "can no convert values for key '"+strings.Join(key, ".")+"'")) continue } log.Info("Converted key '", strings.Join(key, "."), "'") } }
func convertValues(store store.Store, project data.ProjectName, values [][]string) error { for _, value := range values { if len(value) < 2 { return errgo.New("value length must be at least 2") } timestamp, err := time.Parse(time.RFC3339Nano, value[0]) if err != nil { return errgo.Notef(err, "can not parse timestamp of value") } log.Info("Timestamp: ", timestamp) switch value[1] { case "note": log.Debug("Saving note") note := data.Note{ Value: value[2], TimeStamp: timestamp, } err := store.AddEntry(project, note) if err != nil { return errgo.Notef(err, "can not save note to store") } case "todo": log.Debug("Saving todo") done, err := strconv.ParseBool(value[3]) if err != nil { return errgo.Notef(err, "can not parse bool from value") } todo := data.Todo{ Value: value[2], TimeStamp: timestamp, Active: !done, } err = store.AddEntry(project, todo) if err != nil { return errgo.Notef(err, "can not save note to store") } default: return errgo.New("do not know what to do with this type of value: " + value[1]) } } return nil }
func (img *DockerImage) parse(input string) error { if len(input) == 0 { return errgo.Notef(ErrInvalidFormat, "Zero length") } if strings.Contains(input, " ") { return errgo.Notef(ErrInvalidFormat, "No whitespaces allowed") } splitByPath := strings.Split(input, "/") if len(splitByPath) > 3 { return errgo.Notef(ErrInvalidFormat, "Too many path elements") } if containsRegistry(splitByPath) { img.Registry = splitByPath[0] splitByPath = splitByPath[1:] } switch len(splitByPath) { case 1: img.Repository = splitByPath[0] case 2: img.Namespace = splitByPath[0] img.Repository = splitByPath[1] if !isNamespace(img.Namespace) { return errgo.Notef(ErrInvalidFormat, "Invalid namespace part: "+img.Namespace) } default: return errgo.Notef(ErrInvalidFormat, "Invalid format") } // Now split img.Repository into img.Repository and img.Version splitByVersionSeparator := strings.Split(img.Repository, ":") switch len(splitByVersionSeparator) { case 2: img.Repository = splitByVersionSeparator[0] img.Version = splitByVersionSeparator[1] if !isVersion(img.Version) { return errgo.Notef(ErrInvalidFormat, "Invalid version %#v", img.Version) } case 1: img.Repository = splitByVersionSeparator[0] // Don't apply latest, since we would produce an extra diff, when checking // for arbitrary keys in the app-config. 'latest' is not necessary anyway, // because the docker daemon does not pull all tags of an image, if there // is none given. img.Version = "" default: return errgo.Notef(ErrInvalidFormat, "Too many double colons") } if !isImage(img.Repository) { return errgo.Notef(ErrInvalidFormat, "Invalid image part %#v", img.Repository) } return nil }
func runCmdAddTodoInActive(cmd *cobra.Command, args []string) error { project, todo, err := helper.ArgsToTodo(args, flagAddTimeStamp, flagAddTimeStampRaw) if err != nil { return errgo.Notef(err, "can not convert args to todo") } todo.Active = false err = helper.RecordEntry(flagDataDir, project, todo, flagAddAutoCommit) if err != nil { errgo.Notef(err, "can not record todo to store") } return nil }
//Commit will add and commit the given entry into the repository that lays unter //the given datadir. func Commit(datadir string, project data.ProjectName, entry data.Entry) error { err := gitAdd(datadir, ".") if err != nil { return errgo.Notef(err, "can not add file to repository") } message := project.String() + " - " + entry.Type().String() + " - " + entry.GetTimeStamp().Format(data.TimeStampFormat) err = gitCommit(datadir, message) if err != nil { return errgo.Notef(err, "can not commit file to repository") } return nil }
func pageGallery(w http.ResponseWriter, r *http.Request, p httprouter.Params) *httphelper.HandlerError { l := httphelper.NewHandlerLogEntry(r) filepath := path.Join(FlagFolderGallery, p.ByName("path")) l.Debug("Sending ", filepath) stat, err := os.Stat(filepath) if err != nil { return httphelper.NewHandlerErrorDef(errgo.Notef(err, "can not stat file")) } if stat.Mode().IsDir() { l.Debug("Filetype: Directory") return pageFilesDirectory(w, r, p) } if stat.Mode().IsRegular() { l.Debug("Filetype: Regular") return pageFilesRegular(w, r, p) } if !stat.Mode().IsDir() && !stat.Mode().IsRegular() { return httphelper.NewHandlerErrorDef(errgo.New("filetype is not a directory and not a regular file. Something is strange.")) } return httphelper.NewHandlerErrorDef(errgo.New("unreachable code reached!")) }
func asciiDoctor(reader io.Reader, writer io.Writer) error { stderr := new(bytes.Buffer) command := exec.Command("asciidoctor", "-") command.Stdin = reader command.Stdout = writer command.Stderr = stderr err := command.Run() if err != nil { return errgo.Notef(errgo.Notef(err, "can not run asciidoctor"), stderr.String()) } return nil }
func (store FolderStore) ListProjects(showarchive bool) (data.Projects, error) { db := store.db() keys, err := db.Keys() if err != nil { return data.Projects{}, errgo.Notef(err, "can not get keys from database") } out := data.NewProjects() for _, key := range keys { if !showarchive { // Skipping archived projects if len(key) > 0 { log.Debug("Key: ", key[0]) if key[0] == ".archive" { continue } } } name := data.ProjectName(key) out.Add(data.Project{Name: name}) } return out, nil }
func (db *DBFiles) Destroy() error { err := os.RemoveAll(db.BaseDir) if err != nil { return errgo.Notef(err, "can not remove basedir") } return nil }
func (str Flat) File(basedir string, driver Driver, key []string) (io.ReadWriteCloser, error) { keypath := path.Join(basedir, strings.Join(key, ".")) + "." + driver.Extention() folderpath := filepath.Dir(keypath) err := os.MkdirAll(folderpath, 0755) if err != nil { return nil, errgo.Notef(err, "can not create keypath") } file, err := os.OpenFile(keypath, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0640) if err != nil { return nil, errgo.Notef(err, "can not open file") } return file, nil }
func (str Flat) Create(basedir string) error { err := os.MkdirAll(basedir, 0755) if err != nil { return errgo.Notef(err, "can not create basedir") } return nil }
func gitCommit(datadir, message string) error { command := exec.Command("git", "commit", "-m", message) command.Dir = datadir stderr := new(bytes.Buffer) command.Stderr = stderr err := command.Run() if err != nil { return errgo.Notef(errgo.Notef(err, "can not add file with git"), stderr.String()) } // Give git time to commit everything and remove the lockfile. time.Sleep(5 * time.Millisecond) return nil }
func runCmdShowProjects(cmd *cobra.Command, args []string) error { store, err := helper.DefaultStore(flagDataDir) if err != nil { return errgo.Notef(err, "can not get data store") } projects, err := helper.ProjectNamesFromArgs(store, args, flagShowArchive) if err != nil { return errgo.Notef(err, "can not get list of projects") } for _, project := range projects.List() { fmt.Println(project.Name) } return nil }
func (db *DBFiles) walkPopulateKeys(path string, info os.FileInfo, err error) error { if err != nil { return errgo.Notef(err, "error is not empty") } if info == nil { return errgo.New("directory info is empty") } //Skip git folder if info.IsDir() && info.Name() == ".git" { return filepath.SkipDir } if info.IsDir() { return nil } // Remove basedir from path relpath, err := filepath.Rel(db.BaseDir, path) if err != nil { return errgo.Notef(err, "can not get relative path") } // Get driver extention driverext := filepath.Ext(relpath) // remove driverextention nodriverpath := relpath[0 : len(relpath)-len(driverext)] // Split by path sepperator split := strings.Split(nodriverpath, string(os.PathSeparator)) // Append new key to the db.keys db.keysmux.Lock() db.keys = append(db.keys, split) db.keysmux.Unlock() log.Debug("Path: ", path) log.Debug("driverext: ", driverext) log.Debug("Nodriverpath: ", nodriverpath) log.Debug("Split: ", split) return nil }
func (store FolderStore) AddEntry(name data.ProjectName, entry data.Entry) error { db := store.db() err := db.Put(entry.Values(), name.Values()...) if err != nil { return errgo.Notef(err, "can not put entry into the database") } return nil }