diff options
Diffstat (limited to 'steam')
| -rw-r--r-- | steam/archive.go | 17 | ||||
| -rw-r--r-- | steam/filelisting.go | 26 | ||||
| -rw-r--r-- | steam/package.go | 31 | ||||
| -rw-r--r-- | steam/steam.go | 52 | ||||
| -rw-r--r-- | steam/update.go | 70 |
5 files changed, 46 insertions, 150 deletions
diff --git a/steam/archive.go b/steam/archive.go index d997051..296defa 100644 --- a/steam/archive.go +++ b/steam/archive.go @@ -2,13 +2,14 @@ package steam import ( "archive/tar" + "fmt" "io" "os" "path/filepath" "strings" ) -func TarWalkfn(writer *tar.Writer) filepath.WalkFunc { +func tarWalkfn(writer *tar.Writer, prefix string) filepath.WalkFunc { return func(path string, info os.FileInfo, err error) error { if err != nil { return err @@ -24,13 +25,16 @@ func TarWalkfn(writer *tar.Writer) filepath.WalkFunc { } defer f.Close() - // Convert Windows paths to Unix paths - path = strings.Replace(path, "\\", "/", -1) + // Let's strip out all of the leading parts of the path + // to create a tarball realative to the root of the steam library + tarPth := strings.TrimPrefix(path, prefix) + tarPth = strings.ReplaceAll(tarPth, "\\", "/") + tarPth = strings.TrimPrefix(tarPth, "/") // TODO; See if tar.FileInfoheader() could be used instead // without the pathing issues I encountered h := &tar.Header{ - Name: path, + Name: tarPth, Size: info.Size(), // I don't like it... but it helps with platform compatibility Mode: 0664, @@ -44,10 +48,7 @@ func TarWalkfn(writer *tar.Writer) filepath.WalkFunc { _, err = io.Copy(writer, f) if err != nil { - // TODO: Figure out how to add more useful information to - // These errors - // fmt.Fprintln(os.Stderr, f.Name()) - return err + return fmt.Errorf("While copying %s: %w", path, err) } return nil diff --git a/steam/filelisting.go b/steam/filelisting.go deleted file mode 100644 index f94319e..0000000 --- a/steam/filelisting.go +++ /dev/null @@ -1,26 +0,0 @@ -package steam - -import ( - "path/filepath" - "os" -) - -func fileListing(pth string) (map[string]struct{}, error) { - out := map[string]struct{}{} - err := filepath.Walk(pth, func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - - if info.Mode().IsRegular() { - out[path] = struct{}{} - } - - return nil - }) - if err != nil { - return nil, err - } - - return out, nil -} diff --git a/steam/package.go b/steam/package.go index 7287e10..38b5819 100644 --- a/steam/package.go +++ b/steam/package.go @@ -10,9 +10,6 @@ import ( // Package writes the package, returning bytes written and an error if any func (g *Game) Package(wr io.WriteCloser) error { - if err := os.Chdir(g.LibraryPath); err != nil { - return err - } acf, err := FindACF(g.LibraryPath, g.Name) if err != nil { return err @@ -20,8 +17,13 @@ func (g *Game) Package(wr io.WriteCloser) error { twriter := tar.NewWriter(wr) - for _, pth := range []string{"common/" + g.Name, acf} { - if err := filepath.Walk(pth, TarWalkfn(twriter)); err != nil { + paths := []string{ + filepath.Join(g.LibraryPath, "common", g.Name), + acf, + } + for _, pth := range paths { + err := filepath.Walk(pth, tarWalkfn(twriter, g.LibraryPath)) + if err != nil { return err } } @@ -36,11 +38,9 @@ func (g *Game) Package(wr io.WriteCloser) error { return wr.Close() } +// 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 { - if err := os.Chdir(l.Folder); err != nil { - return err - } - treader := tar.NewReader(r) for { @@ -56,6 +56,8 @@ func (l *Library) Extract(r io.Reader) error { // Fix windows slashes... fileName := strings.Replace(hdr.Name, "\\", "/", -1) + fileName = filepath.Join(l.Folder, fileName) + info := hdr.FileInfo() if info.IsDir() { // I don't like hard-coded permissions but it @@ -85,11 +87,8 @@ func (l *Library) Extract(r io.Reader) error { return nil } +// Delete removes all of the game files and the ACF func (g *Game) Delete() error { - if err := os.Chdir(g.LibraryPath); err != nil { - return err - } - acf, err := FindACF(g.LibraryPath, g.Name) if err != nil { return err @@ -97,14 +96,16 @@ func (g *Game) Delete() error { if err := os.Remove(acf); err != nil { return err } - if err := os.RemoveAll("common/" + g.Name); err != nil { + + err = os.RemoveAll(filepath.Join(g.LibraryPath, "common", g.Name)) + if err != nil { return err } return nil } -// Get the Size of a game in a pretty format +// GetSize returns the size of a game in a pretty format func (g Game) GetSize() string { return formatBytes(g.Size) } diff --git a/steam/steam.go b/steam/steam.go index aca20df..ff0ce5a 100644 --- a/steam/steam.go +++ b/steam/steam.go @@ -1,10 +1,10 @@ -// This is designed to be a rather simplistic library to help pull information -// from a local steam library +// Package steam is designed to be a rather simplistic library to help pull +// information from a local steam library and run basic operations like +// archiving, restore and deleting games package steam import ( "bufio" - "errors" "fmt" "io/ioutil" "os" @@ -13,11 +13,15 @@ import ( "strings" ) +// Library is used to represent the steam library, the Games map is populated +// by NewLibrary when called or when ProcessLibrary is called directly type Library struct { Folder string Games map[string]Game } +// Game represents an actual game in the steam Library, allowing you to perform +// a delete, package, and such. type Game struct { Name string LibraryPath string @@ -26,24 +30,14 @@ type Game struct { var slugregexp = regexp.MustCompile(`[^-0-9A-Za-z_:.]`) +// Slug returns a safer version of the name with spaces and other chars +// transformed into dashes for use in HTML element ids and such. func (g Game) Slug() string { - // return strings.ReplaceAll(g.Name, " ", "-") return slugregexp.ReplaceAllString(g.Name, "-") } -func ProcessMultipleLibraries(r []string) ([]*Library, error) { - var libs []*Library - for _, i := range r { - lib := &Library{} - err := lib.ProcessLibrary(i) - if err != nil { - return nil, err - } - libs = append(libs, lib) - } - return libs, nil -} - +// NewLibrary returns a pointer to a processed library and an error +// if any func NewLibrary(path string) (*Library, error) { l := &Library{} err := l.ProcessLibrary(path) @@ -53,6 +47,8 @@ func NewLibrary(path string) (*Library, error) { return l, err } +// NewLibraryMust is the same as NewLibrary but calls panic if there +// is any error func NewLibraryMust(path string) *Library { l, err := NewLibrary(path) if err != nil { @@ -61,10 +57,11 @@ func NewLibraryMust(path string) *Library { return l } -// Populate the "Folder" and "Games" fields based on the provided directory +// ProcessLibrary Populates the "Folder" and "Games" fields based on the +// provided directory. func (s *Library) ProcessLibrary(r string) error { if !hasCommon(r) { - return errors.New(fmt.Sprintf("No common directory in: %s", r)) + return fmt.Errorf("No common directory in: %s", r) } s.Games = make(map[string]Game) @@ -89,12 +86,9 @@ func (s *Library) ProcessLibrary(r string) error { return nil } -// Find the ACF files related to this video game +// FindACF will return the filename of the ACF file for a given `game` func FindACF(libraryPath, game string) (string, error) { - if err := os.Chdir(libraryPath); err != nil { - return "", err - } - files, err := filepath.Glob("*.acf") + files, err := filepath.Glob(filepath.Join(libraryPath, "*.acf")) if err != nil { return "", err } @@ -110,26 +104,22 @@ func FindACF(libraryPath, game string) (string, error) { // Open up the file f, err := os.Open(fn) - defer f.Close() if err != nil { return "", err } + defer f.Close() + scanner := bufio.NewScanner(f) for scanner.Scan() { - // Finally check and see if the file has the video game name if strings.Contains(scanner.Text(), game) { return fn, nil - // fmt.Printf("%s/%s:%d: %s\n", root, path, i, scanner.Text()) } } } - str := "Couldn't find ACF file related to Game: %s" - return "", errors.New(fmt.Sprintf(str, game)) + return "", fmt.Errorf("Couldn't find ACF file related to Game: %s", game) } -// This is automatically called to print out the contents of the struct -// when things like fmt.Println are used func (s *Library) String() (str string) { str = fmt.Sprintf("Library: %s\n", s.Folder) str = str + "----\n" diff --git a/steam/update.go b/steam/update.go deleted file mode 100644 index b3e621e..0000000 --- a/steam/update.go +++ /dev/null @@ -1,70 +0,0 @@ -package steam - -import ( - "archive/tar" - "io" - "os" - "strings" - "path/filepath" -) - -func (l *Library) ExtractUpdate(r io.Reader) error { - if err := os.Chdir(l.Folder); err != nil { - return err - } - - // withinArchive := map[string]struct{}{} - // onDisk, err := fileListing( - - treader := tar.NewReader(r) - - for { - hdr, err := treader.Next() - if err == io.EOF { - // We've reached the end! Whoee - break - } - if err != nil { - return err - } - - // Fix windows slashes... - fileName := strings.Replace(hdr.Name, "\\", "/", -1) - - 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 - } - continue - } - - if err = os.MkdirAll(filepath.Dir(fileName), 0775); err != nil { - return err - } - - fi, err := os.Stat(fileName) - if !os.IsNotExist(err) { - // If the file in the archive is not newer, skip - if !info.ModTime().After(fi.ModTime()) { - continue - } - } - - // Create a file handle to work with - f, err := os.OpenFile(fileName, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0664) - if err != nil { - return err - } - if _, err := io.Copy(f, treader); err != nil { - return err - } - f.Close() - - } - - return nil -} - |
