3ce53ed0c6c8847d87987d04c3f1846ee879d623
lrnassar
  Fri Jun 5 13:37:31 2026 -0700
Point rtsUpdate at the new authoritative .tab manifest location under htdocs/data/recTrackSets/. Chris moved the loader's .tab lookup there in 3b6659d987c so both the manifest and the per-session contents now live under one tree; rtsUpdate's find_db_for_session() needs to follow. Drops the now-unused INC_DIR constant, updates the comment, and points the "session not in manifest" error message at the new location. refs #32768

diff --git src/hg/utils/rts/rtsUpdate src/hg/utils/rts/rtsUpdate
index 39308f91e2b..e67eb8a4032 100755
--- src/hg/utils/rts/rtsUpdate
+++ src/hg/utils/rts/rtsUpdate
@@ -4,31 +4,30 @@
 # where Chris's file-based loader reads it.  No DB writes.
 # Refs #32768, #34907.
 
 import argparse
 import datetime
 import getpass
 import pathlib
 import re
 import subprocess
 import sys
 from urllib.parse import urlparse
 
 HOME = pathlib.Path.home()
 RTS_DIR = HOME / "kent/src/hg/utils/rts"
 DATA_DIR = HOME / "kent/src/hg/htdocs/data/recTrackSets"
-INC_DIR = HOME / "kent/src/hg/htdocs/inc"
 LOGFILE = HOME / ".rtsUpdate.log"
 VERBOTEN = RTS_DIR / "verboten.lst"
 
 TARGET_USER = "View"
 
 # Source host => (hgsql -h target, db).  Default source is rr (canonical curator save location).
 HOSTS = {
     "rr":   ("genome-centdb", "hgcentral"),
     "dev":  ("hgwdev",        "hgcentraltest"),
     "beta": ("hgwbeta",       "hgcentralbeta"),
 }
 
 # Session and userName must match this. Excludes anything that could be SQL- or
 # shell-special; permits the URL-encoding form ('%' and digits) used for sessions
 # whose human-readable names contain spaces (e.g. 'CNVs%20Clinical').
@@ -109,32 +108,33 @@
     out = []
     for p in pairs:
         key = p.split("=", 1)[0]
         # Drop pairs with empty or whitespace-tainted keys (corruption / stray
         # data from manual session edits — e.g. an `& hgsid=...` artifact).
         if not key or any(c.isspace() for c in key):
             continue
         if any(rx.match(key) for rx in verboten):
             continue
         out.append(p)
     return sorted(set(out))
 
 
 def find_db_for_session(session):
     """Return the assembly db for a session by scanning recTrackSets.<db>.tab.
-    Reads from htdocs/inc/ (the authoritative manifest location)."""
-    for tab in sorted(INC_DIR.glob("recTrackSets.*.tab")):
+    Reads from htdocs/data/recTrackSets/ (the authoritative manifest location
+    since 3b6659d987c)."""
+    for tab in sorted(DATA_DIR.glob("recTrackSets.*.tab")):
         m = re.match(r"recTrackSets\.([A-Za-z0-9]+)\.tab$", tab.name)
         if not m:
             continue
         db = m.group(1)
         for line in tab.read_text().splitlines():
             if line.startswith("#") or not line.strip():
                 continue
             cols = line.split("\t")
             if len(cols) >= 3 and cols[2] == session:
                 return db
     return None
 
 
 def kent_path(db, session):
     return DATA_DIR / db / session
@@ -208,31 +208,32 @@
     else:
         if not (args.src_user and args.src_session):
             die("must provide --src-url OR (--src-user AND --src-session)")
         src_user, src_session = args.src_user, args.src_session
 
     target = args.target_session
     validate_name(src_user, "src userName")
     validate_name(src_session, "src sessionName")
     validate_name(target, "target sessionName")
 
     # .tab validation: must be listed in recTrackSets.<db>.tab.  This determines
     # which assembly the file lands under and rejects typos / missing manifest rows.
     db = find_db_for_session(target)
     if db is None:
         die(f"target session {target!r} not found in any recTrackSets.<db>.tab\n"
-            f"  Add a row to ~/kent/src/hg/htdocs/inc/recTrackSets.<db>.tab first, then re-run.")
+            f"  Add a row to ~/kent/src/hg/htdocs/data/recTrackSets/recTrackSets.<db>.tab "
+            f"first, then re-run.")
     print(f"assembly resolved from recTrackSets.{db}.tab: {db}")
 
     src_host = args.src_host
     src_h, src_db = HOSTS[src_host]
     print(f"Fetching {src_user}/{src_session} from {src_host} ({src_h}:{src_db})...")
 
     contents, _, exists = fetch_session_row(src_host, src_user, src_session)
     if not exists:
         die(f"source session {src_user}/{src_session} not found on {src_host}")
     pairs = split_pairs(contents)
     print(f"  fetched {len(pairs)} cart variables ({len(contents)} bytes)")
 
     scrubbed = scrub(pairs, verboten)
     dropped = len(pairs) - len(scrubbed)
     print(f"  scrubbed: dropped {dropped} verboten/duplicate vars, kept {len(scrubbed)}")