-
Notifications
You must be signed in to change notification settings - Fork 135
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
Fixes for repository detection on Windows #136
Conversation
The existing code does not find `git.exe` on Windows, and the metadata lookup fails. This change uses PATHEXT to get the list of valid extensions and checks for each. ``` irb(main):035:0> ENV['PATHEXT'] => ".COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.RB;.RBW" ``` This change also checks if the file is executable to avoid false positives.
Backticks don't work properly without special quoting. Switch to Open3 for portability.
/cc @jekyll/windows |
Some dependencies don't work on 2.2. ``` Gem::RuntimeRequirementNotMetError: jekyll-watch requires Ruby version >= 2.3.0. The current ruby version is 2.2.0. An error occurred while installing jekyll-watch (2.1.2), and Bundler cannot continue. ```
After a few tweaks, the remaining Travis failures are due to code style issues in files I've not modified. |
@GICodeWarrior Can you elaborate on how exactly you came across this issue..? |
@ashmaroli Yeah, it's the same issue described here: http://blog.johannesmp.com/2017/02/13/fixing-jekyll-serve-on-windows/#fix-no-repo-name-found There is a "No repo name found" error on Windows even when git has a properly configured remote. Most people workaround the issue by specifying the repo name in the config. When I ran bits of the repository finder code in irb, I found that it was unable to locate git on Windows. Digging deeper, the problem was that git is This patch fixes that problem and a follow-on issue where paths (with spaces?) on Windows don't work as expected in back-ticks style execution. |
@@ -46,15 +48,19 @@ def nwo_from_config | |||
end | |||
|
|||
def git_exe_path | |||
exts = (ENV["PATHEXT"] || "").split(File::PATH_SEPARATOR).push("") |
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's going on here?
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.
PATHEXT
on Windows is a list of file extensions respected by cmd.exe.
http://environmentvariables.org/PathExt
This code splits PATHEXT into an array of extensions and adds a blank extension to the end (for odd Windows setups and normal non-Windows setups).
irb(main):001:0> (ENV["PATHEXT"] || "").split(File::PATH_SEPARATOR).push("")
=> [".COM", ".EXE", ".BAT", ".CMD", ".VBS", ".VBE", ".JS", ".JSE", ".WSF", ".WSH", ".MSC", ".RB", ".RBW", ""]
On non-Windows platforms exts
is only [""]
.
@@ -46,15 +48,19 @@ def nwo_from_config | |||
end | |||
|
|||
def git_exe_path | |||
exts = (ENV["PATHEXT"] || "").split(File::PATH_SEPARATOR).push("") | |||
cmds = exts.map { |ext| "git#{ext}" } |
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.
Is there any known scenario where git.exe
is not the Git Executable on Windows? If not, lets not waste time searching for those paths and zero in on ~/git.exe
straight away.
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 really have visibility into how people have their machines setup, but having a git.bat
file to wrap Git is one edge case I can think of.
Random example: https://gist.github.com/duebbert/c4f26c9d0691b7d4a0e932e7d9f36271
Technically all of the extensions in PATH_EXT
can be used plainly as git
from the command line on Windows if someone added a wrapper or alternate implementation to their PATH
.
If you want to simplify it, I recommend skipping the PATH
search altogether and allowing the Open3
/Exec.run
call to outsource that to the OS.
Do you know why this PATH
code exists in the first place?
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.
Delegating to Windows can be bothersome IMO.
Some machines respond to where
while some responds to where.exe
while the others do not have either of the two programs in their PATH
..
.find { |path| File.exist?(path) } | ||
.map { |path| cmds.map { |cmd| File.join(path, cmd) } } | ||
.flatten | ||
.find { |path| File.executable?(path) && !File.directory?(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.
Is this branching really necessary?
When is an executable ever a directory?
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.
Directories are always executable. So if there is a git
directory in PATH
, we don't want to select it.
Windows:
irb(main):006:0> File.directory?('/Users')
=> true
irb(main):007:0> File.executable?('/Users')
=> true
Linux:
irb(main):002:0> File.directory?('/home')
=> true
irb(main):003:0> File.executable?('/home')
=> true
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.
Today I Learned TM 👍
@GICodeWarrior Okay, now that I have the proper context to this proposal, I understand the motivation behind this PR.
|
896dbc1
to
de78edc
Compare
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'd like the following changes to be made:
- Attribution to an existing source of information.
I found the proposed changes here to be "very similar" to an answer at StackOverflow:
It is good etiquette to attribute in FOSS, even if the original code has been "adapted" - Reduce Array traversals:
- Push
""
only into an empty array - Join only
.exe
to path strings since we're looking for only~/git.exe
- Check only if
File.executable?(path)
istrue
- Instead of chaining
map
,flatten
,find
, simplyreturn
from a nestedeach
:# By now, `ext` is simply [".exe"] or [""] ENV["PATH"].to_s .split(File::PATH_SEPARATOR) .each do |path| exts.each do |ext| exe = File.join(path, "git#{ext}") return exe if File.executable?(exe) end end nil
- Push
end | ||
|
||
def git_remotes | ||
return [] if git_exe_path.nil? | ||
`#{git_exe_path} remote --verbose`.to_s.strip.split("\n") | ||
output, _status = Open3.capture2(git_exe_path, "remote", "--verbose") |
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.
@parkr @benbalter Can we drop support for Jekyll versions < 3.4.0
and use Jekyll::Utils::Exec.run
instead of using Open3
directly..?
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.
Good idea, as GitHub pages uses currently 3.7.4
it shouldn't be a problem.
If I get back to this, I'll update with a version that removes all the |
@GICodeWarrior Delegating to the OS is probably not a good solution here.. (can not be reliably cross-platform).. |
Can you clarify how allowing the platform to leverage it's own PATH mechanisms will be less reliable than a bespoke implementation of those mechanisms in this library? |
Here are some examples of how Jekyll uses |
How would a developer on UNIX-based systems go about this..? $ which git
# => /path/to/git And how would a developer on Windows go about it? # on default Windows Command Prompt
where git
# => C:\path\to\git.exe # on Windows PowerShell
where.exe git
# => C:\path\to\git.exe |
Well, it's a different story entirely if you're no longer intending to find the path to |
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 re-visiting looks good to me. Just some minor comments
@GICodeWarrior One other thing.. We need to drop support for Jekyll versions older than |
Co-Authored-By: GICodeWarrior <[email protected]>
Co-Authored-By: GICodeWarrior <[email protected]>
@parkr @benbalter Should this warrant a bump in the major version since we're dropping support for Jekyll versions older than |
after(:each) { ENV["PATH"] = @old_path.join(File::PATH_SEPARATOR) } | ||
before(:each) do | ||
@old_path = ENV["PATH"] | ||
ENV["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.
?
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 PATH
is "reset" to an empty string to simulate the scenario where git
is not installed.. (especially in CI environments)
|
||
it "fails with a nice error message" do | ||
allow(subject).to receive(:git_remote_url).and_call_original | ||
expect(subject.send(:git_exe_path)).to eql(nil) |
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 we still need to be able to run git? If we're relying on Jekyll::Utils::Exec, then we'll definitely need to make sure that the exe can be found, right?
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.
Relying on Jekyll::Utils::Exec
is like running system "git"
in a begin..rescue
block..
If the utility method doesn't find the executable, an Errno::ENOENT
is raised which is rescued to output a warning to the terminal..
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.
Ok, so we can remove git_exe_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.
Yep. In fact, this PR has already removed it..
Updated per comments. |
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.
👍 LGTM
Thank you! @jekyllbot: merge +bug |
The repository detection code wasn't portable to Windows.
These changes fix detection on Windows and maintain portability with other platforms.