func parseSIProgress(pb progress.Meter, stdout io.Reader) error { if pb == nil { pb = &progress.NullProgress{} } scanner := bufio.NewScanner(stdout) // s-i is funny, total changes during the runs total := 0.0 pb.Start("ubuntu-core", 100) for scanner.Scan() { if os.Getenv("SNAPPY_DEBUG") != "" { fmt.Println(scanner.Text()) } jsonStream := strings.NewReader(scanner.Text()) dec := json.NewDecoder(jsonStream) var genericData genericJSON if err := dec.Decode(&genericData); err != nil { // we ignore invalid json here and continue // the parsing if s-i-cli or ubuntu-core-upgrader // output something unexpected (like stray debug // output or whatnot) continue } switch { case genericData.Type == "spinner": pb.Spin(genericData.Message) case genericData.Type == "error": return fmt.Errorf("error from %s: %s", systemImageCli, genericData.Message) case genericData.Type == "progress": if total != genericData.Total { total = genericData.Total pb.SetTotal(total) } pb.Set(genericData.Now) } } // ugly: avoid Spin() artifacts pb.Notify("\nApply done") if err := scanner.Err(); err != nil { return err } return nil }
func downloadFile(url string, pbar progress.Meter) (fn string, err error) { name := "classic" w, err := ioutil.TempFile("", name) if err != nil { return "", err } defer func() { if err != nil { os.Remove(w.Name()) } }() defer w.Close() req, err := http.NewRequest("GET", url, nil) if err != nil { return "", err } client := &http.Client{} resp, err := client.Do(req) if err != nil { return "", err } defer resp.Body.Close() if resp.StatusCode != 200 { return "", fmt.Errorf("failed to download %s: %v", url, resp.StatusCode) } if pbar != nil { pbar.Start(name, float64(resp.ContentLength)) mw := io.MultiWriter(w, pbar) _, err = io.Copy(mw, resp.Body) pbar.Finished() } else { _, err = io.Copy(w, resp.Body) } return w.Name(), err }
// download writes an http.Request showing a progress.Meter func download(name string, w io.Writer, req *http.Request, pbar progress.Meter) error { client := &http.Client{} resp, err := client.Do(req) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode != 200 { return &ErrDownload{Code: resp.StatusCode, URL: req.URL} } if pbar != nil { pbar.Start(name, float64(resp.ContentLength)) mw := io.MultiWriter(w, pbar) _, err = io.Copy(mw, resp.Body) pbar.Finished() } else { _, err = io.Copy(w, resp.Body) } return err }