-
-
Notifications
You must be signed in to change notification settings - Fork 372
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
Disable watch to prevent race condition between threads calling site.process #320
Conversation
This prevents a race condition with another thread calling site.process. Before, site.process had to complete before the response would be correct, which is quite unreliable. Instead, use the appropriate Jekyll classes to read the item.
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.
Wow 😄 We were really overthinking. Great solution 👍
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 might need to do this for static files and data files as well.
lib/jekyll-admin/server/page.rb
Outdated
@@ -20,7 +20,9 @@ class Server < Sinatra::Base | |||
end | |||
|
|||
write_file(write_path, page_body) | |||
updated_page = pages.find { |p| p.path == write_path } | |||
updated_page = Jekyll::Page.new( | |||
site, site.source, File.dirname(write_path), File.basename(write_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 the path sanitized prior to being read? (to prevent directory traversal from the user-supplied write_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.
@benbalter The write_path
comes from either document_path
or request_path
. In my opinion this should most certainly be sanitized before it gets here as it's used to interact with the filesystem before this line.
updated_document = collection.docs.find { |d| d.path == write_path } | ||
updated_document = Jekyll::Document.new(write_path, { | ||
:collection => collection, :site => site, | ||
}).tap(&:read) | ||
render_404 if updated_document.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.
If we rename updated_document
to document
, we can use ensure_document
which does the same thing. Same for ensure_page
.
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.
We won't be able to do this, because ensure_document
calls document
, which uses the buggy way of reading:
80 def document
81 collection.docs.find { |d| d.path == document_path }
82 end
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.
Isn't document
overwritten by Jekyll::Document.new
? So ensure_document
uses newly created document object instead of the result object of document
method.
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'm guessing methods' priority is higher over objects in ruby so it will use document
method anyway?
Static files, yes, but data files use their own API: |
…back to the old way.
collection.docs.find { |d| d.path == document_path } || | ||
Jekyll::Document.new(write_path, { | ||
:collection => collection, :site => site, | ||
}).tap(&:read) |
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 is really 🆒 You da boss 😎
lib/jekyll-admin/server/page.rb
Outdated
@@ -85,7 +84,9 @@ def relative_page_path | |||
end | |||
|
|||
def page | |||
site.pages.find { |p| sanitized_path(p.path) == page_path } | |||
Jekyll::Page.new( |
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.
Missed ||
here or is this on purpose?
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.
You could do either.
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 he's asking if we want to look to the existing page first then fall back to creating a new one like we do for other content types?
@@ -29,8 +29,7 @@ class Server < Sinatra::Base | |||
end | |||
|
|||
write_file(write_path, document_body) | |||
updated_document = collection.docs.find { |d| d.path == write_path } | |||
render_404 if updated_document.nil? | |||
ensure_document | |||
json updated_document.to_api(:include_content => 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.
This needs to be document
now instead of updated_document
.
lib/jekyll-admin/server/page.rb
Outdated
@@ -20,8 +20,7 @@ class Server < Sinatra::Base | |||
end | |||
|
|||
write_file(write_path, page_body) | |||
updated_page = pages.find { |p| p.path == write_path } | |||
render_404 if updated_page.nil? | |||
ensure_page | |||
json updated_page.to_api(:include_content => 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.
This needs to be page
.
This should be good to go after deleting test files (unless failing tests generating them). |
@mertkahyaoglu Would you mind taking this PR and running with it? I am not able to commit any more time to it unfortunately but I think we have the right approach here. 😄 |
@parkr Got it 👍 I reverted 1203e14 because Another thing is that static files tests are failing when Here are the failing tests; rspec ./spec/jekyll-admin/server/static_file_spec.rb:30 # static_files 404s when a static file doesn't exist
rspec ./spec/jekyll-admin/server/static_file_spec.rb:35 # static_files returns a deep directory listing
rspec ./spec/jekyll-admin/server/static_file_spec.rb:51 # static_files returns a directory listing starting only at the root @benbalter Any solution for this? Or shall we revert this approach for static files. |
@mertkahyaoglu: @parkr is out of the office this week, but I'll take a look this morning and see what I can do here to get the build passing. |
lib/jekyll-admin/server/page.rb
Outdated
return found if found | ||
return unless File.file?(write_path) | ||
Jekyll::Page.new( | ||
site, site.source, File.dirname(write_path), File.basename(write_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.
Do we want the full path for dir
?
sent a PR #324 inspired by this comment. |
test --watch with this plugin
Full props go to @ashmaroli. If tests are green, I believe this can be merged. |
@ashmaroli @benbalter @parkr Awesome work guys. Many thanks. This and #323 deserve a release. |
Thank you for the acknowledgement @benbalter and @mertkahyaoglu 😃 🍻 |
I feel #321 should be addressed by the next release. Either with the merge of #322 (or another better implementation), or an entry to the documentation informing users about the situation. Another TODO:
from Ben's comment above. |
This introduces other issues, see #340 Not sure why the admin has to take over re-generation when enabled as a plugin? Just write files to disk, like all editors. Then jekyll would do it's job and re-generate content on changes, no matter if files are changed via admin or other editors. Thanks |
From Jekyll Admin's online docs
|
The current editing of .css, layouts or includes is a pain. We have to stop jekyll and start again on each css edit, to see changes. The simplest one does see to limit jekyll-admin to edit files as any IDE, just write them to local disk. Don't try to generate anything, jekyll already handles that well, and it works for all assets. |
The simplest solution when editing "non-content files" is to comment out |
So
Would you agree it's cumbersome? |
Definitely. |
Actually I'm planning to bring the |
FYI, released under gem-name |
This prevents a race condition with another thread calling site.process.
Before, site.process had to complete before the response would be
correct, which is quite unreliable. Instead, use the appropriate Jekyll
classes to read the item.
Replaces #294.