Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Change backup system to include the clean image's hash
The old backup system was to simply copy the "clean" (no overlays) file to "{id} (original).jpg". When reapplying overlays, this clean file is used as base. This works perfectly, but only when SteamGrid is the only program touching these files. If the user customizes an image directly on Steam (right click -> set custom image), Steam changes the "{id}.jpg" file. But SteamGrid doesn't know the file changed, and promptly deletes and reloads from the "(original)" backup, discarding the user's change. This bug has wasted a lot of users' time and effort. Sorry about that :( The solution is to name the backup file (previously "{id} (original).jpg") to include the overlaid file hash (now "{id} backup {sha256}.jpg"). Now when processing a file, first SteamGrid reads "{id}.jpg" and takes it hash. If there is a backup file with this hash, it means the file was created by SteamGrid, and the backup file is the just the clean version. If the user manually customizes an image, the hash won't match any backups, and SteamGrid won't overwrite it. The downside is that it may create files that will never be cleaned. As the images are small, this shouldn't be an issue. Maybe a newer version will automatically cleanup unused backups. This commit also looks for old-style, legacy backups ("{id} (original).jpg"), and converts them to new-style backups.
- Loading branch information
Showing
5 changed files
with
119 additions
and
105 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,59 @@ | ||
package main | ||
|
||
import ( | ||
"crypto/sha256" | ||
"encoding/hex" | ||
"io/ioutil" | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
) | ||
|
||
// BackupGame if a game has a custom image, backs it up by appending "(original)" to the | ||
// file name. | ||
func BackupGame(game *Game) error { | ||
if game.ImagePath != "" && game.ImageBytes != nil { | ||
ext := filepath.Ext(game.ImagePath) | ||
base := filepath.Base(game.ImagePath) | ||
backupPath := filepath.Join(filepath.Dir(game.ImagePath), strings.TrimSuffix(base, ext)+" (original)"+ext) | ||
return ioutil.WriteFile(backupPath, game.ImageBytes, 0666) | ||
} | ||
func BackupGame(gridDir string, game *Game) error { | ||
if game.CleanImageBytes != nil { | ||
return ioutil.WriteFile(getBackupPath(gridDir, game), game.CleanImageBytes, 0666) | ||
} | ||
return nil | ||
} | ||
|
||
func getBackupPath(gridDir string, game *Game) string { | ||
hash := sha256.Sum256(game.OverlayImageBytes) | ||
// [:] is required to convert a fixed length byte array to a byte slice. | ||
hexHash := hex.EncodeToString(hash[:]) | ||
return filepath.Join(gridDir, game.ID+" backup "+hexHash+game.ImageExt) | ||
} | ||
|
||
func loadImage(game *Game, sourceName string, imagePath string) error { | ||
imageBytes, err := ioutil.ReadFile(imagePath) | ||
if err == nil { | ||
game.ImageExt = filepath.Ext(imagePath) | ||
game.CleanImageBytes = imageBytes | ||
game.ImageSource = sourceName | ||
} | ||
return err | ||
} | ||
|
||
func LoadBackup(gridDir string, game *Game) { | ||
// If there are any old-style backups (without hash), load them over the existing (with overlay) images. | ||
oldBackups, err := filepath.Glob(filepath.Join(gridDir, game.ID+" (original)*")) | ||
if err == nil && len(oldBackups) > 0 { | ||
err = loadImage(game, "legacy backup (now converted)", oldBackups[0]) | ||
if err == nil { | ||
os.Remove(oldBackups[0]) | ||
return | ||
} | ||
} | ||
|
||
files, err := filepath.Glob(filepath.Join(gridDir, game.ID+".*")) | ||
if err == nil && len(files) > 0 { | ||
err = loadImage(game, "manual customization", files[0]) | ||
if err == nil { | ||
game.OverlayImageBytes = game.CleanImageBytes | ||
|
||
// See if there exists a backup image with no overlays or modifications. | ||
loadImage(game, "backup", getBackupPath(gridDir, game)) | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.