-
Notifications
You must be signed in to change notification settings - Fork 468
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
deconstructPathRelativeToSWD #307
deconstructPathRelativeToSWD #307
Conversation
…onstructPathRelativeToSWD that finds the absolute path to a given path name relative to a specified working directory (swd).
/// 3) If swd is an empty string, then the path is evaluated as normal | ||
/// in a shell. | ||
static void deconstructPathRelativeToSWD(const std::string& swd, | ||
const std::string& path, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these tabs? 😱
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops. Yes. Many of them.
Cool -- the build failed in 8 seconds due to Chris's hard core tab detector (see above). The message was: |
Do you know how to fix the tab problem, Carmichael? |
Nope (by the way, |
See this part of the CONTRIBUTING.md. Maybe that section could be named differently, like "Do not use tabs for indenting; use 4 spaces". |
@sherm1 the CONTRIBUTING.md right now gives instructions for using spaces in the future, but doesn't give instructions for how to replace tabs after the fact. |
Depends on the editor. In Visual Studio you can use Edit->Advanced->Untabify, or do it with Find & Replace with regular expressions on, using Then after the tabs are gone, commit the changes, and then push to your deconstructPathRelativeToSWD branch again. GitHub will notice the change to this PR and new builds will get kicked off. |
@sherm1 I'm going to create a PR for CONTRIBUTING.md based on what you just said. |
// Then add a path seprator if needed. | ||
String swdcleaned = String::trimWhiteSpace(swd).replaceAllChar('\\', '/'); | ||
if (!swdcleaned.empty() && swdcleaned[swdcleaned.size() - 1] != getPathSeparatorChar()) | ||
swdcleaned += getPathSeparatorChar(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you want to use getPathSeparatorChar()
here, because that will return \
(backslash) on Windows, but you just turned all the slashes into forward slashes temporarily. So the last character won't ever match a backslash.
…tPathRelativeToSWD.
/// evaluates the absolute path of a given path relative to the swd and | ||
/// returns the directory, fileName, and extension of the final absolute | ||
/// path. In general, some rules followed are as follows | ||
/// 1) If a full absolute path is given by path, swd is not used. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The term "full absolute path" may be confusing. Perhaps just say "absolute path"? Once the isAbsolute
boolean is renamed to something like isSearchable
, "absolute path" won't be ambiguous anymore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't sure if "absolute path" becomes ambiguous after the boolean is renamed. To me, ./blah
might still be considered an absolute path, but c:\blah\
would be the full path (I also considered just saying "full path").
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah okay. Maybe say "full path" and define what that means, with an example?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think "absolute path" is a good term but it needs to be defined. How about something like "by absolute path we mean a root-relative path name, and on Windows it will begin with an explicit drive letter." The term "full absolute path" doesn't have a well known meaning anyway so would also require a definition.
const std::string cwd = Pathname::getCurrentWorkingDirectory(); | ||
std::string cwd_nodrive = cwd; cwd_nodrive.erase(0,3); | ||
const std::string cwdX = Pathname::getCurrentWorkingDirectory("x"); | ||
const std::string cwdY = Pathname::getCurrentWorkingDirectory("y"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd be nice if we could somehow simulate interesting values for these cwd's. I presume their values are probably x:\
and y:\
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. I'm open to any ideas here. Even bringing in drives is causing issues with not-Windows platforms (see the fail on the last test), and any suggestions there would be nice. Things to think about:
- What do we even want a non-Windows machine to return if a path has a drive letter?
- How to do tests where we might/would expect different answers on different platforms?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- What do we even want a non-Windows machine to return if a path has a drive letter?
So I just checked, and on linux I can create a directory like /home/chris/C:/hello
. So I think a drive letter on windows is treated just like a directory name, since that's possible (though, why would someone??). That is, on non-windows, treat C:/arbitrary/path
as a relative path, just as you'd treat hello/world
.
- How to do tests where we might/would expect different answers on different platforms?
Maybe separate the tests by platform?
#ifdef _WIN32
windows path tests
#else
other path tests
#endif
See this code example.
If we wanted to account for the potential for people to cross-compile simbody (compile on windows for release on unix), then stuff gets really complicated.
General comment: This routine is more complicated than I was imagining. I thought the strategy was going to be the following: Give swd and pathname:
Maybe that's what it is doing now but mixed into one method? Anyway, I think you want to start with a call to I believe that will cause a blank swd to be expanded to the current working directory (which is what you want it to do). (That needs checking to make sure.) Is there any reason you can't use that method? |
I would like to see a less confusing name for this method; let's not continue in the tradition of bad names that I started when I named |
I think you're right that most of these could go away with I also think this could reduce any calls to the system to calling |
That's a good idea, although it probably doesn't have to be treated as a special case as long as it works -- people shouldn't be calling this method with a blank swd normally! But if you want to do that, you should use |
…y. Updated documentation. Split test cases into Windows vs. not-Windows and updated what answers should be returned. Fixed Windows drive bug when swd was a relative path and path provided a drive. The path drive is now correctly used rather than the drive of the cwd.
Another thought about what this function should do: Previously, |
I like that idea -- seems much cleaner. The only reason why not to do it would be if deconstructing has to get done anyway in order to construct the absolute path name, or if it extra cheap to do them both at the same time for some reason. |
Well the way to make the canoncicalized path name is to deconstruct it then put it back together. I suppose that means it should be left as is (i.e. returning directory, fileName, and ext separately) or else you'd have to "deconstruct" again. |
… tests to prevent cases where tests could pass when they shouldn't.
@sherm1, ready to be looked at again. |
/// an absolute path (i.e. "C:/file.ext", "C:file.ext", "./file.ext", "/file.ext") | ||
/// we change the swd to reflect the absolute path (e.g. "./file.ext" may change | ||
/// to "/cwd/file.ext" or "C:/cwdOnC/file.ext"). | ||
/// 2) If path is a root-relative path name (and on Windows this includes a drive) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think (2) actually is the first rule applied. If so should come first in this list.
Done reviewing -- looks great, Carmichael. Ready except for the few minor comments above. |
…o process some paths. also rearrange some cases to call deconstructPathname() earlier for some cases.
Fixed the "//" problems. Also chose to do some rearranging of the logic to move some things that definitely could be called by "deconstructPathname()" earlier. It lengthens the code a little, so let me know if the logic is easier to follow. If not, the logic can be reverted if it's not worth it. I'm also considering that a bit of code at the end could be removed by just calling on "deconstructPathname()" after figuring out how the paths are combined. Do you think it's worth it to remove some of that copied code? |
Yes, definitely. In fact there are several cases where you can get rid of a bunch of code by using |
Oops -- never mind my last comment. I forgot you need the individual segments not just the absolute path. |
// Check if pathcleaned is a root-relative path. For Windows, this means | ||
// that path gave a drive. For not-Windows, no drives will exist. | ||
if (pathcleaned.substr(0, 1) == "/") { | ||
if (getCurrentDriveLetter().empty() || !pathdrive.empty()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't make sense to me. The current drive would only be empty on a non-Windows system but then why would pathdrive not be empty?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently I think there is no directly platform-dependent code in this method. Instead everything is hidden by platform-dependent methods that understand how to interpret the path characters so that "C:" just comes in as ordinary file characters on Linux. It would be good to keep it that way if possible. Testing whether getCurrentDriveLetter().empty()
is really a hidden platform dependency; those should be done with #ifdef WIN32
and localized with platform dependencies elsewhere. In contrast testing pathdrive.empty()
is not a platform dependency since it could be empty anywhere.
I didn't notice any test cases with ".." segments in the pathnames. It would be good to have one or two of those just to make sure that features is still working right in the new methods. |
…cutable directory is given. also update end of function to use deconstructPathname().
…kingDirectory(). add specific test cases for empty path, "." cases, "@" case, and use of "..".
@sherm1, ready again. Has the changes you suggested and some directed tests at weirder cases. |
Sweet! I love it when the code gets shorter! Thanks so much for all this work, Carmichael. Merging now. |
Addresses fixes to deconstructPathname (addresses issue #264). Introduces a new function deconstructPathRelativeToSWD that finds the absolute path to a given path name relative to a specified working directory (swd).