{"id":13994564,"url":"https://github.com/mtkennerly/ludusavi-manifest","last_synced_at":"2025-04-07T12:08:47.740Z","repository":{"id":38793152,"uuid":"273743959","full_name":"mtkennerly/ludusavi-manifest","owner":"mtkennerly","description":"Backup info for PC game saves","archived":false,"fork":false,"pushed_at":"2024-10-29T12:22:06.000Z","size":369563,"stargazers_count":74,"open_issues_count":0,"forks_count":13,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-10-29T14:50:24.512Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mtkennerly.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-06-20T16:26:48.000Z","updated_at":"2024-10-29T12:22:11.000Z","dependencies_parsed_at":"2023-10-14T17:53:07.283Z","dependency_job_id":"4b5113bf-92b0-4f19-af49-48ea04c7756c","html_url":"https://github.com/mtkennerly/ludusavi-manifest","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtkennerly%2Fludusavi-manifest","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtkennerly%2Fludusavi-manifest/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtkennerly%2Fludusavi-manifest/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtkennerly%2Fludusavi-manifest/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mtkennerly","download_url":"https://codeload.github.com/mtkennerly/ludusavi-manifest/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247648978,"owners_count":20972945,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-09T14:02:56.995Z","updated_at":"2025-04-07T12:08:47.714Z","avatar_url":"https://github.com/mtkennerly.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"# Ludusavi Manifest\nThe Ludusavi Manifest format is a YAML structure for defining\nthe location of game save data and other files that are of interest to back up.\nAlthough this project was started for use by [Ludusavi](https://github.com/mtkennerly/ludusavi),\nthe goal is for the manifest format to be generic enough for any game backup tool to implement,\nwhile leaving room for new fields and functionality over time.\n\nThis repository contains the [primary manifest](data/manifest.yaml),\nwhich is compiled from data on [PCGamingWiki](https://www.pcgamingwiki.com/wiki/Home),\nalong with accessing the Steam API for game installation directory names.\nIf you find any data that is missing or incorrect, please contribute to the wiki,\nand such changes will be incorporated into the primary manifest periodically.\nThere is also a list of [games without any info on what to back up](data/missing.md),\nas well as [articles with wikitext that failed to parse](data/wiki-malformed.md).\n\nGame developers may include a secondary manifest (named `.ludusavi.yaml`) with their games,\nso that backup tools can automatically detect and use it\nto discover what files need to be backed up for save data and configuration.\n\n## Format\nFor the schema, refer to [schema.yaml](data/schema.yaml).\nNote that the primary manifest is validated with [schema.strict.yaml](data/schema.strict.yaml),\nwhich additionally specifies enums for some fields.\nHowever, tools should implement [schema.yaml](data/schema.yaml),\nso that new values in the manifest do not break older tools.\n\nHere is an example:\n\n```yaml\nAn Example Game:\n  files:\n    \u003cbase\u003e/saves:\n      tags:\n        - save\n    \u003cbase\u003e/settings.json:\n      when:\n        - os: windows\n        - os: linux\n      tags:\n        - config\n    \u003cbase\u003e/other:\n      when:\n        - os: mac\n          store: steam\n  installDir:\n    AnExampleGame: {}\n  registry:\n    HKEY_CURRENT_USER/Software/An Example Game:\n      tags:\n        - save\n        - config\n  steam:\n    id: 123\n```\n\nThis means:\n\n* `\u003cbase\u003e/saves` will be backed up on any system.\n* `\u003cbase\u003e/settings.json` will be backed up if you're using Windows or Linux.\n* `\u003cbase\u003e/other` will be backed up if you're using Mac and Steam.\n* On Windows, the registry key `HKEY_CURRENT_USER/Software/An Example Game` will be backed up.\n\nPaths in the `files` section can include these placeholders:\n\n| placeholder            | meaning                                                                                |\n|------------------------|----------------------------------------------------------------------------------------|\n| `\u003croot\u003e`               | a directory where games are installed (configured in backup tool)                      |\n| `\u003cgame\u003e`               | an `installDir` (if defined) or the game's canonical name in the manifest              |\n| `\u003cbase\u003e`               | shorthand for `\u003croot\u003e/\u003cgame\u003e` (unless overridden by store-specific rules)              |\n| `\u003chome\u003e`               | current user's home directory in the OS (`~`)                                          |\n| `\u003cstoreGameId\u003e`        | a store-specific `id` from the manifest, corresponding to the root's store type        |\n| `\u003cstoreUserId\u003e`        | current user's ID in the game store                                                    |\n| `\u003cosUserName\u003e`         | current user's name in the OS                                                          |\n| `\u003cwinAppData\u003e`         | `%APPDATA%` on Windows                                                                 |\n| `\u003cwinLocalAppData\u003e`    | `%LOCALAPPDATA%` on Windows                                                            |\n| `\u003cwinLocalAppDataLow\u003e` | `\u003chome\u003e/AppData/LocalLow` on Windows                                                   |\n| `\u003cwinDocuments\u003e`       | `\u003chome\u003e/Documents` (f.k.a. `\u003chome\u003e/My Documents`) or a localized equivalent on Windows |\n| `\u003cwinPublic\u003e`          | `%PUBLIC%` on Windows                                                                  |\n| `\u003cwinProgramData\u003e`     | `%PROGRAMDATA%` on Windows                                                             |\n| `\u003cwinDir\u003e`             | `%WINDIR%` on Windows                                                                  |\n| `\u003cxdgData\u003e`            | `$XDG_DATA_HOME` on Linux                                                              |\n| `\u003cxdgConfig\u003e`          | `$XDG_CONFIG_HOME` on Linux                                                            |\n\n## Implementation\nTools must implement the following in addition to respecting the schema:\n\n* For paths, first substitute the placeholders, then evaluate as a glob.\n  Because of treating paths as globs, a path may match multiple files or directories.\n* When a path identifies a folder,\n  the backup includes all of its files and subdirectories recursively.\n* When backing up registry keys, the backup includes all sub-keys recursively.\n* If a tool supports secondary manifests, they must be automatically detected\n  when they are named `.ludusavi.yaml` and located directly in `\u003cbase\u003e`.\n  For example, a Steam game's secondary manifest would be `\u003croot\u003e/steamapps/common/\u003cgame\u003e/.ludusavi.yaml`.\n\nTools may also:\n\n* Use store-specific logic to determine the `\u003cbase\u003e`.\n  For example, with Steam, if the root is `~/.steam/steam`,\n  then `\u003cbase\u003e` would be `\u003croot\u003e/steamapps/common/\u003cgame\u003e`.\n  Or a tool could use `\u003croot\u003e/**/\u003cgame\u003e` as a generic option,\n  although it could lead to wasted search time.\n* Check possible save data locations even if the entry has inapplicable constraints.\n  For example, if a file entry is marked as `os: windows`,\n  then ideally a tool should only need to check that entry when running on Windows;\n  however, it is a reality of the data set that it may simply be the only confirmed occurrence of the file,\n  and it may in fact occur on other operating systems as well.\n* Reject/ignore recursive aliases or set a recursion limit.\n  The primary manifest will never contain a recursive alias.\n* Reject/ignore relative paths in the `files` mapping\n  (i.e., paths starting with `./` or `../`).\n  The primary manifest will never contain relative paths.\n\nFor authors of secondary manifests bundled with games:\n\n* If present, the secondary manifest must be located directly in the game's install folder (not a subfolder),\n  and the file name must be `.ludusavi.yaml`.\n* You must use `\u003cbase\u003e` instead of relative paths.\n  For example, use `\u003cbase\u003e/save.dat` instead of `./save.dat`,\n  and use `\u003cbase\u003e/../parent` instead of `../parent`.\n\nThe latest version of the primary manifest can be downloaded from\nhttps://raw.githubusercontent.com/mtkennerly/ludusavi-manifest/master/data/manifest.yaml .\nTo check for updates:\n\n* Store the value of the `ETag` header for the last downloaded version.\n* Send a GET request to the URL with the `If-None-Match` header set to the last known `ETag` value.\n* If the response code is 304, then no update is needed.\n* If the response code is 200, then store the new `ETag` value.\n\n## Development\nPlease refer to [CONTRIBUTING.md](CONTRIBUTING.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmtkennerly%2Fludusavi-manifest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmtkennerly%2Fludusavi-manifest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmtkennerly%2Fludusavi-manifest/lists"}