diff options
Diffstat (limited to 'steam/package.go')
| -rw-r--r-- | steam/package.go | 148 |
1 files changed, 105 insertions, 43 deletions
diff --git a/steam/package.go b/steam/package.go index bd5bfb5..df6f1e8 100644 --- a/steam/package.go +++ b/steam/package.go @@ -8,39 +8,79 @@ import ( "strings" ) -// Package writes the package, returning bytes written and an error if any -func (g *Game) Package(wr io.WriteCloser) error { - acf, err := FindACF(g.LibraryPath, g.Name) +const ( + defaultDirectoryMode = 0775 + defaultFileMode = 0644 +) + +// Package writes the package to wr, returning errors if any +func (l *Library) Package(game string, wr io.WriteCloser) error { + g, ok := l.games[game] + if !ok { + return E_GameDoesNotExist + } + + j := newJob("package", g) + defer j.done() + + l.status.addJob(j) + + acf, err := FindACF(l.folder, g.Name) if err != nil { + j.addError(err) return err } twriter := tar.NewWriter(wr) paths := []string{ - filepath.Join(g.LibraryPath, "common", g.Name), + filepath.Join(l.folder, "common", g.Name), acf, } for _, pth := range paths { - err := filepath.Walk(pth, tarWalkfn(twriter, g.LibraryPath)) + 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 + } - return wr.Close() + err = wr.Close() + if err != nil { + j.addError(err) + } + return err } // Extract will read a tarball from the io.Reader and install the game into -// the current library path -func (l *Library) Extract(r io.Reader) error { +// the current library path. This offers no visibility into the progress, +// as it does not update the job status on the progress, though it will +// populate errors. +// +// Most callers will want to use ExtractHTTP or ExtractFile instead +func (l *Library) Extract(r io.Reader) (*Game, error) { + g := &Game{LibraryPath: l.folder} + j := newJob("extract", g) + defer j.done() + + l.status.addJob(j) + + return l.extractPrimitive(j, g, r) +} + +func (l *Library) extractPrimitive(j *Job, g *Game, r io.Reader) (*Game, error) { treader := tar.NewReader(r) for { @@ -50,78 +90,100 @@ func (l *Library) Extract(r io.Reader) error { break } if err != nil { - return err + j.addError(err) + return nil, err } - // Fix windows slashes... - fileName := strings.Replace(hdr.Name, "\\", "/", -1) + fileName := filepath.ToSlash(hdr.Name) + + if g.Name == "" { + s := strings.Split(fileName, "/") + if len(s) >= 2 { + g.Name = s[1] + } + } - fileName = filepath.Join(l.Folder, fileName) + fileName = filepath.Join(l.folder, fileName) info := hdr.FileInfo() if info.IsDir() { // I don't like hard-coded permissions but it // it helps with overall platform compatibility - if err = os.MkdirAll(fileName, 0775); err != nil { - return err + err = os.MkdirAll(fileName, defaultDirectoryMode) + if err != nil { + j.addError(err) + return nil, err } + continue } - if err = os.MkdirAll(filepath.Dir(fileName), 0775); err != nil { - return err + err = os.MkdirAll(filepath.Dir(fileName), defaultDirectoryMode) + if err != nil { + j.addError(err) + return nil, err } // Create a file handle to work with - f, err := os.OpenFile(fileName, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0664) + f, err := os.OpenFile(fileName, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, + defaultFileMode) if err != nil { - return err + j.addError(err) + return nil, err } if _, err := io.Copy(f, treader); err != nil { + j.addError(err) f.Close() - return err + return nil, err } f.Close() } - return nil + err := g.SetSizeInfo() + if err != nil { + j.addError(err) + return nil, err + } + + l.m.Lock() + l.games[g.Name] = g + l.m.Unlock() + + return g, nil } // Delete removes all of the game files and the ACF -func (g *Game) Delete() error { - acf, err := FindACF(g.LibraryPath, g.Name) +func (l *Library) Delete(game string) error { + g, ok := l.games[game] + if !ok { + return E_GameDoesNotExist + } + + j := newJob("delete", g) + defer j.done() + + l.status.addJob(j) + + acf, err := FindACF(l.folder, game) if err != nil { + j.addError(err) return err } if err := os.Remove(acf); err != nil { + j.addError(err) return err } - err = os.RemoveAll(filepath.Join(g.LibraryPath, "common", g.Name)) + err = os.RemoveAll(filepath.Join(l.folder, "common", g.Name)) if err != nil { + j.addError(err) return err } - return nil -} - -// GetSize returns the size of a game in a pretty format -func (g Game) GetSize() string { - return formatBytes(g.Size) -} - -func (g *Game) setSizeInfo() error { - pth := filepath.Join(g.LibraryPath, "common", g.Name) - return filepath.Walk(pth, func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } + l.m.Lock() + delete(l.games, game) + l.m.Unlock() - if info.Mode().IsRegular() { - g.Size += info.Size() - } - - return nil - }) + return nil } |
