Render broken symlinks & show symlinks in different colors#27
Render broken symlinks & show symlinks in different colors#27slinjhu merged 2 commits intoSmooSenseAI:mainfrom
Conversation
|
Some more background: I basically took the Happy to answer any questions or get feedback on this PR! 🙏 |
| try: | ||
| stat = entry.stat() | ||
| all_items.append( | ||
| FSItem( | ||
| name=entry.name, | ||
| size=stat.st_size, | ||
| lastModified=int(1000 * stat.st_mtime), | ||
| isDir=entry.is_dir(), | ||
| symlinkTarget=os.readlink(entry.path) if entry.is_symlink() else "", | ||
| ) | ||
| ) | ||
| ) | ||
| except OSError: | ||
| if entry.is_symlink(): | ||
| all_items.append( | ||
| FSItem( | ||
| name=entry.name, | ||
| size=0, | ||
| lastModified=0, | ||
| isDir=False, | ||
| isBrokenSymlink=True, | ||
| symlinkTarget=os.readlink(entry.path), | ||
| ) | ||
| ) | ||
| else: | ||
| logger.warning(f"Failed to stat entry: {entry.path}") |
There was a problem hiding this comment.
I think your version here is a bit too much based on the vibe-coded version I showcased in this comment.
I'd reduce the scope of the try statement to just the entry.stat() to both make intent clearer as well as don't unnecessarily catch other exceptions that shouldn't be caught.
Also, I'd personally always rather see what exceptions happened and therefore include the stack trace (either through exc_info or by using logger.exception). But that is for @slinjhu to decide 😄
| try: | |
| stat = entry.stat() | |
| all_items.append( | |
| FSItem( | |
| name=entry.name, | |
| size=stat.st_size, | |
| lastModified=int(1000 * stat.st_mtime), | |
| isDir=entry.is_dir(), | |
| symlinkTarget=os.readlink(entry.path) if entry.is_symlink() else "", | |
| ) | |
| ) | |
| ) | |
| except OSError: | |
| if entry.is_symlink(): | |
| all_items.append( | |
| FSItem( | |
| name=entry.name, | |
| size=0, | |
| lastModified=0, | |
| isDir=False, | |
| isBrokenSymlink=True, | |
| symlinkTarget=os.readlink(entry.path), | |
| ) | |
| ) | |
| else: | |
| logger.warning(f"Failed to stat entry: {entry.path}") | |
| try: | |
| stat = entry.stat() | |
| except OSError: | |
| if entry.is_symlink(): | |
| all_items.append( | |
| FSItem( | |
| name=entry.name, | |
| size=0, | |
| lastModified=0, | |
| isDir=False, | |
| isBrokenSymlink=True, | |
| symlinkTarget=os.readlink(entry.path), | |
| ) | |
| ) | |
| else: | |
| logger.exception(f"Failed to stat entry: {entry.path}") | |
| else: | |
| all_items.append( | |
| FSItem( | |
| name=entry.name, | |
| size=stat.st_size, | |
| lastModified=int(1000 * stat.st_mtime), | |
| isDir=entry.is_dir(), | |
| symlinkTarget=os.readlink(entry.path) if entry.is_symlink() else "", | |
| ) | |
| ) |
There was a problem hiding this comment.
Makes sense. In general it is better to keep try-catch scope smaller.
There was a problem hiding this comment.
Agreed, I applied the suggestion.
slinjhu
left a comment
There was a problem hiding this comment.
Thanks @nikitakrh for the great work. I wasn't anticipating broken symlink, thanks for floating up this corner case in realistic data.
@jonded94 made a suggestion to reduce scope of try-catch, and I think it makes sense and increase code readability.
Otherwise your PR looks good to me.
| ) | ||
| ) | ||
| else: | ||
| logger.warning(f"Failed to stat entry: {entry.path}") |
There was a problem hiding this comment.
Change logger.warning to logger.exception so we can see full traceback
There was a problem hiding this comment.
Changed it to exception 🙂
| try: | ||
| stat = entry.stat() | ||
| all_items.append( | ||
| FSItem( | ||
| name=entry.name, | ||
| size=stat.st_size, | ||
| lastModified=int(1000 * stat.st_mtime), | ||
| isDir=entry.is_dir(), | ||
| symlinkTarget=os.readlink(entry.path) if entry.is_symlink() else "", | ||
| ) | ||
| ) | ||
| ) | ||
| except OSError: | ||
| if entry.is_symlink(): | ||
| all_items.append( | ||
| FSItem( | ||
| name=entry.name, | ||
| size=0, | ||
| lastModified=0, | ||
| isDir=False, | ||
| isBrokenSymlink=True, | ||
| symlinkTarget=os.readlink(entry.path), | ||
| ) | ||
| ) | ||
| else: | ||
| logger.warning(f"Failed to stat entry: {entry.path}") |
There was a problem hiding this comment.
Makes sense. In general it is better to keep try-catch scope smaller.
|
Tests failing due to lack of AWS credentials. After some research I fount issue: This is a GitHub security restriction: when a PR comes from a fork (nikitakrh's When you push directly to main, the workflow runs in your own repo context and secrets work fine. |
|
Released v0.1.47 |
Closes #24
Changes
Backend (
local_fs.py,models.py):FSItemgetsisBrokenSymlinkandsymlinkTargetfields.scandirnow catchesOSErroron broken symlinks instead of crashing.isBrokenSymlink=True, working symlinks can be found viaisBrokenSymlink == False and symlinkTarget is not None.Frontend (
folderTreeSlice.ts,FolderTreeView.tsx,TreeNodeComponent.tsx,iconUtils.tsx):FileXicon (red) and red textname (→ target)with a tooltipExample:
