[PATCH 3/7] drecurse: simplify the logic and only normpath() once

0 views
Skip to first unread message

Rob Browning

unread,
Mar 15, 2026, 6:25:34 PM (9 days ago) Mar 15
to bup-...@googlegroups.com
Flatten the logic via more loop continue short-circuting, and remember
the normalized path if we compute it, so we can use it later when
needed. Lift checks like the "isn't a directory" check so that we
stop sooner in that case. Drop the separate "is symlink" test since
it's superseded by the directory check.

Signed-off-by: Rob Browning <r...@defaultvalue.org>
Tested-by: Rob Browning <r...@defaultvalue.org>
---
lib/bup/drecurse.py | 76 +++++++++++++++++++++++----------------------
1 file changed, 39 insertions(+), 37 deletions(-)

diff --git a/lib/bup/drecurse.py b/lib/bup/drecurse.py
index 215c7132..800add4e 100644
--- a/lib/bup/drecurse.py
+++ b/lib/bup/drecurse.py
@@ -43,34 +43,39 @@ def _recursive_dirlist(prepend, xdev, bup_dir=None,
xdev_exceptions=frozenset()):
for (name,pst) in _dirlist():
path = prepend + name
+ npath = None
if excluded_paths:
- if os.path.normpath(path) in excluded_paths:
+ npath = os.path.normpath(path)
+ if npath in excluded_paths:
debug1('Skipping %r: excluded.\n' % path_msg(path))
continue
if exclude_rxs and should_rx_exclude_path(path, exclude_rxs):
continue
- if name.endswith(b'/'):
- if bup_dir is not None:
- if os.path.normpath(path) == bup_dir:
- debug1('Skipping BUP_DIR.\n')
- continue
- if xdev is not None and pst.st_dev != xdev \
- and path not in xdev_exceptions:
- debug1('Skipping contents of %r: different filesystem.\n'
- % path_msg(path))
- else:
- try:
- with finalized_fd(name) as fd:
- os.fchdir(fd)
- except OSError as e:
- add_error('%s: %s' % (prepend, e))
- else:
- yield from _recursive_dirlist(prepend=prepend+name, xdev=xdev,
- bup_dir=bup_dir,
- excluded_paths=excluded_paths,
- exclude_rxs=exclude_rxs,
- xdev_exceptions=xdev_exceptions)
- os.chdir(b'..')
+ if name[-1] != b'/'[0]:
+ yield path, pst
+ continue
+ if bup_dir is not None and (npath or os.path.normpath(path)) == bup_dir:
+ debug1('Skipping BUP_DIR.\n')
+ continue
+ if xdev is not None and pst.st_dev != xdev \
+ and path not in xdev_exceptions:
+ debug1('Skipping contents of %r: different filesystem.\n'
+ % path_msg(path))
+ yield path, pst
+ continue
+ try:
+ with finalized_fd(name) as fd:
+ os.fchdir(fd)
+ except OSError as e:
+ add_error('%s: %s' % (prepend, e))
+ yield path, pst
+ continue
+ yield from _recursive_dirlist(prepend=path, xdev=xdev,
+ bup_dir=bup_dir,
+ excluded_paths=excluded_paths,
+ exclude_rxs=exclude_rxs,
+ xdev_exceptions=xdev_exceptions)
+ os.chdir(b'..')
yield (path, pst)


@@ -84,12 +89,12 @@ def recursive_dirlist(paths, xdev, bup_dir=None,
for path in paths:
try:
pst = xstat.lstat(path)
- if stat.S_ISLNK(pst.st_mode):
- yield (path, pst)
- continue
except OSError as e:
add_error('recursive_dirlist: %s' % e)
continue
+ if not stat.S_ISDIR(pst.st_mode):
+ yield path, pst
+ continue
try:
opened_pfile = finalized_fd(path)
except OSError as e:
@@ -97,17 +102,14 @@ def recursive_dirlist(paths, xdev, bup_dir=None,
continue
with opened_pfile as pfile:
xdev = pst.st_dev if xdev else None
- if stat.S_ISDIR(pst.st_mode):
- os.fchdir(pfile)
- prepend = os.path.join(path, b'')
- yield from _recursive_dirlist(prepend=prepend, xdev=xdev,
- bup_dir=bup_dir,
- excluded_paths=excluded_paths,
- exclude_rxs=exclude_rxs,
- xdev_exceptions=xdev_exceptions)
- os.fchdir(startdir)
- else:
- prepend = path
+ os.fchdir(pfile)
+ prepend = os.path.join(path, b'')
+ yield from _recursive_dirlist(prepend=prepend, xdev=xdev,
+ bup_dir=bup_dir,
+ excluded_paths=excluded_paths,
+ exclude_rxs=exclude_rxs,
+ xdev_exceptions=xdev_exceptions)
+ os.fchdir(startdir)
yield (prepend,pst)
finally:
os.fchdir(startdir)
--
2.47.3

Reply all
Reply to author
Forward
0 new messages