Commit e03b4ae0 authored by Quentin Smith's avatar Quentin Smith

cmd/benchsave: add header flag for specifying common keys

This allows easily adding additional information when uploading
existing files. Example usage:

benchsave -header <(echo goarch: arm; echo goos: linux) *.log

Change-Id: I46afafd39d8314d9c06c209f868b71cd5e58c63a
Reviewed-on: https://go-review.googlesource.com/35350Reviewed-by: default avatarRuss Cox <rsc@golang.org>
parent 6f1afaec
......@@ -6,21 +6,23 @@
//
// Usage:
//
// benchsave [-server https://server.org] a.txt [b.txt ...]
// benchsave [-v] [-header file] [-server url] file...
//
// Each input file should contain the output from one or more runs of
// ``go test -bench'', or another tool which uses the same format.
//
// benchsave will upload the input files to the specified server and
// Benchsave will upload the input files to the specified server and
// print a URL where they can be viewed.
package main
import (
"bytes"
"context"
"encoding/json"
"flag"
"fmt"
"io"
"io/ioutil"
"log"
"mime/multipart"
"os"
......@@ -31,8 +33,9 @@ import (
)
var (
server = flag.String("server", "https://perfdata.golang.org", "perfdata server to upload benchmarks to")
verbose = flag.Bool("v", false, "verbose")
server = flag.String("server", "https://perfdata.golang.org", "upload benchmarks to server at `url`")
verbose = flag.Bool("v", false, "print verbose log messages")
header = flag.String("header", "", "insert `file` at the beginning of each uploaded file")
)
type uploadStatus struct {
......@@ -45,25 +48,26 @@ type uploadStatus struct {
}
// writeOneFile reads name and writes it to mpw.
func writeOneFile(mpw *multipart.Writer, name string) {
func writeOneFile(mpw *multipart.Writer, name string, header []byte) error {
w, err := mpw.CreateFormFile("file", filepath.Base(name))
if err != nil {
fmt.Fprintf(os.Stderr, "Writing upload failed: %v\n", err)
os.Exit(1)
return err
}
if len(header) > 0 {
if _, err := w.Write(header); err != nil {
return err
}
}
f, err := os.Open(name)
if err != nil {
fmt.Fprint(os.Stderr, err)
mpw.WriteField("abort", "1")
// TODO(quentin): Wait until the abort field is written before exiting.
os.Exit(1)
return err
}
defer f.Close()
if _, err := io.Copy(w, f); err != nil {
fmt.Fprintf(os.Stderr, "Writing upload failed: %v", err)
os.Exit(1)
return err
}
return nil
}
func usage() {
......@@ -85,6 +89,16 @@ func main() {
log.Fatal("no files to upload")
}
var headerData []byte
if *header != "" {
var err error
headerData, err = ioutil.ReadFile(*header)
if err != nil {
log.Fatal(err)
}
headerData = append(bytes.TrimRight(headerData, "\n"), '\n', '\n')
}
// TODO(quentin): Some servers might not need authentication.
// We should somehow detect this and not force the user to get a token.
// Or they might need non-Google authentication.
......@@ -98,8 +112,16 @@ func main() {
defer mpw.Close()
for _, name := range files {
writeOneFile(mpw, name)
if err := writeOneFile(mpw, name, headerData); err != nil {
log.Print(err)
mpw.WriteField("abort", "1")
// Writing the 'abort' field will cause the server to send back an error response,
// which will cause the main goroutine to below.
return
}
}
mpw.WriteField("commit", "1")
}()
start := time.Now()
......
......@@ -93,6 +93,9 @@ func (a *App) processUpload(ctx context.Context, user string, mr *multipart.Read
}
name := p.FormName()
if name == "commit" {
continue
}
if name != "file" {
return nil, fmt.Errorf("unexpected field %q", name)
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment