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

[ospaths] fix #8491: XDG_CONFIG_HOME was being ignored due to #8681 + private normalizePathEnd #8680

Merged

Conversation

timotheecour
Copy link
Member

@timotheecour timotheecour commented Aug 18, 2018

[1] here's the bug: XDG_CONFIG_HOME is ignored:
XDG_CONFIG_HOME=FOO rnim bugs/compiler/t20_XDG_CONFIG_HOME.nim
nim c --nimcache:/tmp/nim//nimcache/ -o:/tmp/nim//app -r bugs/compiler/t20_XDG_CONFIG_HOME.nim
getConfigDir()=/Users/timothee/.config/

bugs/compiler/t20_XDG_CONFIG_HOME.nim:

import ospaths
echo "getConfigDir()=", getConfigDir()

@timotheecour timotheecour changed the title [ospaths] fix #8491: XDG_CONFIG_HOME was being ignored due to a bug in nim:when; add normalizePathEnd [ospaths] fix #8491: XDG_CONFIG_HOME was being ignored due to #8681; add normalizePathEnd Aug 18, 2018
@timotheecour
Copy link
Member Author

/cc @Varriount I'd love to get this merged ASAP as it fixes an annoying bug; thanks!

@Araq
Copy link
Member

Araq commented Aug 18, 2018

  • What is the remaining bug? (Yes, I can guess it, but you didn't say.)
  • Why do you rewrite working code in your preferred style?
  • Why do you conflate a bugfix with a new feature? There is no reason normalizePathEnd cannot stay private.
  • Only the path using XDG_CONFIG_HOME has the bug, but your code unconditionally calls normalizePathEnd which probably allocates.
  • The better design seems to me to make getConfigDir not return a string that ends in /. People should write getConfigDir() / "x", not getConfigDir() & x.

@Araq
Copy link
Member

Araq commented Aug 18, 2018

/cc @Varriount I'd love to get this merged ASAP as it fixes an annoying bug; thanks!

I can see what you did here and I'm mildly offended. ;-)

@timotheecour
Copy link
Member Author

What is the remaining bug? (Yes, I can guess it, but you didn't say.)

well i mentioned "#8491 XDG_CONFIG_HOME was being happily ignored"; but ok, I just added test case to show the bug in top-level message

Why do you rewrite working code in your preferred style?

the original code had style issues, eg using & "/.config/" instead of the idiomatic / ; furthermore it had other issues (eg ending up with multiple trailing /) beyond the bug being fixed.

But ok, I just added a commit to remove some of the excessive UFCS.

Why do you conflate a bugfix with a new feature? There is no reason normalizePathEnd cannot stay private.

ok; made it private for now.

Only the path using XDG_CONFIG_HOME has the bug, but your code unconditionally calls normalizePathEnd which probably allocates.

well the other issue was that old code could end up with double trailing DirSep (in both windows and posix); after the PR, this is fixed.
Wouldn't & "\\" also allocate? in any case, being correct should come before being fast; and we can always optimize out un-necessary allocations in normalizePathEnd later (it'll be just in 1 function instead of spread out everywhere)

The better design seems to me to make getConfigDir not return a string that ends in /.

It's right there in the documentation: An OS-dependent trailing slash is always present at the end of the returned string
That would be a breaking change, which I don't wanna do in this PR.

People should write getConfigDir() / "x", not getConfigDir() & x.

I agree with that statement.
However, it's not incompatible with getConfigDir ending in / : once joinPath gets fixed to avoid inserting double / on joinPath("foo/", "bar"), this won't be a problem; Note that my other pending PR #8351 does fix that.

I can see what you did here and I'm mildly offended. ;-)

not sure I follow; keep in mind this is all volunteer work. Do you want me to CC you in every PR? I could do that; I assumed you may not want to review every single PR, which doesn't scale, and I'm assuming everyone with commit rights is expected to do a good review.

@timotheecour timotheecour changed the title [ospaths] fix #8491: XDG_CONFIG_HOME was being ignored due to #8681; add normalizePathEnd [ospaths] fix #8491: XDG_CONFIG_HOME was being ignored due to #8681 Aug 18, 2018
Copy link
Member

@Araq Araq left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Take a look at my alternative implementation please.

else:
# still need to end with `DirSep` for root
if result.len == 0:
result = "" & DirSep
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$DirSep is better style.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

result = "" & DirSep
else:
when doslikeFileSystem:
if result[^1] == ':':
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think more correct would be this check if result.len == 2 and result[1] == ':'

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -449,6 +449,23 @@ proc isAbsolute*(path: string): bool {.rtl, noSideEffect, extern: "nos$1".} =
elif defined(posix):
result = path[0] == '/'

proc normalizePathEnd(path:string, trailingSep = false): string =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, space after colon.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

## Returns ``path`` with guaranteed 0 or 1 trailing separator, depending on
## ``trailingSep``, and taking care of special case of root paths.
if path.len == 0: return ""
result = strip(path, leading = false, trailing = true, {DirSep, AltSep})
Copy link
Member

@Araq Araq Aug 18, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is still "meh". How about this:

proc normalizePathEnd(path: var string, trailingSep = false) =
  var i = path.len
  while i >= 1 and path[i-1] in {DirSep, AltSep}: dec(i)
  if trailingSep and i == path.len:
    path.add DirSep
  else:
    path.setLen(i+ord(trailingSep))

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this had a few bugs:
normalizePathEnd should only normalize path end, and should not change whether a path is absolute or relative; the version above could turn "/" into "" or vice versa.

I added test cases to make sure we prevent future regressions) but I reimplemented starting from your version and trying hard to minimize branching.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not so much about minimzing branching, it's about avoiding stdlib procs that never quite do the right thing and you are left with the hairy special cases anyway.

@Araq
Copy link
Member

Araq commented Aug 18, 2018

It's right there in the documentation: An OS-dependent trailing slash is always present at the end of the returned string
That would be a breaking change, which I don't wanna do in this PR.

Ok, fair enough, the other get*Dir() procs also seem to produce trailing slashes... (Bah!)

@timotheecour
Copy link
Member Author

thx, will fix all these this weekend

@dom96
Copy link
Contributor

dom96 commented Aug 18, 2018

Wouldn't & "\" also allocate? in any case, being correct should come before being fast

As far as correctness is concerned, isn't a path like C:\foo\\file.txt\\ correct on Windows? Similar for /home/dom//file.txt//?

By "correct" I mean "it works, the OS doesn't care that the slashes are doubled".

@Araq
Copy link
Member

Araq commented Aug 18, 2018

By "correct" I mean "it works, the OS doesn't care that the slashes are doubled".

Pretty sure this is the case, however allowing these makes path comparisons much trickier to implement correctly.

@timotheecour
Copy link
Member Author

timotheecour commented Aug 23, 2018

By "correct" I mean "it works, the OS doesn't care that the slashes are doubled".

Pretty sure this is the case, however allowing these makes path comparisons much trickier to implement correctly.

and there are existing bugs related to that: eg just filed #8734 (yes, these will be eventually fixed). But Nim should not introduce new double slashes (in getConfigDir, before this PR, it could introduce double slashes even though XDG_CONFIG_HOME didn't contain double slashes)

@timotheecour timotheecour force-pushed the pr_fix_8491_XDG_CONFIG_HOME_ignored branch from b79ac01 to 721cdf8 Compare August 23, 2018 22:46
@timotheecour timotheecour changed the title [ospaths] fix #8491: XDG_CONFIG_HOME was being ignored due to #8681 [ospaths] fix #8491: XDG_CONFIG_HOME was being ignored due to #8681 + private normalizePathEnd Aug 23, 2018
@timotheecour timotheecour force-pushed the pr_fix_8491_XDG_CONFIG_HOME_ignored branch from 721cdf8 to a2f9c47 Compare August 23, 2018 22:56
@timotheecour
Copy link
Member Author

@Araq PTAL

@timotheecour timotheecour force-pushed the pr_fix_8491_XDG_CONFIG_HOME_ignored branch 2 times, most recently from 23d2272 to d3ba8ae Compare August 24, 2018 09:19
@timotheecour timotheecour reopened this Aug 24, 2018
sure path endings are normalized with 0 or 1 trailing sep, taking care
of edge cases
@timotheecour timotheecour force-pushed the pr_fix_8491_XDG_CONFIG_HOME_ignored branch from d3ba8ae to 90d3611 Compare August 24, 2018 20:35
@Araq
Copy link
Member

Araq commented Aug 25, 2018

'normalizePathEnd' is still the wrong idea.

cmpPaths("C://foo/bar", r"C:\foo\bar") --> should be equal
probably it's better to push the complexity into the cmpPaths logic instead of trying to "normalize" every single path in the APIs (which would also be slower).

@timotheecour
Copy link
Member Author

timotheecour commented Aug 25, 2018

cmpPaths("C://foo/bar", r"C:\foo\bar") --> should be equal

I just filed #8780 for that

yes, cmpPaths should do the right thing (and #8780 will be fixed eventually); not arguing with that.

What I'm arguing for is that our API's should not introduce new style violation (by that I mean duplicated DirSep):
before this PR, getConfigDir can return a style violation even though XDG_CONFIG_HOME doesn't have style violation
style issues affect both Nim API's (see #8734 and #8780 etc) and non-Nim APIs (over which we have no control)

As shown in this PR, getting the details right is tricky, so that's why this PR is needed so the tricky work is handled in just 1 place.
There's a few other places where normalizePathEnd can be used; note that, in its latest form, it wont' have any practical impact on runtime performance.

@Araq Araq merged commit b4edfa6 into nim-lang:devel Aug 26, 2018
@timotheecour
Copy link
Member Author

thanks

@timotheecour timotheecour deleted the pr_fix_8491_XDG_CONFIG_HOME_ignored branch August 26, 2018 22:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

XDG_CONFIG_DIR env var ignored (prevents disabling ~/.config/nim.cfg for 1 process)
3 participants