6b237159a15cc8957bc40b802ebfe1116e06b9e7 hiram Fri Aug 21 15:17:28 2026 -0700 quite output on the git source tree update refs #31811 diff --git src/hg/utils/otto/userRequests/ottoLib.py src/hg/utils/otto/userRequests/ottoLib.py index a36a6dcda8a..edf3203c7bf 100644 --- src/hg/utils/otto/userRequests/ottoLib.py +++ src/hg/utils/otto/userRequests/ottoLib.py @@ -53,69 +53,86 @@ try: fcntl.flock(fh, fcntl.LOCK_EX | fcntl.LOCK_NB) except BlockingIOError: if exitOnLocked: sys.exit(0) return None fh.seek(0) fh.truncate() fh.write("%d\n" % os.getpid()) fh.flush() return fh ### FYI: can also see the locking process via: lsof def gitPullKentTree(): - """Run 'git -C pull' so make commands run against an - up-to-date checkout (mirrors the first thing chainNetTrackDb.pl - does after sanity-checking $kentTree). Returns True on success, - False otherwise (with the error printed to stderr). Untracked - files such as the regenerated tsv.otto are tolerated; conflicting - local edits will cause 'git pull' to fail, which is what we want - -- we don't want to silently run makes against a dirty tree. - The "Already up to date." case is suppressed to keep cron output - quiet; any other pull output is surfaced to stderr.""" + """Run 'git -C fetch' + 'reset --hard origin/master' so + make commands run against an up-to-date checkout (mirrors the first + thing chainNetTrackDb.pl does after sanity-checking $kentTree). + Returns True on success, False otherwise (with the error printed to + stderr). Untracked files such as the regenerated tsv.otto are + tolerated; conflicting local edits will cause the reset to still + succeed (it's a hard reset), which is fine here -- the point is a + clean, current tree, not preserving local changes. + 'reset --hard' prints a "HEAD is now at ..." status line on every + successful run, whether or not anything actually moved, so that + line is not useful for deciding what to report. Instead we compare + HEAD before and after: silent when nothing changed, one summary + line to stderr when the tree actually advanced.""" if not os.path.isdir(os.path.join(kentTree, ".git")): print("ERROR: not a git working tree: %s" % kentTree, file=sys.stderr) return False + beforeResult = subprocess.run( + ["git", "-C", kentTree, "rev-parse", "HEAD"], + capture_output=True, + text=True, + ) + beforeSha = beforeResult.stdout.strip() if beforeResult.returncode == 0 else None # Fetch updates from origin result = subprocess.run( ["git", "-C", kentTree, "fetch", "--prune", "origin"], capture_output=True, text=True, ) if result.returncode != 0: print("ERROR: 'git fetch' failed in %s:\n%s%s" % (kentTree, result.stdout, result.stderr), file=sys.stderr) return False # Hard reset working tree to match origin/master result = subprocess.run( ["git", "-C", kentTree, "reset", "--hard", "origin/master"], capture_output=True, text=True, ) if result.returncode != 0: print("ERROR: 'git reset --hard' failed in %s:\n%s%s" % (kentTree, result.stdout, result.stderr), file=sys.stderr) return False - out = result.stdout.strip() - if out and out != "Already up to date.": - print("# git pull in %s:\n%s" % (kentTree, out), file=sys.stderr) + afterResult = subprocess.run( + ["git", "-C", kentTree, "rev-parse", "HEAD"], + capture_output=True, + text=True, + ) + afterSha = afterResult.stdout.strip() if afterResult.returncode == 0 else None + if afterSha and afterSha != beforeSha: + print("# kent tree in %s updated: %s -> %s" + % (kentTree, (beforeSha or "?")[:12], afterSha[:12]), + file=sys.stderr) return True def hgsql(query, db="hgcentral"): """Run hgsql -N -B and return rows as list of tuples (tab-split).""" out = subprocess.run( ["/cluster/bin/x86_64/hgsql", '-h', 'genome-centdb', "-N", "-B", "-e", query, db], check=True, capture_output=True, text=True, ).stdout return [tuple(line.split("\t")) for line in out.splitlines() if line] def loadDbDbClades(): """Read dbDb.name.clade.tsv -> {dbName: clade}.""" result = {} with open(cladeTsv) as fh: