Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recommended strategy for dealing with broken symlinks? #231

Closed
jdblischak opened this issue Oct 29, 2019 · 8 comments
Closed

Recommended strategy for dealing with broken symlinks? #231

jdblischak opened this issue Oct 29, 2019 · 8 comments
Labels
feature a feature request or enhancement

Comments

@jdblischak
Copy link
Contributor

Is there a recommended strategy for finding and gracefully handling broken symlinks? My package functions run path_real() on the project files to resolve any potential symlinks, and I had a user report a bug where a broken symlink broke everything. Is there a better option than always having to check with is_link()/link_path()/file_exists()?

Here is a reprex to demonstrate the issue:

packageVersion("fs")
#> [1] '1.3.1.9000'
library(fs)
d <- file_temp()
dir_create(d)
non_existent <- path(d, "non-existent")
broken_link <- path(d, "broken-link")
link_create(non_existent, broken_link)
file_exists(non_existent)
#> /tmp/RtmpeYDu12/file25f817354d04/non-existent 
#>                                         FALSE
link_exists(broken_link)
#> /tmp/RtmpeYDu12/file25f817354d04/broken-link 
#>                                         TRUE
link_path(broken_link)
#> /tmp/RtmpeYDu12/file25f817354d04/non-existent
file_exists(link_path(broken_link))
#> /tmp/RtmpeYDu12/file25f817354d04/non-existent 
#>                                         FALSE
f <- dir_ls(path = d)
path_real(f)
#> Error: [ENOENT] Failed to realize '/tmp/RtmpeYDu12/file25f817354d04/broken-link': no such file or directory
# Find any broken links
any(!file_exists(link_path(f[is_link(f)])))
#> [1] TRUE

Created on 2019-10-29 by the reprex package (v0.3.0.9000)

Session info
sessioninfo::session_info()
#> ─ Session info ──────────────────────────────────────────────────────────
#>  setting  value                       
#>  version  R version 3.6.1 (2019-07-05)
#>  os       Ubuntu 18.04.3 LTS          
#>  system   x86_64, linux-gnu           
#>  ui       X11                         
#>  language (EN)                        
#>  collate  en_US.UTF-8                 
#>  ctype    en_US.UTF-8                 
#>  tz       America/New_York            
#>  date     2019-10-29                  
#> 
#> ─ Packages ──────────────────────────────────────────────────────────────
#>  package     * version    date       lib source                   
#>  assertthat    0.2.1      2019-03-21 [3] CRAN (R 3.5.3)           
#>  cli           1.1.0      2019-03-19 [3] CRAN (R 3.5.3)           
#>  crayon        1.3.4      2017-09-16 [3] CRAN (R 3.5.0)           
#>  digest        0.6.22     2019-10-21 [3] CRAN (R 3.6.1)           
#>  evaluate      0.14       2019-05-28 [3] CRAN (R 3.6.0)           
#>  fs          * 1.3.1.9000 2019-10-28 [1] Github (r-lib/fs@a292266)
#>  highr         0.8        2019-03-20 [3] CRAN (R 3.5.3)           
#>  htmltools     0.4.0      2019-10-04 [3] CRAN (R 3.6.1)           
#>  knitr         1.25       2019-09-18 [3] CRAN (R 3.6.1)           
#>  magrittr      1.5        2014-11-22 [3] CRAN (R 3.5.0)           
#>  Rcpp          1.0.2      2019-07-25 [3] CRAN (R 3.6.1)           
#>  reprex        0.3.0.9000 2019-07-19 [1] local                    
#>  rlang         0.4.1      2019-10-24 [3] CRAN (R 3.6.1)           
#>  rmarkdown     1.15       2019-08-21 [1] CRAN (R 3.6.1)           
#>  sessioninfo   1.1.1      2018-11-05 [3] CRAN (R 3.5.1)           
#>  stringi       1.4.3      2019-03-12 [3] CRAN (R 3.5.3)           
#>  stringr       1.4.0      2019-02-10 [3] CRAN (R 3.5.2)           
#>  withr         2.1.2      2018-03-15 [3] CRAN (R 3.5.0)           
#>  xfun          0.10       2019-10-01 [3] CRAN (R 3.6.1)           
#>  yaml          2.2.0      2018-07-25 [3] CRAN (R 3.5.1)           
#> 
#> [1] /home/jdb-work/R/x86_64-pc-linux-gnu-library/3.6
#> [2] /usr/local/lib/R/site-library
#> [3] /usr/lib/R/site-library
#> [4] /usr/lib/R/library
@jimhester
Copy link
Member

Maybe link_exists() should do the equivalent of file_exists(link_path()), I am sure...

@jdblischak
Copy link
Contributor Author

Maybe link_exists() should do the equivalent of file_exists(link_path()), I am sure...

They are slightly different, ie is there a link vs does the link point to an existing file.

I was thinking of a change to path_real(). In the above example, it could return the path /tmp/RtmpeYDu12/file25f817354d04/non-existent instead of throwing an error. Maybe this behavior could be controlled by an argument?

@jimhester
Copy link
Member

I think path_real() should fail if the file doesn't exist, if the file doesn't exist there is no real path.

@jdblischak
Copy link
Contributor Author

But what about Issue #144, where you added the ability to resolve the symlink even if the destination file doesn't exist?

Basically, I need a function that will resolve any potential symlinks in a file path, and will not complain if anything is missing. If possible I'd prefer an fs solution since that will be much faster than any recursive R function that I write to handle resolving symlinks.

@jimhester
Copy link
Member

Ok I forgot about that, your proposal makes sense then

@jdblischak
Copy link
Contributor Author

I recently got bit by this again. Would it be possible to add a flag to path_real() that doesn't require the target file to exist? Something like the following behavior:

> fs::path_real("broken-symlink", error = TRUE)
Error: [ENOENT] Failed to realize 'broken-symlink': no such file or directory
> fs::path_real("broken-symlink", error = FALSE)
[1] "broken-symlink"

@jimhester jimhester added the feature a feature request or enhancement label Apr 3, 2020
@jimhester
Copy link
Member

I think making path_real() do anything but go to the real file was a mistake. If you try to use path_real() on a file that does not exist it should fail.

jimhester added a commit that referenced this issue Apr 23, 2020
This reverts commit 7e7df34.

Allowing realization of paths which do not actually exist is complex and
resulted in a number of subsequent issues.
#221, #231
@jdblischak
Copy link
Contributor Author

xref: workflowr/workflowr#204

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature a feature request or enhancement
Projects
None yet
Development

No branches or pull requests

2 participants