Tests are launched with subprocess.run(..., cwd=TOOLDIR) so the
subprocess's argv[0] resolves against TOOLDIR, not the runner's
invocation cwd. A user-supplied --rsync-bin=../foo/rsync therefore
worked when invoked from inside TOOLDIR but silently failed (or
ENOENT'd inside individual tests) when invoked from a sibling
directory.
Fix: absolutize rsync_bin via os.path.abspath() at parse time, before
it propagates into build_rsync_cmd()/RSYNC. abspath() captures
os.getcwd() now, which is the operator's invocation cwd -- exactly
what the --rsync-bin=../path form expresses.
Regression check:
cd /tmp/somewhere-else
ln -s /path/to/rsync ./alt/rsync
python3 /path/to/rsync-git/runtests.py \
--rsync-bin=./alt/rsync \
--srcdir=/path/to/rsync-git --tooldir=/path/to/rsync-git \
00-hello
Before this commit the test failed at subprocess time with the relative
path being looked up under TOOLDIR; after, it passes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
if not srcdir or srcdir == '.':
srcdir = tooldir
rsync_bin = args.rsync_bin or os.environ.get('rsync_bin') or os.path.join(tooldir, 'rsync')
+ # Absolutize: tests run with subprocess(cwd=TOOLDIR) below, so a relative
+ # argv[0] would re-resolve against TOOLDIR rather than the runner's
+ # invocation cwd, breaking --rsync-bin=../foo/rsync forms. abspath()
+ # captures os.getcwd() now, which is what the operator intended.
+ if rsync_bin and not os.path.isabs(rsync_bin):
+ rsync_bin = os.path.abspath(rsync_bin)
suitedir = os.path.join(srcdir, 'testsuite')
scratchbase = os.path.join(os.environ.get('scratchbase', tooldir), 'testtmp')