Add sidecar functionality
This commit is contained in:
@@ -94,10 +94,16 @@ def prompt_if_missing(args):
|
||||
# Same prompts as config, plus base_date
|
||||
prompt_for_config(args)
|
||||
try:
|
||||
if not args.base_date:
|
||||
while not args.base_date:
|
||||
dflt = datetime.datetime.now().strftime("%Y-%m-%d")
|
||||
resp = input(f"Base date/time for first image [{dflt}]: ").strip()
|
||||
args.base_date = resp if resp else dflt
|
||||
# Validate immediately so we don't crash later
|
||||
try:
|
||||
parse_user_date(args.base_date)
|
||||
except ValueError:
|
||||
print("Invalid format. Please use 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS'.")
|
||||
args.base_date = None
|
||||
except KeyboardInterrupt:
|
||||
print("\nInterrupted by user. Exiting.")
|
||||
sys.exit(1)
|
||||
@@ -111,10 +117,10 @@ def parse_user_date(dt_str):
|
||||
return datetime.datetime.strptime(dt_str, "%Y-%m-%d")
|
||||
|
||||
|
||||
def build_exiftool_cmd(file_path, author, lab, make, model, film, timestamp):
|
||||
def build_exiftool_cmd(file_path, author, lab, make, model, film, timestamp, sidecar_source=None):
|
||||
"""
|
||||
Builds the command list. Does NOT handle dry_run formatting.
|
||||
Always returns a list for subprocess safety.
|
||||
Builds the command list.
|
||||
sidecar_source: If set, we are creating/updating a sidecar FROM this source image.
|
||||
"""
|
||||
current_year = datetime.datetime.now().year
|
||||
cmd = [
|
||||
@@ -142,7 +148,15 @@ def build_exiftool_cmd(file_path, author, lab, make, model, film, timestamp):
|
||||
cmd.append(f"-UserComment={film}")
|
||||
cmd.append(f"-XMP:Description={film}")
|
||||
|
||||
cmd.append(file_path)
|
||||
if sidecar_source:
|
||||
# Advanced ExifTool usage: read source, write to specific sidecar file
|
||||
# This ensures it works even if the sidecar doesn't exist yet
|
||||
cmd.append(f"-srcfile")
|
||||
cmd.append(file_path)
|
||||
cmd.append(sidecar_source)
|
||||
else:
|
||||
cmd.append(file_path)
|
||||
|
||||
return cmd
|
||||
|
||||
|
||||
@@ -166,6 +180,8 @@ def run_exiftool(cmd, dry_run=False):
|
||||
return True, "Updated"
|
||||
except subprocess.CalledProcessError as e:
|
||||
return False, f"Error: {e}"
|
||||
except FileNotFoundError:
|
||||
return False, "Error: 'exiftool' not found. Please install it."
|
||||
|
||||
|
||||
def create_config_file(args):
|
||||
@@ -201,9 +217,6 @@ def main():
|
||||
if args.workers is None:
|
||||
args.workers = os.cpu_count() or 1
|
||||
|
||||
# LOGIC SIMPLIFICATION 1:
|
||||
# Instead of writing a separate sequential loop for dry-runs,
|
||||
# we just force workers=1 here. The executor handles the rest.
|
||||
if args.dry_run:
|
||||
print("Dry run detected: Forcing sequential processing.")
|
||||
args.workers = 1
|
||||
@@ -243,8 +256,12 @@ def main():
|
||||
ts_dt = base_dt + datetime.timedelta(seconds=i * time_increment)
|
||||
timestamp_str = ts_dt.strftime("%Y:%m:%d %H:%M:%S")
|
||||
|
||||
sidecar_source = None
|
||||
if args.sidecar:
|
||||
target_file_path = f"{f}.xmp"
|
||||
# If sidecar doesn't exist, we must tell ExifTool to create it from the source image
|
||||
if not os.path.exists(target_file_path):
|
||||
sidecar_source = f
|
||||
else:
|
||||
target_file_path = f
|
||||
|
||||
@@ -255,14 +272,14 @@ def main():
|
||||
make=args.make,
|
||||
model=args.model,
|
||||
film=args.film,
|
||||
timestamp=timestamp_str
|
||||
timestamp=timestamp_str,
|
||||
sidecar_source=sidecar_source
|
||||
)
|
||||
|
||||
tasks.append((cmd, f, timestamp_str))
|
||||
|
||||
with ThreadPoolExecutor(max_workers=args.workers) as executor:
|
||||
# Submit all tasks
|
||||
# Note: We pass args.dry_run into the function here
|
||||
futures = {
|
||||
executor.submit(run_exiftool, cmd, args.dry_run): (f, ts)
|
||||
for cmd, f, ts in tasks
|
||||
@@ -274,8 +291,6 @@ def main():
|
||||
success, msg = future.result()
|
||||
|
||||
if args.dry_run:
|
||||
# For dry run, we PRINT the command so the user can copy it
|
||||
# bar.text() is transient, print() persists in terminal
|
||||
print(msg)
|
||||
elif not success:
|
||||
bar.text(f"Failed {original_file}: {msg}")
|
||||
|
||||
Reference in New Issue
Block a user