Sfoglia il codice sorgente

Stabilize svn_git_sync messages and non-history init

cere 1 mese fa
parent
commit
ebd60e145c
1 ha cambiato i file con 76 aggiunte e 30 eliminazioni
  1. 76 30
      svn_interact/svn_git_sync

+ 76 - 30
svn_interact/svn_git_sync

@@ -144,12 +144,26 @@ link_git_to_source() {
 }
 
 stage_and_commit() {
-  local msg="$1"
-  echo "[$(elapsed) s] Staging files..."
+  local subject="${1:-}"
+  local body="${2:-}"
+  local allow_empty="${3:-0}"
+  local display="${4:-$subject}"
+  [[ -z "$subject" ]] && subject="SVN snapshot"
   git add -A
 
-  echo "[$(elapsed) s] Creating commit: $msg"
-  GIT_QUIET=1 git commit -q -m "$msg" || true
+  if (( allow_empty )); then
+    if [[ -n "$body" ]]; then
+      GIT_QUIET=1 git commit -q --allow-empty -m "$subject" -m "$body"
+    else
+      GIT_QUIET=1 git commit -q --allow-empty -m "$subject"
+    fi
+  else
+    if [[ -n "$body" ]]; then
+      GIT_QUIET=1 git commit -q -m "$subject" -m "$body"
+    else
+      GIT_QUIET=1 git commit -q -m "$subject"
+    fi
+  fi
 }
 
 # Validate history_count is numeric (default 0)
@@ -170,42 +184,74 @@ if (( history_count == 0 )); then
 fi
 
 # History mode: pull last N revisions into Git.
-head_rev="$(svn info --show-item revision 2>/dev/null || svn info | awk -F': ' '/^Revision:/ {print $2; exit}')"
-if [[ -z "$head_rev" ]]; then
-  echo "Unable to determine HEAD revision" >&2
+SRC_URL="$(svn info --show-item url 2>/dev/null || svn info | awk -F': ' '/^URL:/ {print $2; exit}')"
+if [[ -z "$SRC_URL" ]]; then
+  echo "Unable to determine SVN URL" >&2
   exit 1
 fi
-start_rev=$(( head_rev - history_count + 1 ))
-if (( start_rev < 1 )); then start_rev=1; fi
+REPO_ROOT="$(svn info --show-item repos-root-url 2>/dev/null || svn info | awk -F': ' '/^Repository Root:/ {print $2; exit}')"
 
-echo "Including last $history_count revisions (r${start_rev}..r${head_rev})..."
+mapfile -t REV_LIST < <(svn log -q -r HEAD:1 --limit "$history_count" "$SRC_URL" | awk '/^r[0-9]+/ {sub(/^r/,"",$1); print $1}' | tac)
+if (( ${#REV_LIST[@]} == 0 )); then
+  echo "No SVN revisions found for path $SRC_URL" >&2
+  exit 1
+fi
+
+start_rev="${REV_LIST[0]}"
+head_rev="${REV_LIST[-1]}"
+echo "Including last ${#REV_LIST[@]} revisions affecting this path (r${start_rev}..r${head_rev})..."
 
-STAGE_DIR="$(mktemp -d "${MIRROR_ROOT}/.svn_git_sync_stage.XXXXXX")"
+WC_DIR="$(mktemp -d "${MIRROR_ROOT}/.svn_git_sync_wc.XXXXXX")"
 mkdir -p "$DEST"
-cd "$DEST"
-init_git_repo
 
-for rev in $(seq "$start_rev" "$head_rev"); do
-  echo "[$(elapsed) s] Exporting r${rev}..."
-  rm -rf -- "$STAGE_DIR"
-  mkdir -p "$STAGE_DIR"
-  svn export --force --quiet -r "$rev" "$SRC_DIR" "$STAGE_DIR"
+sync_wc_to_dest() {
+  rsync -a --delete --exclude '.svn' --exclude '.git' "$WC_DIR"/ "$DEST"/
+  if [[ ! -e "$DEST/.gitignore" ]]; then
+    printf "*.pyc\n__pycache__/\n" > "$DEST/.gitignore"
+  fi
+}
 
-  # Sync exported snapshot into repo working tree, preserving .git and .gitignore
-  rsync -a --delete --exclude '.git' --exclude '.gitignore' "$STAGE_DIR"/ "$DEST"/
+echo "[$(elapsed) s] Checking out r${start_rev}..."
+svn checkout -q -r "$start_rev" "$SRC_URL" "$WC_DIR"
 
-  # Ensure ignores persist
-  if [[ ! -e .gitignore ]]; then
-    printf "*.pyc\n__pycache__/\n" > .gitignore
-  fi
+sync_wc_to_dest
 
-  if [[ "$rev" -eq "$start_rev" ]]; then
-    stage_and_commit "Import SVN r${rev}"
-  else
-    stage_and_commit "Update to SVN r${rev}"
+cd "$DEST"
+init_git_repo
+build_commit_msg() {
+  local rev="$1"
+  local svn_log author msg_body
+  svn_log="$(svn log -r "$rev" -l 1 "$SRC_URL")"
+  author="$(printf "%s\n" "$svn_log" | awk 'NR==2{split($0,a,"|"); gsub(/^ +| +$/,"",a[2]); print a[2]}')"
+  msg_body="$(printf "%s\n" "$svn_log" | sed '1,2d;/^---/,$d')"
+  if { [[ -z "$author" ]] || [[ -z "$msg_body" ]]; } && [[ -n "$REPO_ROOT" ]]; then
+    svn_log="$(svn log -r "$rev" -l 1 "$REPO_ROOT" 2>/dev/null || true)"
+    author="$(printf "%s\n" "$svn_log" | awk 'NR==2{split($0,a,"|"); gsub(/^ +| +$/,"",a[2]); print a[2]}')"
+    msg_body="$(printf "%s\n" "$svn_log" | sed '1,2d;/^---/,$d')"
   fi
-done
+  msg_body="$(printf "%s" "$msg_body" | perl -0777 -pe 's/\A\s+//; s/\s+\z//; s/\n{2,}/\n\n/g')"
+  COMMIT_BODY="$msg_body"
+  COMMIT_BODY_FIRST="$(printf "%s" "$msg_body" | sed -n '1p')"
+  COMMIT_SUBJECT="SVN r${rev}"
+  [[ -n "$author" ]] && COMMIT_SUBJECT+=" by $author"
+  COMMIT_PROGRESS="$COMMIT_SUBJECT"
+  [[ -n "$COMMIT_BODY_FIRST" ]] && COMMIT_PROGRESS+=" — $COMMIT_BODY_FIRST"
+}
+
+build_commit_msg "$start_rev"
+echo "[$(elapsed) s] Preparing commit: $COMMIT_PROGRESS"
+stage_and_commit "$COMMIT_SUBJECT" "$COMMIT_BODY" 0 "$COMMIT_PROGRESS"
+
+if (( ${#REV_LIST[@]} > 1 )); then
+  for rev in "${REV_LIST[@]:1}"; do
+    svn update -q -r "$rev" "$WC_DIR"
+    sync_wc_to_dest
+    build_commit_msg "$rev"
+    echo "[$(elapsed) s] Preparing commit: $COMMIT_PROGRESS"
+    stage_and_commit "$COMMIT_SUBJECT" "$COMMIT_BODY" 1 "$COMMIT_PROGRESS"
+  done
+fi
 
-rm -rf -- "$STAGE_DIR"
+rm -rf -- "$WC_DIR"
 
 link_git_to_source