package steam import ( "archive/tar" "errors" "fmt" "io" "path/filepath" "time" ) const ( defaultDirectoryMode = 0775 defaultFileMode = 0644 ) func (l *Library) Package(game string, wr io.Writer) error { if _, ok := l.Games()[game]; !ok { return E_GameDoesNotExist } g := l.Games()[game] j := newJob("package", g) defer j.done() l.status.addJob(j) j.setSize(g.GetSizeBytes()) // Invert the writer so we can break up the copy and get progress // information in here rdr, pwrtr := io.Pipe() go func() { err := l.packagePrimitive(j, g, pwrtr) if err != nil { j.addError(err) } }() var total int64 for { n, err := io.CopyN(wr, rdr, updateEveryNBytes) if err == io.EOF { break } if err != nil { j.addError(err) return err } total += n j.setTransferred(total) elapsedSeconds := float64(time.Since(*j.StartTime()).Seconds()) rate := float64(total) / elapsedSeconds fmt.Println("rate in bytes/second: ", formatBytes(int64(rate))) estSize := j.GetSize() if estSize == nil { j.addError(errors.New("Expected an estimated size, got nil")) continue } remainingBytes := float64(*estSize - total) fmt.Println("remaining bytes: ", formatBytes(int64(remainingBytes))) seconds := (remainingBytes / rate) duration := time.Duration(seconds * 1000 * 1000 * 1000) fmt.Println("Raw duration: ", duration) j.setETA(duration) } return nil } // Package writes the package to wr, returning errors if any func (l *Library) packagePrimitive(j *Job, g *Game, wr io.WriteCloser) error { acf, err := FindACF(l.folder, g.Name) if err != nil { j.addError(err) return err } twriter := tar.NewWriter(wr) paths := []string{ filepath.Join(l.folder, "common", g.Name), acf, } for _, pth := range paths { err := filepath.Walk(pth, tarWalkfn(twriter, l.folder)) if err != nil { j.addError(err) return err } } err = twriter.Flush() if err != nil { j.addError(err) return err } err = twriter.Close() if err != nil { j.addError(err) return err } err = wr.Close() if err != nil { j.addError(err) return err } return err }