From f8a6d28311404ecf3300748363b0ffaf4eee8c9a Mon Sep 17 00:00:00 2001 From: Mark Randall Havens Date: Mon, 9 Jun 2025 15:30:46 -0500 Subject: [PATCH] Post-Local sync at 2025-06-09T20:30:45Z --- .gitfield/push_log.json | 6 + .gitfield/pushed.log | 4 + bin/gitfield-sync | 253 +++++++++++++++++++++++++++++++++++++-- bin/gitfield-sync-OLD2 | 259 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 513 insertions(+), 9 deletions(-) create mode 100755 bin/gitfield-sync-OLD2 diff --git a/.gitfield/push_log.json b/.gitfield/push_log.json index 3893ec0..8bdddac 100644 --- a/.gitfield/push_log.json +++ b/.gitfield/push_log.json @@ -206,6 +206,12 @@ "branch": "master", "commit": "bd6094eef8e13a5f13bee04ace29d7f6809e9e55", "message": "Post-Local sync at 2025-06-09 14:43:29" + }, + { + "timestamp": "2025-06-09 15:30:45", + "branch": "master", + "commit": "fa6f594a7d42fa9faada350c22846a814537ed7c", + "message": "Generated .gitfield/README.txt at 2025-06-09T20:30:45Z" } ] } diff --git a/.gitfield/pushed.log b/.gitfield/pushed.log index ae6e597..7e1ee1e 100644 --- a/.gitfield/pushed.log +++ b/.gitfield/pushed.log @@ -193,3 +193,7 @@ CLI: rad inspect rad:z3FEj7rF8gZw9eFksCuiN43qjzrex # View project details CLI: git ls-tree -r --name-only HEAD # View file structure [2025-06-09 14:45:17] Forgejo: https://remember.thefoldwithin.earth/mrhavens/git-sigil +[2025-06-09T20:30:46Z] Local: , Branch=master, Commit=89b7d20 + Diff Summary: + .gitfield/local.sigil.md | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/bin/gitfield-sync b/bin/gitfield-sync index d3e0499..98500d1 100755 --- a/bin/gitfield-sync +++ b/bin/gitfield-sync @@ -8,12 +8,19 @@ IFS=$'\n\t' REPO_PATH=$(git rev-parse --show-toplevel 2>/dev/null) || error "Not inside a Git repository" REPO_NAME=$(basename "$REPO_PATH") GITFIELD_DIR="$REPO_PATH/.gitfield" +WELL_KNOWN_DIR="$REPO_PATH/.well-known" LOG_FILE="$GITFIELD_DIR/pushed.log" GITFIELD_MD="$REPO_PATH/GITFIELD.md" -TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S') -SCRIPT_VERSION="1.0" +CANONICAL_META="$GITFIELD_DIR/canonical.meta" +CANONICAL_MD="$GITFIELD_DIR/canonical.md" +INDEX_JSON="$GITFIELD_DIR/index.json" +WELL_KNOWN_JSON="$WELL_KNOWN_DIR/gitfield.json" +TIMESTAMP=$(date -u '+%Y-%m-%dT%H:%M:%SZ') +SCRIPT_VERSION="1.1" # Updated version for metadata enhancements +PRESERVE_META=${PRESERVE_META:-false} # Flag to preserve existing metadata (default: false) # URLs for each platform +CANONICAL_URL="https://remember.thefoldwithin.earth/mrhavens/$REPO_NAME" GITHUB_URL="https://github.com/mrhavens/$REPO_NAME" GITLAB_URL="https://gitlab.com/mrhavens/$REPO_NAME" BITBUCKET_URL="https://bitbucket.org/thefoldwithin/$REPO_NAME" @@ -23,6 +30,20 @@ GITEA_URL="https://gitea.com/mrhavens/$REPO_NAME" RADICLE_RID="rad:z3FEj7rF8gZw9eFksCuiN43qjzrex" RADICLE_PEER_ID="z6Mkw5s3ppo26C7y7tGK5MD8n2GqTHS582PPpeX5Xqbu2Mpz" +# Metadata configuration +MIRRORS=( + "$GITHUB_URL" + "$GITLAB_URL" + "$BITBUCKET_URL" + "$FORGEJO_URL" + "$CODEBERG_URL" + "$GITEA_URL" + "rad:$RADICLE_RID" +) +COMMIT_HASH=$(git -C "$REPO_PATH" rev-parse --short HEAD 2>/dev/null || echo "unknown") +TREE_HASH=$(git -C "$REPO_PATH" rev-parse HEAD^{tree} 2>/dev/null || echo "unknown") +SYNC_CYCLES=0 + # ╭─────────────────────────────────────╮ # │ LOGGING UTILS │ # ╰─────────────────────────────────────╮ @@ -62,10 +83,176 @@ find_script() { error "Script $script_name not found in any search path" } +# ╭─────────────────────────────────────╮ +# │ METADATA GENERATION │ +# ╰─────────────────────────────────────╮ +generate_canonical_meta() { + info "Generating $CANONICAL_META..." + if [ "$PRESERVE_META" = "true" ] && [ -f "$CANONICAL_META" ]; then + info "Preserving existing $CANONICAL_META (--preserve-meta enabled)" + return + fi + cat > "$CANONICAL_META" < "$CANONICAL_MD" < "$INDEX_JSON" < "$WELL_KNOWN_JSON" < "$readme_file" < "$LOG_FILE" @@ -160,8 +347,11 @@ This multi-repository approach, bolstered by Forgejo’s sovereign hosting, refl ## 📜 Metadata and Logs -- **Metadata Files**: Each platform generates a metadata snapshot in the \`.gitfield\` directory (e.g., \`github.sigil.md\`, \`gitlab.sigil.md\`, \`remember.sigil.md\`, \`codeberg.sigil.md\`, \`gitea.sigil.md\`, etc.), capturing commit details, environment information, and hardware fingerprints. -- **Push Log**: The \`.gitfield/pushed.log\` file records the date, time, and RID/URL of every push operation across all platforms, providing a transparent audit trail. +- **Canonical Metadata**: The canonical repository is declared in [\`.gitfield/canonical.meta\`](./.gitfield/canonical.meta) (machine-readable JSON) and [\`.gitfield/canonical.md\`](./.gitfield/canonical.md) (human-readable Markdown). +- **Index Manifest**: A full manifest of remotes, commit details, and sync cycles is available in [\`.gitfield/index.json\`](./.gitfield/index.json). +- **Well-Known Metadata**: SEO-friendly metadata with Schema.org JSON-LD is available in [\`.well-known/gitfield.json\`](./.well-known/gitfield.json). +- **Push Log**: The \`.gitfield/pushed.log\` file records the date, time, commit hash, and RID/URL of every push operation across all platforms, providing a transparent audit trail. +- **GitField Directory**: The \`.gitfield\` directory contains additional metadata and platform-specific sigils (e.g., \`github.sigil.md\`). See [\`.gitfield/README.txt\`](./.gitfield/README.txt) for details. - **Recursive Sync**: The repository is synchronized across all platforms in a recursive loop (three cycles) to ensure interconnected metadata captures the latest state of the project. - **Push Order**: The repository is synchronized in the following order: **Radicle → Forgejo → Codeberg → Gitea → GitLab → Bitbucket → GitHub**. This prioritizes Radicle’s decentralized, censorship-resistant network as the primary anchor, followed by Forgejo’s sovereign, self-hosted infrastructure, Codeberg’s community-driven platform, Gitea’s lightweight efficiency, GitLab’s robust DevOps features, Bitbucket’s enterprise redundancy, and GitHub’s broad visibility, ensuring a resilient and accessible metadata chain. @@ -183,15 +373,25 @@ log_url() { local url=$2 local rid=$3 local peer_id=$4 - local timestamp=$(date '+%Y-%m-%d %H:%M:%S') + local timestamp=$(date -u '+%Y-%m-%dT%H:%M:%SZ') + local branch=$(git -C "$REPO_PATH" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown") + local diff_summary=$(git -C "$REPO_PATH" diff --stat HEAD^ HEAD 2>/dev/null || echo "No diff available") if [ "$platform" = "Radicle" ]; then - echo "[$timestamp] $platform: RID=$rid, Peer ID=$peer_id" >> "$LOG_FILE" + echo "[$timestamp] $platform: RID=$rid, Peer ID=$peer_id, Branch=$branch, Commit=$COMMIT_HASH" >> "$LOG_FILE" echo " CLI: rad inspect $rid # View project details" >> "$LOG_FILE" echo " CLI: git ls-tree -r --name-only HEAD # View file structure" >> "$LOG_FILE" - info "Logged push to $LOG_FILE: [$timestamp] $platform: RID=$rid, Peer ID=$peer_id" + if [ -n "$diff_summary" ]; then + echo " Diff Summary:" >> "$LOG_FILE" + echo "$diff_summary" | sed 's/^/ /' >> "$LOG_FILE" + fi + info "Logged push to $LOG_FILE: [$timestamp] $platform: RID=$rid, Peer ID=$peer_id, Branch=$branch, Commit=$COMMIT_HASH" else - echo "[$timestamp] $platform: $url" >> "$LOG_FILE" - info "Logged push to $LOG_FILE: [$timestamp] $platform: $url" + echo "[$timestamp] $platform: $url, Branch=$branch, Commit=$COMMIT_HASH" >> "$LOG_FILE" + if [ -n "$diff_summary" ]; then + echo " Diff Summary:" >> "$LOG_FILE" + echo "$diff_summary" | sed 's/^/ /' >> "$LOG_FILE" + fi + info "Logged push to $LOG_FILE: [$timestamp] $platform: $url, Branch=$branch, Commit=$COMMIT_HASH" fi } @@ -225,6 +425,7 @@ execute_push() { run_push_cycle() { local cycle_number=$1 info "Starting push cycle $cycle_number..." + SYNC_CYCLES=$cycle_number execute_push "gitfield-local" "Local" "" "" "" execute_push "gitfield-radicle" "Radicle" "" "$RADICLE_RID" "$RADICLE_PEER_ID" @@ -234,6 +435,13 @@ run_push_cycle() { execute_push "gitfield-gitlab" "GitLab" "$GITLAB_URL" "" "" execute_push "gitfield-bitbucket" "Bitbucket" "$BITBUCKET_URL" "" "" execute_push "gitfield-github" "GitHub" "$GITHUB_URL" "" "" + + # Regenerate metadata after each cycle to update sync_cycles + generate_canonical_meta + generate_canonical_md + generate_index_json + generate_well_known_json + generate_gitfield_readme } # ╭─────────────────────────────────────╮ @@ -241,6 +449,21 @@ run_push_cycle() { # ╰─────────────────────────────────────╮ info "Starting gitfield-sync for $REPO_NAME..." +# Parse --preserve-meta flag +while [ $# -gt 0 ]; do + case "$1" in + --preserve-meta) + PRESERVE_META=true + info "Preserve metadata flag enabled" + shift + ;; + *) + warn "Unknown argument: $1" + shift + ;; + esac +done + if [ ! -d "$REPO_PATH/.git" ]; then pushd "$REPO_PATH" >/dev/null git init @@ -249,6 +472,14 @@ if [ ! -d "$REPO_PATH/.git" ]; then popd >/dev/null fi +# Generate initial metadata +generate_canonical_meta +generate_canonical_md +generate_index_json +generate_well_known_json +generate_gitfield_readme + +# Run push cycles run_push_cycle 1 generate_gitfield_md run_push_cycle 2 @@ -257,3 +488,7 @@ run_push_cycle 3 info "✅ gitfield-sync completed successfully." info "🔗 View logs: $LOG_FILE" info "🔗 View multi-repo manifest: $GITFIELD_MD" +info "🔗 View canonical metadata: $CANONICAL_META" +info "🔗 View canonical declaration: $CANONICAL_MD" +info "🔗 View index manifest: $INDEX_JSON" +info "🔗 View well-known metadata: $WELL_KNOWN_JSON" diff --git a/bin/gitfield-sync-OLD2 b/bin/gitfield-sync-OLD2 new file mode 100755 index 0000000..d3e0499 --- /dev/null +++ b/bin/gitfield-sync-OLD2 @@ -0,0 +1,259 @@ +#!/bin/bash +set -euo pipefail +IFS=$'\n\t' + +# ╭─────────────────────────────────────╮ +# │ CONFIGURATION │ +# ╰─────────────────────────────────────╮ +REPO_PATH=$(git rev-parse --show-toplevel 2>/dev/null) || error "Not inside a Git repository" +REPO_NAME=$(basename "$REPO_PATH") +GITFIELD_DIR="$REPO_PATH/.gitfield" +LOG_FILE="$GITFIELD_DIR/pushed.log" +GITFIELD_MD="$REPO_PATH/GITFIELD.md" +TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S') +SCRIPT_VERSION="1.0" + +# URLs for each platform +GITHUB_URL="https://github.com/mrhavens/$REPO_NAME" +GITLAB_URL="https://gitlab.com/mrhavens/$REPO_NAME" +BITBUCKET_URL="https://bitbucket.org/thefoldwithin/$REPO_NAME" +FORGEJO_URL="https://remember.thefoldwithin.earth/mrhavens/$REPO_NAME" +CODEBERG_URL="https://codeberg.org/mrhavens/$REPO_NAME" +GITEA_URL="https://gitea.com/mrhavens/$REPO_NAME" +RADICLE_RID="rad:z3FEj7rF8gZw9eFksCuiN43qjzrex" +RADICLE_PEER_ID="z6Mkw5s3ppo26C7y7tGK5MD8n2GqTHS582PPpeX5Xqbu2Mpz" + +# ╭─────────────────────────────────────╮ +# │ LOGGING UTILS │ +# ╰─────────────────────────────────────╮ +info() { echo -e "\e[1;34m[INFO]\e[0m $*" >&2; } +warn() { echo -e "\e[1;33m[WARN]\e[0m $*" >&2; } +error() { echo -e "\e[1;31m[ERROR]\e[0m $*" >&2; exit 1; } + +# ╭─────────────────────────────────────╮ +# │ SCRIPT LOOKUP FUNCTION │ +# ╰─────────────────────────────────────╮ +find_script() { + local script_name=$1 + local search_paths=( + "$HOME/.local/gitfieldbin" + "$HOME/.local/bin" + "$HOME/.local/gitfield" + "$HOME/.local/bin/gitfield" + "$HOME/.local/bin/gitfieldbin" + "$REPO_PATH/bin" + ) + + for path in "${search_paths[@]}"; do + if [ -f "$path/$script_name" ]; then + if [ -x "$path/$script_name" ]; then + if [[ "$path" != "$HOME"* && "$path" != "$REPO_PATH"* ]]; then + info "Using script: \e[1;31m$path/$script_name\e[0m (outside home or repo)" + else + info "Using script: $path/$script_name" + fi + echo "$path/$script_name" + return 0 + else + warn "Found $path/$script_name but it is not executable" + fi + fi + done + error "Script $script_name not found in any search path" +} + +# ╭─────────────────────────────────────╮ +# │ INITIAL SETUP │ +# ╰─────────────────────────────────────╮ +mkdir -p "$GITFIELD_DIR" + +if [ ! -f "$LOG_FILE" ]; then + echo "# Push Log for $REPO_NAME" > "$LOG_FILE" + echo "# Generated by gitfield-sync" >> "$LOG_FILE" + echo "" >> "$LOG_FILE" +fi + +# ╭─────────────────────────────────────╮ +# │ GENERATE GITFIELD.MD │ +# ╰─────────────────────────────────────╮ +generate_gitfield_md() { + info "Generating $GITFIELD_MD..." + cat > "$GITFIELD_MD" <> "$LOG_FILE" + echo " CLI: rad inspect $rid # View project details" >> "$LOG_FILE" + echo " CLI: git ls-tree -r --name-only HEAD # View file structure" >> "$LOG_FILE" + info "Logged push to $LOG_FILE: [$timestamp] $platform: RID=$rid, Peer ID=$peer_id" + else + echo "[$timestamp] $platform: $url" >> "$LOG_FILE" + info "Logged push to $LOG_FILE: [$timestamp] $platform: $url" + fi +} + +# ╭─────────────────────────────────────╮ +# │ EXECUTE PUSH SCRIPT │ +# ╰─────────────────────────────────────╮ +execute_push() { + local script_name=$1 + local platform=$2 + local url=$3 + local rid=$4 + local peer_id=$5 + local script_path + script_path=$(find_script "$script_name") || error "Failed to find $script_name" + info "Executing $platform push with script: $script_path" + if [ -x "$script_path" ]; then + pushd "$REPO_PATH" >/dev/null + "$script_path" || warn "Execution of $script_path failed, continuing..." + log_url "$platform" "$url" "$rid" "$peer_id" + git add . || warn "Nothing to add after $script_path" + git commit -m "Post-$platform sync at $TIMESTAMP" || warn "No changes to commit after $script_path" + popd >/dev/null + else + error "Script $script_path is not executable" + fi +} + +# ╭─────────────────────────────────────╮ +# │ RECURSIVE PUSH LOOP │ +# ╰─────────────────────────────────────╮ +run_push_cycle() { + local cycle_number=$1 + info "Starting push cycle $cycle_number..." + + execute_push "gitfield-local" "Local" "" "" "" + execute_push "gitfield-radicle" "Radicle" "" "$RADICLE_RID" "$RADICLE_PEER_ID" + execute_push "gitfield-remember" "Forgejo" "$FORGEJO_URL" "" "" + execute_push "gitfield-codeberg" "Codeberg" "$CODEBERG_URL" "" "" + execute_push "gitfield-gitea" "Gitea" "$GITEA_URL" "" "" + execute_push "gitfield-gitlab" "GitLab" "$GITLAB_URL" "" "" + execute_push "gitfield-bitbucket" "Bitbucket" "$BITBUCKET_URL" "" "" + execute_push "gitfield-github" "GitHub" "$GITHUB_URL" "" "" +} + +# ╭─────────────────────────────────────╮ +# │ MAIN EXECUTION │ +# ╰─────────────────────────────────────╮ +info "Starting gitfield-sync for $REPO_NAME..." + +if [ ! -d "$REPO_PATH/.git" ]; then + pushd "$REPO_PATH" >/dev/null + git init + git add . + git commit -m "Initial commit" || warn "Nothing to commit" + popd >/dev/null +fi + +run_push_cycle 1 +generate_gitfield_md +run_push_cycle 2 +run_push_cycle 3 + +info "✅ gitfield-sync completed successfully." +info "🔗 View logs: $LOG_FILE" +info "🔗 View multi-repo manifest: $GITFIELD_MD"