Fix export filename extension case handling (fixes #19050) - #21863
Open
sjmudd wants to merge 2 commits into
Open
Fix export filename extension case handling (fixes #19050)#21863sjmudd wants to merge 2 commits into
sjmudd wants to merge 2 commits into
Conversation
Storage modules (disk, gallery, latex) unconditionally appended the export format's extension after variable expansion, even when the filename pattern already produced one -- so a pattern like $(FILE_NAME).JPG became name.JPG.jpg. Now they skip the implicit append when the expanded name already ends in a matching extension (case-insensitive). In disk.c, the "generate unique filename on conflict" handling reuses the same insertion point to write "_01", "_02" suffixes before the extension. That insertion point is now computed consistently via dt_util_str_extension_offset() whether the extension was already present or just appended, fixing a related duplicate-extension bug in the conflict path. Also add $(EXPORT_EXTENSION), exposing the extension of the format actually being exported to, as opposed to $(FILE_EXTENSION) which is the source file's extension. This lets $(FILE_NAME).$(EXPORT_EXTENSION^^) produce the correct extension dynamically, matching camera-style uppercase naming, for whatever export format is selected.
da-phil
reviewed
Aug 15, 2026
| LINK_LIBRARIES lib_darktable cmocka) | ||
|
|
||
| if(WIN32) | ||
| target_link_libraries(test_utility PRIVATE lib_darktable) |
Contributor
There was a problem hiding this comment.
I'm wondering why this is needed only for windows, does the add_cmocka_test(... LINK_LIBRARIES lib_darktable) not work properly on windows?
Author
There was a problem hiding this comment.
My understanding is Windows has no RPATH, so the DLL must be copied next to the test binary manually or it won't be found at runtime.
|
What happens in these case?
|
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Export filename extension case (fixes #19050)
Problem
Exported filenames always got a hard-coded lowercase extension (
.jpg,.png, ...) appended by the storage module, regardless of what thefilename pattern already produced. Two consequences:
.JPGto match camera-style naming like
IMG_1234.CR3).$(FILE_NAME).JPG) produced a duplicated extension:IMG_1234.JPG.jpg.There was also no variable exposing the export format's extension.
$(FILE_EXTENSION)reflects the source file's extension only, so$(FILE_NAME).$(FILE_EXTENSION^^)does not give the export extensionat all — for a CR3 processed to JPEG it expands to
IMG_1234.CR3.Changes
1. Don't double-append a matching extension
(
common/utility.c/.h,imageio/storage/{disk,gallery,latex}.c)Added
dt_util_str_ends_with_extension(), a case-insensitive"does this filename already end in
.ext" check. Each storagemodule now skips appending its implicit extension when the expanded
pattern already ends with it (in any case). Patterns without an
extension behave exactly as before.
In
disk.c, the "generate unique filename on conflict" handlingreuses the same insertion point to write
_01,_02, ... suffixesbefore the extension on repeated exports to the same target. That
insertion point is now computed consistently whether the extension
was already present in the pattern or just appended, so conflict
suffixes land in the right place (
name_01.jpg) instead of after analready-present extension (
name.JPG_01.jpg).2. New
$(EXPORT_EXTENSION)variable(
common/variables.c/.h,gui/gtkentry.c,imageio/storage/{disk,gallery,latex,piwigo}.c)Exposes the extension of the export format actually being used
(
format->extension(fdata)), as opposed to$(FILE_EXTENSION)which is the source file's extension. Works with the existing
^/^^/,/,,case operators like any other variable.Result
now expands correctly and dynamically for whatever format is being
exported to, e.g.
IMG_1234.CR3→IMG_1234.JPGwhen exporting toJPEG, with no duplicated extension.
Scope
disk(file export) and the GUI'sEXPORT_EXTENSIONavailabilitycover the reported case.
galleryandlatexstorage got the samedouble-append fix for consistency (same underlying pattern, same
bug).
piwigo's pattern-driven path doesn't append an extensionitself, so it only gained
$(EXPORT_EXTENSION)support, not thedouble-append fix (nothing to fix there).
emailstorage builds itsfilename internally, not from a user pattern, so it's unaffected.
Testing
All changed files compile cleanly under the project's CI flags
(
gcc-16,-Werror -Wfatal-errors, Ubuntu 26.04 toolchain).Verified end-to-end with
darktable-cliexporting a real Canon CR3sample:
$(FILE_NAME).JPG(JPEG export) → single correctly-casedextension, no duplication.
.jpgbehavior, no regression.$(FILE_NAME).$(EXPORT_EXTENSION^^)(JPEG export) →IMG_1234.JPG.$(FILE_NAME).$(EXPORT_EXTENSION^^)(PNG export, same sourcefile) →
IMG_1234.PNG— confirms the variable tracks the actualexport format rather than being hard-coded to one.
$(FILE_NAME).$(EXPORT_EXTENSION,,)(JPEG export) →IMG_1234.jpg— lowercase operator works as expected.$(FILE_NAME).JPG(JPEG export) exported three times to the samelocation with "generate unique filename" conflict handling →
IMG_1234.JPG,IMG_1234_01.jpg,IMG_1234_02.jpg.Automated tests added:
src/tests/variables.cgained atest_export_extensioncasecovering
$(EXPORT_EXTENSION)with all four case operators, andthe
$(FILE_NAME).$(EXPORT_EXTENSION^^)combination, including acase confirming
$(FILE_EXTENSION)and$(EXPORT_EXTENSION)stayindependent (source vs. export format extension).
src/tests/unittests/util/test_utility.cfor
dt_util_str_ends_with_extension()and the extracteddt_util_str_extension_offset()helper, including the exactmatching-extension-plus-conflict-suffix case that caused the
disk.cbug above.