#!/bin/bash
# License: GPL
# Author: Steven Shiau <steven _at_ clonezilla org>
# Description: Program to generate JSON file from lsblk output with ID_PATH_TAG, excluding loop* devices
# This file contains code generated by Grok, created by xAI.
# Improved by Google's Gemini for efficiency and robustness.

USAGE() {
    echo "$0 - To generate JSON file from lsblk output with ID_PATH_TAG, excluding loop* devices"
    echo "Usage:"
    echo "To run $0:"
    echo "$0 OUTPUT_FILE"
    echo
} # end of USAGE

####################
### Main program ###
####################

if [ "$#" -ne 1 ] || [[ "$1" == -* ]]; then
    USAGE >&2
    exit 1
fi
ocs_out_f="$1"

# Ensure udev has processed all devices
udevadm settle

# Run lsblk with JSON output, excluding loop, ram, and rom devices (-e 1,7,11)
lsblk_output=$(LC_ALL=C lsblk -J -o name,type,size,model,fstype,serial,label -e 1,7,11 -x name 2>/dev/null)

# Check if lsblk output is empty or contains no devices
if [ -z "$lsblk_output" ] || [ "$(echo "$lsblk_output" | jq '.blockdevices | length')" -eq 0 ]; then
    echo "[]" > "$ocs_out_f"
    exit 0
fi

# Process the entire JSON output with a more efficient pipeline.
echo "$lsblk_output" | jq -c '.blockdevices[]' | while IFS= read -r device_json; do
    # Extract name to query udevadm
    name=$(echo "$device_json" | jq -r '.name')
    dev_path="/dev/$name"

    # Query udevadm for ID_PATH_TAG
    id_path_tag=$(udevadm info --query=property --name="$dev_path" 2>/dev/null | grep '^ID_PATH_TAG=' | cut -d'=' -f2)

    # If ID_PATH_TAG is empty, set it to "N/A"
    id_path_tag=${id_path_tag:-N/A}

    # Use a single jq command to:
    # 1. Add the new 'id_path_tag' field.
    # 2. Use '(.field // "")' to handle potential null values before piping to gsub.
    echo "$device_json" | jq \
        --arg id_path_tag "$id_path_tag" \
        '. + {id_path_tag: $id_path_tag} |
         .type = (.type // "" | gsub(" "; "_")) |
         .size = (.size // "" | gsub(" "; "_")) |
         .model = (.model // "" | gsub(" "; "_")) |
         .fstype = (.fstype // "" | gsub(" "; "_")) |
         .serial = (.serial // "" | gsub(" "; "_")) |
         .label = (.label // "" | gsub(" "; "_")) |
         .id_path_tag = (.id_path_tag // "" | gsub(" "; "_"))'
done | jq -s . > "$ocs_out_f"
