diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
new file mode 100644
index 0000000..e2c778f
--- /dev/null
+++ b/.github/workflows/publish.yml
@@ -0,0 +1,26 @@
+name: Docker Image CI
+
+on:
+ push:
+ branches:
+ - master
+ - main
+ pull_request:
+ branches:
+ - master
+ - main
+
+jobs:
+ publish:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Docker Login
+ env:
+ DOCKER_USER: ${{secrets.DOCKER_USER}}
+ DOCKER_PASSWORD: ${{secrets.DOCKER_PASSWORD}}
+ run: docker login -u $DOCKER_USER -p $DOCKER_PASSWORD
+ - name: Docker Build
+ run: docker build . --file Dockerfile --tag ${{secrets.DOCKER_USER}}/elodie:$(date +%s) --tag ${{secrets.DOCKER_USER}}/elodie:latest
+ - name: Docker Publish
+ run: docker push --all-tags ${{secrets.DOCKER_USER}}/elodie
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index df8f050..59b8c55 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,50 +1,54 @@
-FROM python:3-alpine AS builder
+FROM python:3.9-alpine AS builder
ENV PYTHONUNBUFFERED 1
# Install runtime dependencies
RUN apk --update upgrade && \
- apk add --update inotify-tools exiftool zlib jpeg lcms2 tiff openjpeg su-exec && \
- rm -rf /var/cache/apk/*
-
+ apk add --update inotify-tools exiftool zlib jpeg lcms2 tiff openjpeg su-exec && \
+ rm -rf /var/cache/apk/*
+
# Install build dependencies
RUN apk --update upgrade && \
- apk add --update git \
- build-base \
- jpeg-dev \
- zlib-dev \
- lcms2-dev \
- openjpeg-dev \
- tiff-dev && \
- rm -rf /var/cache/apk/*
+ apk add --update git \
+ build-base \
+ jpeg-dev \
+ zlib-dev \
+ lcms2-dev \
+ openjpeg-dev \
+ tiff-dev && \
+ rm -rf /var/cache/apk/*
WORKDIR /wheels
-RUN git clone https://github.com/jmathai/elodie.git /elodie && \
- pip wheel --no-cache-dir -r /elodie/requirements.txt && \
- rm -rf /elodie/.git
+RUN git clone https://github.com/D3Zyre/Elodie.git /elodie && \
+ pip wheel --no-cache-dir -r /elodie/requirements.txt && \
+ rm -rf /elodie/.git
+
+#Using internal modified copy of file for now
+#RUN git clone https://github.com/javanile/inotifywait-polling.git /inotifywait-polling && \
+# chmod +x /inotifywait-polling/inotifywait-polling.sh
-FROM python:3-alpine
+FROM python:3.9-alpine
LABEL maintainer="pierre@buyle.org"
ENV PYTHONUNBUFFERED 1
# Install runtime dependencies
RUN apk --update upgrade && \
- apk add --update inotify-tools exiftool zlib jpeg lcms2 tiff openjpeg su-exec && \
- rm -rf /var/cache/apk/*
+ apk add --update inotify-tools exiftool zlib jpeg lcms2 tiff openjpeg su-exec bash findutils && \
+ rm -rf /var/cache/apk/*
COPY --from=builder /wheels /wheels
COPY --from=builder /elodie /elodie
+#COPY --from=builder /inotifywait-polling/inotifywait-polling.sh /usr/local/bin/inotifywait-polling
WORKDIR /elodie
RUN pip install --no-cache-dir -r requirements.txt -f /wheels && \
- rm -rf /wheels
-
+ rm -rf /wheels
+
COPY entrypoint.sh /entrypoint.sh
+COPY --chown=root:root --chmod=0777 inotifywait-polling.sh /usr/local/bin/inotifywait-polling
-ENV PUID=1000
-ENV PGID=1000
ENV SOURCE=/source
ENV DESTINATION=/destination
-ENV ELODIE_APPLICATION_DIRECTORY=/elodie
-ENV DEFAULT_COMMAND=watch
+ENV ELODIE_APPLICATION_DIRECTORY=~/.elodie
+ENV ELODIE_DEFAULT_COMMAND=watch
ENTRYPOINT ["/entrypoint.sh"]
\ No newline at end of file
diff --git a/README.md b/README.md
index 6d7a216..71c9a2f 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,10 @@
# elodie-docker
-Docker container for [Elodie](https://github.com/jmathai/elodie)
+Docker container for a more recently updated fork of [Elodie](https://github.com/D3Zyre/Elodie.git)
-
![](https://raw.githubusercontent.com/jmathai/elodie/master/creative/logo@300x.png)
+![](https://raw.githubusercontent.com/D3Zyre/elodie/master/creative/logo@300x.png)
-
-The container default command is to watch a source folder using `inotifywait` and automatically execute `elodie` to import added images to a destination folder.
+The container default command is to watch a source folder using `inotifywait` or [`inotifywait-polling`](https://github.com/javanile/inotifywait-polling) and automatically execute `elodie` to import added images to a destination folder.
## Usage
@@ -32,10 +31,11 @@ docker run \
| DESTINATION | /destination | Copy imported files into this directory
| TRASH | | Set to move files to this trash folder after copying files
| EXCLUDE | | Regular expression for directories or files to exclude
-| ALLOW_DUPLICATE | | Set to import the files even if theu have already been imported
+| ALLOW_DUPLICATE | | Set to import the files even if theu have already been imported
| ALBUM_FROM_FOLDER | | Set to use images' folders as their album names
| MAPQUEST_KEY | | Mapquest API key for geo-code location from EXIF's GPS fields
| DEBUG | | Set to enable debug messages
+| INOTIFYWAIT_POLLING | | Set to enable use of inotifywait polling. Useful for CIFS/SMB/NFS mounts.
### Advanced configurtion
@@ -53,7 +53,7 @@ docker run \
pbuyle/elodie
```
-Note: If a custom configuartion file is used then setting the `MAPQUEST_KEY` environment variable will have not effect.
+Note: If a custom configuration file is used then setting the `MAPQUEST_KEY` environment variable will have not effect.
### User / Group Identifiers
@@ -62,7 +62,8 @@ When using volumes (-v flags) permissions issues can arise between the host OS a
Ensure any volume directories on the host are owned by the same user you specify and any permissions issues will vanish like magic.
In this instance PUID=1000 and PGID=1000, to find yours use id user as below:
+
```
$ id username
uid=1000(dockeruser) gid=1000(dockergroup) groups=1000(dockergroup)
-```
\ No newline at end of file
+```
diff --git a/entrypoint.sh b/entrypoint.sh
index b6e3738..a1693a0 100755
--- a/entrypoint.sh
+++ b/entrypoint.sh
@@ -4,12 +4,13 @@ set -eu
PYTHON="su-exec ${PUID}:${PGID} python"
ELODIE="${PYTHON} /elodie/elodie.py"
+INOTIFY_BIN="inotifywait"
IMPORT_OPTIONS="--destination ${DESTINATION}"
if [ "${TRASH:-}" ]; then
- mkdir -p "${XDG_DATA_HOME:-~/.local/share}"
- ln -s "${TRASH}" "${XDG_DATA_HOME:-${HOME}/.local/share/Trash"
+ mkdir -p "${XDG_DATA_HOME:-${HOME}/.local/share}"
+ ln -s "${TRASH}" "${XDG_DATA_HOME:-${HOME}/.local/share/Trash}"
IMPORT_OPTIONS="${IMPORT_OPTIONS} --trash"
fi
@@ -29,13 +30,17 @@ if [ "${DEBUG:-}" ]; then
IMPORT_OPTIONS="${IMPORT_OPTIONS} --debug"
fi
+if [ "${INOTIFYWAIT_POLLING:-}" ]; then
+ INOTIFY_BIN="inotifywait-polling"
+fi
+
if [ ! -e "${ELODIE_APPLICATION_DIRECTORY}/config.ini" ] && [ "${MAPQUEST_KEY:-}" ] ; then
echo -e "[MapQuest]\nkey=${MAPQUEST_KEY}\nprefer_english_names=False" > "${ELODIE_APPLICATION_DIRECTORY}/config.ini"
fi
case "${1:-watch}" in
watch)
- inotifywait -e close_write -mr "${SOURCE}" | while read -r EV;
+ ${INOTIFY_BIN} -e close_write -mr "${SOURCE}" | while read -r EV;
do
(
NOW=$($PYTHON -c "import time;print(time.time());")
diff --git a/inotifywait-polling.sh b/inotifywait-polling.sh
new file mode 100644
index 0000000..374b682
--- /dev/null
+++ b/inotifywait-polling.sh
@@ -0,0 +1,218 @@
+#!/usr/bin/env bash
+
+##
+# inotifywait-polling
+#
+# REQUIRES: inotifywait in full BASH.
+#
+# Copyright (c) 2020 Francesco Bianco
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+##
+
+[[ -z "${LCOV_DEBUG}" ]] || set -x
+
+set -e
+#set -xv
+
+export LC_ALL=C
+
+#trap '[[ -z "$(jobs -p)" ]] || kill $(jobs -p)' EXIT
+trap 'kill $(jobs -p) > /dev/null 2>&1' EXIT
+
+usage () {
+ cat <<'EOF'
+inotifywait 3.14
+Wait for a particular event on a file or set of files.
+Usage: inotifywait [ options ] file1 [ file2 ] [ file3 ] [ ... ]
+Options:
+ -h|--help Show this help text.
+ @ Exclude the specified file from being watched.
+ --exclude
+ Exclude all events on files matching the
+ extended regular expression .
+ --excludei
+ Like --exclude but case insensitive.
+ -m|--monitor Keep listening for events forever. Without
+ this option, inotifywait will exit after one
+ event is received.
+ -d|--daemon Same as --monitor, except run in the background
+ logging events to a file specified by --outfile.
+ Implies --syslog.
+ -r|--recursive Watch directories recursively.
+ --fromfile
+ Read files to watch from or `-' for stdin.
+ -o|--outfile
+ Print events to rather than stdout.
+ -s|--syslog Send errors to syslog rather than stderr.
+ -q|--quiet Print less (only print events).
+ -qq Print nothing (not even events).
+ --format Print using a specified printf-like format
+ string; read the man page for more details.
+ --timefmt strftime-compatible format string for use with
+ %T in --format string.
+ -c|--csv Print events in CSV format.
+ -t|--timeout
+ When listening for a single event, time out after
+ waiting for an event for seconds.
+ If is 0, inotifywait will never time out.
+ -e|--event [ -e|--event ... ]
+ Listen for specific event(s). If omitted, all events are
+ listened for.
+
+Exit status:
+ 0 - An event you asked to watch for was received.
+ 1 - An event you did not ask to watch for was received
+ (usually delete_self or unmount), or some error occurred.
+ 2 - The --timeout option was given and no events occurred
+ in the specified interval of time.
+
+Events:
+ access file or directory contents were read
+ modify file or directory contents were written
+ attrib file or directory attributes changed
+ close_write file or directory closed, after being opened in
+ writable mode
+ close_nowrite file or directory closed, after being opened in
+ read-only mode
+ close file or directory closed, regardless of read/write mode
+ open file or directory opened
+ moved_to file or directory moved to watched directory
+ moved_from file or directory moved from watched directory
+ move file or directory moved to or from watched directory
+ create file or directory created within watched directory
+ delete file or directory deleted within watched directory
+ delete_self file or directory was deleted
+ unmount file system containing file or directory unmounted
+EOF
+}
+
+quiet=
+recursive=
+options=$(getopt -n inotifywait -o qrhme: -l help -- "$@" && true)
+eval set -- "${options}"
+#echo "options: ${options}"
+
+while true; do
+ case "$1" in
+ -q) quiet=1 ;;
+ -r) recursive=1 ;;
+ -e) shift; events=${1^^} ;;
+ -h|--help) usage; exit ;;
+ --) shift; break ;;
+ esac
+ shift
+done
+
+##
+#
+##
+watch () {
+ #echo "watch $1"
+ find $1 -printf "%s %y %p %T@\\n" | sort -k3 - > $1.inotifywait
+ while true; do
+ sleep 2
+ sign=
+ last=$(cat $1.inotifywait)
+ #mv $1.inotifywait $1.$(date +%s).inotifywait
+ find $1 -printf "%s %y %p %T@\\n" | sort -k3 - > $1.inotifywait
+ meta=$(diff <(echo "${last}") <(cat "$1.inotifywait")) && true
+ [[ -z "${meta}" ]] && continue
+ echo -e "${meta}\n." | while IFS= read line || [[ -n "${line}" ]]; do
+ echo "line: ${line}"
+ if [[ "${line}" == "." ]]; then
+ echo "sign: ${sign}"
+ for item in $(tr ';' '\n' <<< "${sign}"); do
+ echo "item: ${item}"
+ event=$(echo ${item} | cut -s -d':' -f1)
+ focus=$(echo ${item} | cut -s -d':' -f2)
+ dir=$(dirname "${focus}")/
+ echo "focus: ${focus}"
+ file=$(basename "${focus}")
+ print_event ${dir} ${event} ${file}
+ done
+ break
+ fi
+ flag=$(echo ${line} | cut -s -d' ' -f1)
+ file=$(echo ${line} | cut -s -d' ' -f3-)
+ [[ -n "${file}" ]] || continue
+ #echo "${file} -- ${file: -12}"
+ [[ "${file: -12}" != ".inotifywait" ]] || continue
+ case ${flag} in
+ "<")
+ event=DELETE
+ ;;
+ ">")
+ event=CREATE
+ if [[ "${sign}" == *"DELETE:${file};"* ]]; then
+ event=MODIFY
+ sign=$(echo "${sign}" | sed "s#DELETE:${file};##g")
+ elif [[ "${sign}" == *"DELETE:"* ]]; then
+ event=MOVED_TO
+ sign=$(echo "${sign}" | sed "s#DELETE:.*;##g")
+ fi
+ ;;
+ esac
+ sign+="${event}:${file};"
+ done
+ done
+ return 0
+}
+
+##
+#
+##
+print_event () {
+ [[ -z "${events}" || "${events}" == *"$2"* ]] && echo "$1 $2 $3"
+ case "$2" in
+ CREATE)
+ [[ -z "${events}" || "${events}" == *"OPEN"* ]] && echo "$1 OPEN $3"
+ [[ -z "${events}" || "${events}" == *"MODIFY"* ]] && echo "$1 MODIFY $3"
+ [[ -z "${events}" || "${events}" == *"CLOSE"* ]] && echo "$1 CLOSE_WRITE,CLOSE $3"
+ ;;
+ esac
+ return 0
+}
+
+##
+# Entrypoint
+##
+main () {
+ if [[ -z "$1" ]]; then
+ >&2 echo "No files specified to watch!"
+ exit 1
+ fi
+
+ [[ -z "${quiet}" ]] && >&2 echo "Setting up watches."
+
+ for file in "$@"; do
+ if [[ ! -e "${file}" ]]; then
+ echo "Couldn't watch $1: No such file or directory"
+ exit 1
+ fi
+ watch ${file} &
+ done
+
+ [[ -z "${quiet}" ]] && >&2 echo "Watches established."
+ sleep infinity
+ exit 0
+}
+
+##
+main "$@"
\ No newline at end of file