summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md9
-rwxr-xr-xbin/photoalbum52
-rwxr-xr-xsrc/photoalbum.sh52
-rwxr-xr-xtests/cli.sh74
4 files changed, 172 insertions, 15 deletions
diff --git a/README.md b/README.md
index 7dcfa43..3e62274 100644
--- a/README.md
+++ b/README.md
@@ -45,10 +45,15 @@ settings, readable input and template directories, a writable output location,
and ImageMagick availability. Generation stops before writing album output when
validation fails.
+Only regular files in `INCOMING_DIR` with supported image extensions are
+processed as album images. Supported extensions are `jpg`, `jpeg`, `png`, `webp`,
+and `gif`, matched case-insensitively. Other files, such as `.txt` or `.md`
+notes, are ignored with a warning so generation can continue.
+
Successful generation writes `photoalbum.json` into the output directory. This
metadata records the generator version and timestamp, config source, template
-directory, source and generated file counts, tarball status, and effective
-settings useful for debugging a published album.
+directory, supported source image and generated file counts, tarball status, and
+effective settings useful for debugging a published album.
The following long options override config values:
diff --git a/bin/photoalbum b/bin/photoalbum
index 4dbc484..4429f7e 100755
--- a/bin/photoalbum
+++ b/bin/photoalbum
@@ -299,7 +299,8 @@ cleanphotos() {
while IFS= read -r photo; do
basename=$(basename "$photo")
- if [ -f "$INCOMING_DIR/$basename" ]; then
+ if [[ -f "$INCOMING_DIR/$basename" ]] \
+ && is_supported_image_file "$basename"; then
continue
fi
@@ -312,6 +313,43 @@ cleanphotos() {
done < <(find "$DIST_DIR/photos" -maxdepth 1 -type f)
}
+is_supported_image_file() {
+ local -r file="$1"; shift
+ local extension="${file##*.}"
+
+ extension="${extension,,}"
+
+ case "$extension" in
+ gif|jpeg|jpg|png|webp)
+ return 0
+ ;;
+ *)
+ return 1
+ ;;
+ esac
+}
+
+incoming_image_files() {
+ local file
+
+ while IFS= read -r file; do
+ if is_supported_image_file "$file"; then
+ printf '%s\n' "$file"
+ fi
+ done < <(find "$INCOMING_DIR" -maxdepth 1 -type f -printf '%f\n') \
+ | sort
+}
+
+warn_unsupported_incoming_files() {
+ local file
+
+ while IFS= read -r file; do
+ if ! is_supported_image_file "$file"; then
+ echo "WARNING: Ignoring unsupported incoming file: $file" >&2
+ fi
+ done < <(find "$INCOMING_DIR" -maxdepth 1 -type f -printf '%f\n' | sort)
+}
+
scalephotos() {
local destphoto
local dirname
@@ -342,10 +380,7 @@ scalephotos() {
-auto-orient \
"$destphoto"
fi
- done < <(
- find "$INCOMING_DIR" -maxdepth 1 -type f -printf '%f\n' \
- | sort
- )
+ done < <(incoming_image_files)
}
random_animation_css_class() {
@@ -568,6 +603,10 @@ count_files() {
fi
}
+count_incoming_images() {
+ incoming_image_files | wc -l
+}
+
count_tree_files() {
local -r dir="$1"; shift
local -r name="$1"; shift
@@ -585,7 +624,7 @@ write_generation_metadata() {
local -r generated_at=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
local -r config_source="${PHOTOALBUM_CONFIG_SOURCE:-}"
local -r template_name=$(basename "$TEMPLATE_DIR")
- local -r source_image_count=$(count_files "$INCOMING_DIR")
+ local -r source_image_count=$(count_incoming_images)
local -r generated_photo_count=$(count_files "$DIST_DIR/photos")
local -r generated_thumb_count=$(count_files "$DIST_DIR/thumbs")
local -r generated_html_count=$(count_tree_files "$DIST_DIR" '*.html')
@@ -641,6 +680,7 @@ generate() {
tarball_name="${base}-${now}${TARBALL_SUFFIX:-.tar}"
fi
+ warn_unsupported_incoming_files
mkdir -p "$DIST_DIR/photos"
cleanphotos
scalephotos
diff --git a/src/photoalbum.sh b/src/photoalbum.sh
index 4573946..18f3e70 100755
--- a/src/photoalbum.sh
+++ b/src/photoalbum.sh
@@ -299,7 +299,8 @@ cleanphotos() {
while IFS= read -r photo; do
basename=$(basename "$photo")
- if [ -f "$INCOMING_DIR/$basename" ]; then
+ if [[ -f "$INCOMING_DIR/$basename" ]] \
+ && is_supported_image_file "$basename"; then
continue
fi
@@ -312,6 +313,43 @@ cleanphotos() {
done < <(find "$DIST_DIR/photos" -maxdepth 1 -type f)
}
+is_supported_image_file() {
+ local -r file="$1"; shift
+ local extension="${file##*.}"
+
+ extension="${extension,,}"
+
+ case "$extension" in
+ gif|jpeg|jpg|png|webp)
+ return 0
+ ;;
+ *)
+ return 1
+ ;;
+ esac
+}
+
+incoming_image_files() {
+ local file
+
+ while IFS= read -r file; do
+ if is_supported_image_file "$file"; then
+ printf '%s\n' "$file"
+ fi
+ done < <(find "$INCOMING_DIR" -maxdepth 1 -type f -printf '%f\n') \
+ | sort
+}
+
+warn_unsupported_incoming_files() {
+ local file
+
+ while IFS= read -r file; do
+ if ! is_supported_image_file "$file"; then
+ echo "WARNING: Ignoring unsupported incoming file: $file" >&2
+ fi
+ done < <(find "$INCOMING_DIR" -maxdepth 1 -type f -printf '%f\n' | sort)
+}
+
scalephotos() {
local destphoto
local dirname
@@ -342,10 +380,7 @@ scalephotos() {
-auto-orient \
"$destphoto"
fi
- done < <(
- find "$INCOMING_DIR" -maxdepth 1 -type f -printf '%f\n' \
- | sort
- )
+ done < <(incoming_image_files)
}
random_animation_css_class() {
@@ -568,6 +603,10 @@ count_files() {
fi
}
+count_incoming_images() {
+ incoming_image_files | wc -l
+}
+
count_tree_files() {
local -r dir="$1"; shift
local -r name="$1"; shift
@@ -585,7 +624,7 @@ write_generation_metadata() {
local -r generated_at=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
local -r config_source="${PHOTOALBUM_CONFIG_SOURCE:-}"
local -r template_name=$(basename "$TEMPLATE_DIR")
- local -r source_image_count=$(count_files "$INCOMING_DIR")
+ local -r source_image_count=$(count_incoming_images)
local -r generated_photo_count=$(count_files "$DIST_DIR/photos")
local -r generated_thumb_count=$(count_files "$DIST_DIR/thumbs")
local -r generated_html_count=$(count_tree_files "$DIST_DIR" '*.html')
@@ -641,6 +680,7 @@ generate() {
tarball_name="${base}-${now}${TARBALL_SUFFIX:-.tar}"
fi
+ warn_unsupported_incoming_files
mkdir -p "$DIST_DIR/photos"
cleanphotos
scalephotos
diff --git a/tests/cli.sh b/tests/cli.sh
index 33e4d44..bcad987 100755
--- a/tests/cli.sh
+++ b/tests/cli.sh
@@ -111,8 +111,11 @@ assert metadata["config_source"] == config_source
assert metadata["template"]["directory"] == template_dir
assert metadata["template"]["name"] == template_path.name
assert metadata["source"]["incoming_dir"] == incoming_dir
+supported_extensions = {".gif", ".jpeg", ".jpg", ".png", ".webp"}
assert metadata["source"]["image_count"] == sum(
- 1 for path in incoming_path.iterdir() if path.is_file()
+ 1
+ for path in incoming_path.iterdir()
+ if path.is_file() and path.suffix.lower() in supported_extensions
)
assert metadata["generated"]["photo_count"] == sum(
1 for path in (dist_path / "photos").iterdir() if path.is_file()
@@ -499,6 +502,72 @@ test_generate_cli_no_tarball_overrides_config() {
test::teardown
}
+test_generate_ignores_unsupported_incoming_files_with_warning() {
+ local config_file
+ local fake_bin
+ local output
+
+ test::setup
+ fake_bin="$TEST_TMPDIR/bin"
+ config_file="$TEST_TMPDIR/photoalbum.conf"
+
+ test::install_fake_imagemagick "$fake_bin"
+ mkdir -p "$TEST_TMPDIR/incoming"
+ "$TEST_IMAGEMAGICK" -size 160x90 xc:red \
+ "$TEST_TMPDIR/incoming/01-upper.JPG"
+ "$TEST_IMAGEMAGICK" -size 160x90 xc:red \
+ "$TEST_TMPDIR/incoming/02-photo.jpeg"
+ "$TEST_IMAGEMAGICK" -size 160x90 xc:red \
+ "$TEST_TMPDIR/incoming/03-photo.png"
+ "$TEST_IMAGEMAGICK" -size 160x90 xc:red \
+ "$TEST_TMPDIR/incoming/04-photo.webp"
+ "$TEST_IMAGEMAGICK" -size 160x90 xc:red \
+ "$TEST_TMPDIR/incoming/05-photo.gif"
+ printf 'notes\n' > "$TEST_TMPDIR/incoming/notes.txt"
+ printf '# album notes\n' > "$TEST_TMPDIR/incoming/README.md"
+ mkdir -p "$TEST_TMPDIR/dist/photos"
+ printf 'stale cached unsupported file\n' \
+ > "$TEST_TMPDIR/dist/photos/notes.txt"
+ printf 'stale cached unsupported file\n' \
+ > "$TEST_TMPDIR/dist/photos/README.md"
+ test::write_album_config \
+ "$config_file" "$TEST_TMPDIR/incoming" "$TEST_TMPDIR/dist" \
+ 'Extension filter album' 40
+
+ output=$(
+ cd "$TEST_TMPDIR"
+ PATH="$fake_bin:$PATH" "$TEST_PHOTOALBUM" --generate 2>&1
+ )
+
+ test::assert_file_exists "$TEST_TMPDIR/dist/photos/01-upper.JPG"
+ test::assert_file_exists "$TEST_TMPDIR/dist/photos/02-photo.jpeg"
+ test::assert_file_exists "$TEST_TMPDIR/dist/photos/03-photo.png"
+ test::assert_file_exists "$TEST_TMPDIR/dist/photos/04-photo.webp"
+ test::assert_file_exists "$TEST_TMPDIR/dist/photos/05-photo.gif"
+ test::assert_path_absent "$TEST_TMPDIR/dist/photos/notes.txt"
+ test::assert_path_absent "$TEST_TMPDIR/dist/photos/README.md"
+ test::assert_contains \
+ 'WARNING: Ignoring unsupported incoming file: README.md' \
+ "$output"
+ test::assert_contains \
+ 'WARNING: Ignoring unsupported incoming file: notes.txt' \
+ "$output"
+ test::assert_not_contains 'Processing notes.txt' "$output"
+ test::assert_not_contains 'Processing README.md' "$output"
+
+ python3 - "$TEST_TMPDIR/dist/photoalbum.json" <<'PY'
+import json
+import pathlib
+import sys
+
+metadata = json.loads(pathlib.Path(sys.argv[1]).read_text())
+assert metadata["source"]["image_count"] == 5
+assert metadata["generated"]["photo_count"] == 5
+PY
+
+ test::teardown
+}
+
test_generate_missing_incoming_fails() {
local output
@@ -1298,6 +1367,9 @@ main() {
'--generate --no-tarball overrides config' \
test_generate_cli_no_tarball_overrides_config
test::run_case \
+ '--generate ignores unsupported incoming files with warning' \
+ test_generate_ignores_unsupported_incoming_files_with_warning
+ test::run_case \
'--generate missing incoming fails' \
test_generate_missing_incoming_fails
test::run_case \