Comment lib/copy/* (#LLM-assisted - Claude Code)
This commit is contained in:
parent
c99825912f
commit
ee119f07a4
@ -1,6 +1,25 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright © 2012-2026 ScriptFanix
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# A copy of the GNU General Public License v3 is includded in the LICENSE file
|
||||||
|
# at the root of the project.
|
||||||
|
|
||||||
copyFiles_action() {
|
copyFiles_action() {
|
||||||
(( cron )) || echo -n $'Copying files...\033[K'
|
(( cron )) || echo -n $'Copying files...\033[K'
|
||||||
|
# Query all destination_files whose last_change doesn't match the
|
||||||
|
# source, restricted to mime_type_actions with action=2 (direct copy,
|
||||||
|
# not transcode).
|
||||||
|
# The join on mime_type_actions ensures we only copy files destined for
|
||||||
|
# a destination that has explicitly mapped this MIME type to action=2.
|
||||||
echo '
|
echo '
|
||||||
SELECT
|
SELECT
|
||||||
source_files.filename,
|
source_files.filename,
|
||||||
@ -22,6 +41,8 @@ copyFiles_action() {
|
|||||||
AND mime_type_actions.action = 2;
|
AND mime_type_actions.action = 2;
|
||||||
|
|
||||||
SELECT "AtOM:NoMoreFiles";' >&3
|
SELECT "AtOM:NoMoreFiles";' >&3
|
||||||
|
# Results are NUL-delimited rows; sentinel value signals end of result
|
||||||
|
# set.
|
||||||
read -u4 -r -d $'\0' line
|
read -u4 -r -d $'\0' line
|
||||||
while ! [[ $line = AtOM:NoMoreFiles ]]
|
while ! [[ $line = AtOM:NoMoreFiles ]]
|
||||||
do
|
do
|
||||||
@ -29,9 +50,14 @@ copyFiles_action() {
|
|||||||
read -u4 -r -d $'\0' line
|
read -u4 -r -d $'\0' line
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Wrap all DB updates in a single transaction for performance.
|
||||||
echo 'BEGIN TRANSACTION;' >&3
|
echo 'BEGIN TRANSACTION;' >&3
|
||||||
for copyfile in "${copyfiles[@]}"
|
for copyfile in "${copyfiles[@]}"
|
||||||
do
|
do
|
||||||
|
# Each row is a single string with columns joined by
|
||||||
|
# ::AtOM:SQL:Sep::.
|
||||||
|
# Strip prefix to extract each field in order, advancing $rest
|
||||||
|
# each time.
|
||||||
sourcefilename=${copyfile%%::AtOM:SQL:Sep::*}
|
sourcefilename=${copyfile%%::AtOM:SQL:Sep::*}
|
||||||
sourcedir=${sourcefilename%/*}
|
sourcedir=${sourcefilename%/*}
|
||||||
rest="${copyfile#*::AtOM:SQL:Sep::}::AtOM:SQL:Sep::"
|
rest="${copyfile#*::AtOM:SQL:Sep::}::AtOM:SQL:Sep::"
|
||||||
@ -45,20 +71,33 @@ copyFiles_action() {
|
|||||||
rest=${rest#*::AtOM:SQL:Sep::}
|
rest=${rest#*::AtOM:SQL:Sep::}
|
||||||
(( count++ ))
|
(( count++ ))
|
||||||
(( cron )) || printf '\b\b\b\b%3i%%' $(( (count * 100) / ${#copyfiles[@]} ))
|
(( cron )) || printf '\b\b\b\b%3i%%' $(( (count * 100) / ${#copyfiles[@]} ))
|
||||||
|
# If this destination uses a rename/path pattern, delegate path
|
||||||
|
# resolution to guessPath(), which looks up the
|
||||||
|
# already-transcoded sibling to find the correct output
|
||||||
|
# directory.
|
||||||
if [ -n "${destinationrenamepath["$destination"]}" ]
|
if [ -n "${destinationrenamepath["$destination"]}" ]
|
||||||
then
|
then
|
||||||
destdir="$(guessPath)"
|
destdir="$(guessPath)"
|
||||||
guessstatus=$?
|
guessstatus=$?
|
||||||
case $guessstatus in
|
case $guessstatus in
|
||||||
1)
|
1)
|
||||||
|
# guessPath found no transcoded
|
||||||
|
# sibling; skip this file entirely.
|
||||||
continue
|
continue
|
||||||
;;
|
;;
|
||||||
2)
|
2)
|
||||||
|
# Transcoded siblings exist but are not
|
||||||
|
# yet up to date; defer this copy until
|
||||||
|
# the next run so the directory is
|
||||||
|
# stable.
|
||||||
(( postponed++ ))
|
(( postponed++ ))
|
||||||
continue
|
continue
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
else
|
else
|
||||||
|
# No rename pattern: mirror the source directory
|
||||||
|
# structure under the destination root, sanitizing each
|
||||||
|
# path component for the target FS.
|
||||||
destdir="${destinationpath["$destination"]}/"
|
destdir="${destinationpath["$destination"]}/"
|
||||||
if [[ $sourcefilename =~ / ]]
|
if [[ $sourcefilename =~ / ]]
|
||||||
then
|
then
|
||||||
@ -79,6 +118,9 @@ copyFiles_action() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
# Try the cheapest copy methods first: reflink (CoW, same
|
||||||
|
# filesystem), then hardlink (csame filesystem), falling back
|
||||||
|
# to a full data copy.
|
||||||
if cp -a --reflink=always \
|
if cp -a --reflink=always \
|
||||||
"$sourcepath/$sourcefilename" \
|
"$sourcepath/$sourcefilename" \
|
||||||
"$destdir" \
|
"$destdir" \
|
||||||
@ -91,6 +133,9 @@ copyFiles_action() {
|
|||||||
"$sourcepath/$sourcefilename" \
|
"$sourcepath/$sourcefilename" \
|
||||||
"$destdir"
|
"$destdir"
|
||||||
then
|
then
|
||||||
|
# Newlines in filenames are stored as a safe inline
|
||||||
|
# placeholder so the value can be embedded in SQL
|
||||||
|
# without breaking row parsing.
|
||||||
destfilename=${sourcefilename//$'\n'/::AtOM:NewLine:SQL:Inline::}
|
destfilename=${sourcefilename//$'\n'/::AtOM:NewLine:SQL:Inline::}
|
||||||
Update destination_files \
|
Update destination_files \
|
||||||
filename \
|
filename \
|
||||||
|
|||||||
@ -1,12 +1,39 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright © 2012-2026 ScriptFanix
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# A copy of the GNU General Public License v3 is includded in the LICENSE file
|
||||||
|
# at the root of the project.
|
||||||
|
|
||||||
checkCopy() {
|
checkCopy() {
|
||||||
|
# Returns true only when the source file is compatible enough with the
|
||||||
|
# destination profile that it can be copied instead of re-encoded.
|
||||||
|
# All three conditions must hold simultaneously.
|
||||||
(
|
(
|
||||||
|
# If the destination doesn't restrict sample rate, any rate is
|
||||||
|
# acceptable. Otherwise the source rate must match exactly.
|
||||||
[ -z "${destinationfrequency[$destination]}" ] \
|
[ -z "${destinationfrequency[$destination]}" ] \
|
||||||
|| (( ${rate:-0} == ${destinationfrequency[$destination]} ))
|
|| (( ${rate:-0} == ${destinationfrequency[$destination]} ))
|
||||||
) && (
|
) && (
|
||||||
|
# If the destination doesn't restrict channel count, any number
|
||||||
|
# is acceptable. Otherwise the source channel count must match
|
||||||
|
# exactly.
|
||||||
[ -z "${destinationchannels[$destination]}" ] \
|
[ -z "${destinationchannels[$destination]}" ] \
|
||||||
|| (( ${channels:-0} == ${destinationchannels[$destination]} ))
|
|| (( ${channels:-0} == ${destinationchannels[$destination]} ))
|
||||||
) && (
|
) && (
|
||||||
|
# Bitrate check: accept if source exactly matches the target
|
||||||
|
# quality setting, OR if a maximum bps ceiling is configured
|
||||||
|
# and the source bitrate is at or below it.
|
||||||
|
# Default of 1000 kbps when bitrate is unknown forces a
|
||||||
|
# re-encode
|
||||||
(( ${bitrate:-1000} == ${destinationquality[$destination]} )) \
|
(( ${bitrate:-1000} == ${destinationquality[$destination]} )) \
|
||||||
|| (
|
|| (
|
||||||
[ -n "${destinationmaxbps[$destination]}" ] \
|
[ -n "${destinationmaxbps[$destination]}" ] \
|
||||||
|
|||||||
@ -1,6 +1,29 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright © 2012-2026 ScriptFanix
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# A copy of the GNU General Public License v3 is includded in the LICENSE file
|
||||||
|
# at the root of the project.
|
||||||
|
|
||||||
guessPath() {
|
guessPath() {
|
||||||
|
# For copy files (action=2) with a rename pattern, we don't know the
|
||||||
|
# output directory ourselves: it was determined when the audio siblings
|
||||||
|
# were transcoded (action=1). We infer it by finding a transcoded
|
||||||
|
# sibling in the same source directory and reading back its destination
|
||||||
|
# path.
|
||||||
|
#
|
||||||
|
# First query: check whether any transcoded sibling is up to date.
|
||||||
|
# The LIKE pattern matches files directly inside $sourcedir only
|
||||||
|
# the NOT LIKE excludes deeper subdirectorie to avoid crossing
|
||||||
|
# boundaries.
|
||||||
echo 'SELECT IFNULL( (
|
echo 'SELECT IFNULL( (
|
||||||
SELECT destination_files.last_change
|
SELECT destination_files.last_change
|
||||||
FROM destination_files
|
FROM destination_files
|
||||||
@ -22,10 +45,17 @@ guessPath() {
|
|||||||
),"0.0");
|
),"0.0");
|
||||||
'>&3
|
'>&3
|
||||||
read -u4 -r -d $'\0' timestamp
|
read -u4 -r -d $'\0' timestamp
|
||||||
|
# IFNULL returns "0.0" when no transcoded sibling exists yet; strip the
|
||||||
|
# decimal and treat as zero to detect the no-sibling case.
|
||||||
if (( ${timestamp/./} == 0 ))
|
if (( ${timestamp/./} == 0 ))
|
||||||
then
|
then
|
||||||
|
# No transcoded sibling found at all
|
||||||
|
# caller should postpone this copy.
|
||||||
return 2
|
return 2
|
||||||
fi
|
fi
|
||||||
|
# Second query: retrieve the actual destination filename of the most
|
||||||
|
# recently updated transcoded sibling so we can derive its parent
|
||||||
|
# directory.
|
||||||
echo 'SELECT IFNULL( (
|
echo 'SELECT IFNULL( (
|
||||||
SELECT destination_files.filename
|
SELECT destination_files.filename
|
||||||
FROM destination_files
|
FROM destination_files
|
||||||
@ -49,8 +79,12 @@ guessPath() {
|
|||||||
read -u4 -r -d $'\0' filename
|
read -u4 -r -d $'\0' filename
|
||||||
if [[ $filename != AtOM:NotFound ]]
|
if [[ $filename != AtOM:NotFound ]]
|
||||||
then
|
then
|
||||||
|
# Strip the filename component to return only the directory
|
||||||
|
# portion.
|
||||||
echo "${filename%/*}"
|
echo "${filename%/*}"
|
||||||
else
|
else
|
||||||
|
# Sibling record exists but has no usable filename — skip this
|
||||||
|
# file.
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,25 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright © 2012-2026 ScriptFanix
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# A copy of the GNU General Public License v3 is includded in the LICENSE file
|
||||||
|
# at the root of the project.
|
||||||
|
|
||||||
copyFiles_matching() {
|
copyFiles_matching() {
|
||||||
|
# Preserve the original file extension so the copy keeps its type
|
||||||
|
# (e.g. .jpg, .png, .cue) regardless of any rename pattern applied to
|
||||||
|
# the base name.
|
||||||
local extension="${filename##*.}"
|
local extension="${filename##*.}"
|
||||||
|
# Try hardlink first (no extra disk space); fall back to a full data
|
||||||
|
# copy if the source and destination are on different filesystems.
|
||||||
if \
|
if \
|
||||||
cp -al \
|
cp -al \
|
||||||
"$sourcepath/$filename" \
|
"$sourcepath/$filename" \
|
||||||
@ -10,6 +29,11 @@ copyFiles_matching() {
|
|||||||
"$sourcepath/$filename" \
|
"$sourcepath/$filename" \
|
||||||
"${destinationpath[$destination]}/$destdir/$destfile.$extension"
|
"${destinationpath[$destination]}/$destdir/$destfile.$extension"
|
||||||
then
|
then
|
||||||
|
# Record the new destination path and copy the source
|
||||||
|
# last_change timestamp via a subquery so the DB reflects when
|
||||||
|
# the source was last modified.
|
||||||
|
# old_filename captures the previous path so stale files can be
|
||||||
|
# cleaned up later.
|
||||||
echo \
|
echo \
|
||||||
"UPDATE destination_files" \
|
"UPDATE destination_files" \
|
||||||
"SET filename=" \
|
"SET filename=" \
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user