Conversation
This searches through the path variable's directories for the docker commands, instead of looking in predetermined OS-specific locations or requiring new environmental variables to be set. This also renames DockerCommandLocations to DockerCommandLocator, which better reflects what it is.
….com/samwright/docker-compose-rule into samwright-feature/use-path-to-find-executables
| @@ -1,47 +1,75 @@ | |||
| /* | |||
| * Copyright 2016 Palantir Technologies, Inc. All rights reserved. | |||
There was a problem hiding this comment.
Are we keeping or removing the License? It's removed here but kept in the following file.
There was a problem hiding this comment.
All files should have the Apache licence. I'll fix the ones that had it removed.
| return Stream.concat(Stream.of(locationOverride()), pathLocations); | ||
| } | ||
|
|
||
| public Stream<Path> forCommand() { |
There was a problem hiding this comment.
Why are we returning Stream? They have use once semantics
There was a problem hiding this comment.
Purely because it was extracted out the middle of a stream, I'll make it a list.
| protected abstract String command(); | ||
|
|
||
| @Value.Default | ||
| protected boolean isWindows() { |
There was a problem hiding this comment.
returning a constant to represent a default where the constant is framed as a question is somewhat misleading (I still don't know what the default is)
There was a problem hiding this comment.
The default is to allow it to be overriden in tests, otherwise it should behave as a constant.
Would "useWindowsExecutableNaming" have been easier to understand?
There was a problem hiding this comment.
isWindows is fine, but I'm starting to think that making it a default doesn't really make any sense. Whoever creates this builder will know at the time what environment they're in, and it feels odd to be like "I'm not going to specify if I'm running on windows because defaults"
Unless of course this is for backcompat and it's used in client code then nevermind.
| .orElseThrow(() -> new IllegalStateException( | ||
| "Could not find docker-compose, looked in: " + DOCKER_COMPOSE_LOCATIONS)); | ||
|
|
||
| DockerCommandLocator commandLocator = DockerCommandLocator.forCommand("docker-compose") |
There was a problem hiding this comment.
returning a builder just to do this looks kinda meh, might as well do the entire builder from here and delete the forCommand method
|
|
||
| public Optional<String> preferredLocation() { | ||
| @Value.Derived | ||
| protected String path() { |
There was a problem hiding this comment.
This doesn't work on Windows, where the path variable is "Path". You could add another if (path == null) path = env().get("Path"), or iterate through the env() map to find any key that equals "path" ignoring case, e.g.
String path = getEnv().entrySet().stream()
.filter(e -> e.getKey().equalsIgnoreCase("path"))
.findFirst()
.map(Map.Entry::getValue)
.orElseThrow(() -> new IllegalStateException("Could not find path variable in env"));
There was a problem hiding this comment.
Okay, this should now cover PATH, path and Path.
| } | ||
|
|
||
| @Test public void | ||
| fail_when_no_paths_contain_command() { |
There was a problem hiding this comment.
Sorry, ignore this one. I got an error running this but I now can't recreate it.
There was a problem hiding this comment.
Ah, found it again (I had @ignore'd the test, woops!)
Expected: (an instance of java.lang.IllegalStateException and exception with message a string containing "Could not find not-a-real-command! in [/usr/local/bin, /usr/bin]") but: exception with message a string containing "Could not find not-a-real-command! in [/usr/local/bin, /usr/bin]" message was "Could not find not-a-real-command! in [\usr\local\bin, \usr\bin]"
The "/usr/local/bin" string is converted to a Path in DockerCommandLocations.pathLocations(), which on Windows converts it to "\usr\local\bin" (aren't path separators fun?!)
You could change the expected message to just "Could not find " + command, or create a List<Path> defaultPaths = ImmutableList.of(Paths.get("/usr/local/bin"), Paths.get("/usr/bin")) and expect "Could not find " + command + " in " + defaultPaths.
| public String toString() { | ||
| return "DockerCommandLocations{possiblePaths=" + possiblePaths + "}"; | ||
| public static List<Path> pathLocations() { | ||
| String path = Stream.of(System.getenv("PATH"), System.getenv("path"), System.getenv("Path")) |
There was a problem hiding this comment.
But what about CrazyOS that uses "pATh"? /s
| return singletonList(Paths.get(locationOverride())); | ||
| } | ||
|
|
||
| public String getLocation() { |
There was a problem hiding this comment.
Previously DOCKER_COMPOSE_LOCATION would be the path to the binary, e.g. /path/to/docker-compose, but the logic here requires it to point to the directory in which to find docker-compose, i.e. /path/to. I think the previous behaviour is more obvious/expected.
You could remove the searchLocations method, and do the check for the location override here instead, e..g
if (locationOverride() == null) {
return DockerCommandLocations.pathLocations().stream()....;
} else {
return locationOverride();
}
It might even be worth moving DockerCommandLocations.pathLocations() to this class, but that's just a design thing.
|
Okay, it turns out ProcessBuilder looks for commands on the path (at least on Mac/Linux) and so there is no need to do this manually. I've updated the PR to do the simpler thing of only looking in the known Mac install locations and allow for explicitly setting it through an environment variable. @samwright could you give this a spin and see if it is actually sufficient for Windows? If not we should find a library that will give us as because as @ChrisAlice pointed out the Windows path variable can contain expansions that would require us to look at other environment variables to correctly use. |
|
Yep this works in Windows. I also tried just running "docker-compose.exe" without specifying its location and that worked too: So it would probably be best to get rid of all that path variable stuff. Sorry for giving you a red herring! |
|
@hpryce , is this still relevant / needed to merge? Or is this overcome-by-events? |
|
On windows, the just-released |
This combines #170 and #152 to provide support for finding docker from the path both on Windows and in existing setups.