func main() { sw := ui.NewSpinningWriter("", ioutil.Discard) defer sw.Close() if _, err := io.Copy(sw, os.Stdin); err != nil { fmt.Println(err) } }
// Write ACI to `, return its hash. If packlist file is nil, writes // flat ACI (and manifest omits the dependencies). func (img *Image) writeACI(w io.Writer, packlist *os.File) (*types.Hash, error) { var sink io.WriteCloser var faucet io.Reader sw := ui.NewSpinningWriter("Writing ACI", w) defer sw.Close() sink = sw tarArgs := []string{"-C", img.Path(), "-c", "--null", "-f", "-"} if packlist != nil { img.ui.Debug("Writing an incremental ACI") tarArgs = append(tarArgs, "-n", "-T", "-") } else { img.ui.Debug("Writing a flat ACI") // no packlist -> flat ACI manifest := img.Manifest manifest.Dependencies = nil manifest.PathWhitelist = nil manifestF, err := ioutil.TempFile(img.Path(), "manifest.flat.") if err != nil { return nil, errors.Trace(err) } defer os.Remove(manifestF.Name()) if manifestB, err := json.Marshal(manifest); err != nil { manifestF.Close() return nil, errors.Trace(err) } else { _, err := manifestF.Write(manifestB) manifestF.Close() if err != nil { return nil, errors.Trace(err) } } manifestN := filepath.Base(manifestF.Name()) tarArgs = append(tarArgs, "-s", "/^"+manifestN+"$/manifest/", manifestN, "rootfs") } tar := run.Command("tar", tarArgs...).ReadFrom(packlist) if tarPipe, err := tar.StdoutPipe(); err != nil { return nil, errors.Trace(err) } else { faucet = tarPipe } hash := sha512.New() faucet = io.TeeReader(faucet, hash) var compressor *run.Cmd = nil if compression := Config().GetString("images.aci.compression", "no"); compression != "none" { switch compression { case "xz": compressor = run.Command("xz", "-z", "-c") case "bzip2": compressor = run.Command("bzip2", "-z", "-c") case "gz": case "gzip": compressor = run.Command("gzip", "-c") default: return nil, errors.Errorf("Invalid setting images.aci.compression=%#v (allowed values: xz, bzip2, gzip, none)", compression) } compressor.Cmd.Stdout = sink if cin, err := compressor.StdinPipe(); err != nil { return nil, errors.Trace(err) } else { sink = cin } } if err := tar.Start(); err != nil { return nil, errors.Trace(err) } if compressor != nil { if err := compressor.Start(); err != nil { tar.Kill() return nil, errors.Trace(err) } } if _, err := io.Copy(sink, faucet); err != nil { sink.Close() tar.Kill() compressor.Kill() return nil, errors.Trace(err) } if err := tar.Wait(); err != nil { sink.Close() compressor.Kill() return nil, errors.Trace(err) } sink.Close() if err := compressor.Wait(); err != nil { return nil, errors.Trace(err) } if hash, err := types.NewHash(fmt.Sprintf("sha512-%x", hash.Sum(nil))); err != nil { // CAN'T HAPPEN, srsly return nil, errors.Trace(err) } else { img.ui.Debug("Saved", hash) return hash, nil } }