Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ Metrics/ModuleLength:
Exclude:
- lib/factorix.rb # Cache configuration with hierarchical backend settings

Metrics/ParameterLists:
Max: 6

Naming/PredicateMethod:
Exclude:
- lib/factorix/cache/file_system.rb # fetch/store/delete return boolean but are standard cache API names
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
## [Unreleased]

### Added

- Add `--strict-version` flag to `mod sync` to install exact MOD versions from the save file (#75)

### Changed

- Raise minimum Ruby version requirement to 3.3 (#81)
Expand Down
2 changes: 1 addition & 1 deletion completion/_factorix.bash
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ _factorix() {
;;
sync)
if [[ "$cur" == -* ]]; then
COMPREPLY=($(compgen -W "$global_opts $confirmable_opts -j --jobs --keep-unlisted" -- "$cur"))
COMPREPLY=($(compgen -W "$global_opts $confirmable_opts -j --jobs --keep-unlisted --strict-version" -- "$cur"))
else
COMPREPLY=($(compgen -f -X '!*.zip' -- "$cur"))
fi
Expand Down
1 change: 1 addition & 0 deletions completion/_factorix.fish
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ complete -c factorix -n "__factorix_using_subcommand mod search" -l json -d 'Out
complete -c factorix -n "__factorix_using_subcommand mod sync" -s y -l yes -d 'Skip confirmation prompts'
complete -c factorix -n "__factorix_using_subcommand mod sync" -s j -l jobs -d 'Number of parallel downloads' -r
complete -c factorix -n "__factorix_using_subcommand mod sync" -l keep-unlisted -d 'Keep MODs not listed in save file enabled'
complete -c factorix -n "__factorix_using_subcommand mod sync" -l strict-version -d 'Install exact MOD versions from save file'
complete -c factorix -n "__factorix_using_subcommand mod sync" -ra '(__fish_complete_suffix .zip)'

# mod changelog subcommands
Expand Down
1 change: 1 addition & 0 deletions completion/_factorix.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ _factorix_mod() {
$confirmable_opts \
'(-j --jobs)'{-j,--jobs}'[Number of parallel downloads]:jobs:' \
'--keep-unlisted[Keep MODs not listed in save file enabled]' \
'--strict-version[Install exact MOD versions from save file]' \
'1:save file:_files -g "*.zip"'
;;
changelog)
Expand Down
4 changes: 3 additions & 1 deletion doc/components/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -422,13 +422,15 @@ Synchronize MOD states from a save file.
**Options**:
- `-j`, `--jobs` - Number of parallel downloads (default: 4)
- `--keep-unlisted` - Keep MODs not listed in the save file enabled (default: disable them)
- `--strict-version` - Install exact MOD versions recorded in the save file (default: install latest)

**Features**:
- Extracts MOD information from save file
- Downloads missing MODs concurrently
- Enables/disables MODs to match save file state
- Disables enabled MODs (including expansion MODs) not listed in the save file (unless `--keep-unlisted` is specified)
- Preserves existing MOD files when possible
- Without `--strict-version`: installs missing MODs at their latest available version, does not record or change version in mod-list.json
- With `--strict-version`: installs MODs at the exact version from the save file, records version in mod-list.json; deletes any installed version newer than the save version (Factorio picks the newest zip when multiple versions coexist)

**Use case**: Set up MOD environment to match a specific save file

Expand Down
4 changes: 4 additions & 0 deletions doc/factorix.1
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,10 @@ Number of parallel downloads (default: 4).
.TP
.B \-\-keep\-unlisted
Keep MODs not listed in the save file enabled.
.TP
.B \-\-strict\-version
Install exact MOD versions recorded in the save file (default: install latest).
Deletes any installed version newer than the save version.
.SS factorix mod changelog add ENTRY
Add an entry to MOD changelog.
.TP
Expand Down
16 changes: 8 additions & 8 deletions lib/factorix/api/mod_management_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ def init_upload(mod_name)
response = client.post(uri, body:, headers: build_auth_header, content_type: "application/x-www-form-urlencoded")

parse_upload_url(response)
rescue HTTPNotFoundError => e
raise MODNotOnPortalError, e.api_message || "MOD '#{mod_name}' not found on portal"
rescue HTTPNotFoundError
raise MODNotOnPortalError, "MOD '#{mod_name}' not found on portal"
end

# Complete upload (works for both publish and update scenarios)
Expand Down Expand Up @@ -136,8 +136,8 @@ def edit_details(mod_name, **metadata)
client.post(uri, body:, headers: build_auth_header, content_type: "application/x-www-form-urlencoded")
logger.info("Edit completed successfully", mod: mod_name)
publish("mod.changed", mod: mod_name)
rescue HTTPNotFoundError => e
raise MODNotOnPortalError, e.api_message || "MOD '#{mod_name}' not found on portal"
rescue HTTPNotFoundError
raise MODNotOnPortalError, "MOD '#{mod_name}' not found on portal"
end

# Initialize image upload for a MOD
Expand All @@ -155,8 +155,8 @@ def init_image_upload(mod_name)
response = client.post(uri, body:, headers: build_auth_header, content_type: "application/x-www-form-urlencoded")

parse_upload_url(response)
rescue HTTPNotFoundError => e
raise MODNotOnPortalError, e.api_message || "MOD '#{mod_name}' not found on portal"
rescue HTTPNotFoundError
raise MODNotOnPortalError, "MOD '#{mod_name}' not found on portal"
end

# Complete image upload
Expand Down Expand Up @@ -200,8 +200,8 @@ def edit_images(mod_name, image_ids)
client.post(uri, body:, headers: build_auth_header, content_type: "application/x-www-form-urlencoded")
logger.info("Images updated successfully", mod: mod_name)
publish("mod.changed", mod: mod_name)
rescue HTTPNotFoundError => e
raise MODNotOnPortalError, e.api_message || "MOD '#{mod_name}' not found on portal"
rescue HTTPNotFoundError
raise MODNotOnPortalError, "MOD '#{mod_name}' not found on portal"
end

private def api_credential
Expand Down
8 changes: 4 additions & 4 deletions lib/factorix/api/mod_portal_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ def get_mod(name)
encoded_name = ERB::Util.url_encode(name)
uri = build_uri("/api/mods/#{encoded_name}")
fetch_with_cache(uri)
rescue HTTPNotFoundError => e
raise MODNotOnPortalError, e.api_message || "MOD '#{name}' not found on portal"
rescue HTTPNotFoundError
raise MODNotOnPortalError, "MOD '#{name}' not found on portal"
end

# Retrieve detailed information for a specific MOD
Expand All @@ -70,8 +70,8 @@ def get_mod_full(name)
encoded_name = ERB::Util.url_encode(name)
uri = build_uri("/api/mods/#{encoded_name}/full")
fetch_with_cache(uri)
rescue HTTPNotFoundError => e
raise MODNotOnPortalError, e.api_message || "MOD '#{name}' not found on portal"
rescue HTTPNotFoundError
raise MODNotOnPortalError, "MOD '#{name}' not found on portal"
end

# Event handler for mod.changed event
Expand Down
Loading