mirror of
https://github.com/ivuorinen/homebrew-tap.git
synced 2026-02-15 04:50:16 +00:00
chore: fixes, several improvements and refactorings (#2)
* chore: fixes * chore: rubocop fixes, linting, etc. * chore: switching to use `brew style` only * chore: use `brew style` for linting, skip example formulae in ci.yml * chore(lint): fixes, additions and tweaks
This commit is contained in:
247
scripts/serve.rb
Normal file → Executable file
247
scripts/serve.rb
Normal file → Executable file
@@ -1,22 +1,146 @@
|
||||
#!/usr/bin/env ruby
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'webrick'
|
||||
require 'fileutils'
|
||||
require_relative 'parse_formulas'
|
||||
require_relative 'build_site'
|
||||
require "webrick"
|
||||
require "fileutils"
|
||||
require_relative "parse_formulas"
|
||||
require_relative "build_site"
|
||||
|
||||
# Simple development server for the homebrew tap documentation
|
||||
# Module for handling file watching and change detection
|
||||
module FileWatcher
|
||||
def start_file_watcher
|
||||
Thread.new do
|
||||
last_mtime = max_mtime
|
||||
rebuild_pending = false
|
||||
watched_files = watched_files_count
|
||||
|
||||
puts "👀 Watching #{watched_files} files for changes..."
|
||||
|
||||
loop do
|
||||
sleep 1
|
||||
current_mtime = max_mtime
|
||||
|
||||
next if should_skip_rebuild?(current_mtime, last_mtime, rebuild_pending)
|
||||
|
||||
rebuild_pending = true
|
||||
handle_file_change(last_mtime)
|
||||
last_mtime = perform_rebuild_with_debounce
|
||||
rebuild_pending = false
|
||||
puts "✅ Rebuild complete"
|
||||
rescue => e
|
||||
puts "⚠️ File watcher error: #{e.message}"
|
||||
puts "📍 Backtrace: #{e.backtrace.first(3).join(", ")}"
|
||||
rebuild_pending = false
|
||||
sleep 2
|
||||
puts "🔄 File watcher continuing..."
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def watched_files_count
|
||||
all_watched_files.count { |file| !File.directory?(file) }
|
||||
end
|
||||
|
||||
def find_changed_file(since_mtime)
|
||||
all_watched_files.find do |file|
|
||||
File.exist?(file) && !File.directory?(file) && File.mtime(file) > since_mtime
|
||||
end
|
||||
end
|
||||
|
||||
def all_watched_files
|
||||
[
|
||||
formula_files,
|
||||
theme_files,
|
||||
template_files,
|
||||
style_and_script_files,
|
||||
asset_files,
|
||||
build_script_files,
|
||||
config_files,
|
||||
].flatten.compact.uniq
|
||||
end
|
||||
|
||||
def max_mtime
|
||||
all_watched_files
|
||||
.select { |file| File.exist?(file) && !File.directory?(file) }
|
||||
.map { |file| File.mtime(file) }
|
||||
.max || Time.at(0)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def should_skip_rebuild?(current_mtime, last_mtime, rebuild_pending)
|
||||
current_mtime <= last_mtime || rebuild_pending
|
||||
end
|
||||
|
||||
def handle_file_change(last_mtime)
|
||||
changed_file = find_changed_file(last_mtime)
|
||||
puts "📝 Changed: #{changed_file}" if changed_file
|
||||
puts "🔄 Rebuilding in 1 second..."
|
||||
end
|
||||
|
||||
def perform_rebuild_with_debounce
|
||||
sleep 1 # Debounce: wait for additional changes
|
||||
final_mtime = max_mtime
|
||||
puts "🔨 Building site..."
|
||||
build_site
|
||||
final_mtime
|
||||
end
|
||||
|
||||
def formula_files
|
||||
Dir.glob(File.expand_path("../Formula/**/*.rb", __dir__))
|
||||
end
|
||||
|
||||
def theme_files
|
||||
Dir.glob(File.expand_path("../theme/**/*", __dir__))
|
||||
end
|
||||
|
||||
def template_files
|
||||
[
|
||||
Dir.glob(File.expand_path("../theme/*.erb", __dir__)),
|
||||
Dir.glob(File.expand_path("../theme/_*.erb", __dir__)),
|
||||
Dir.glob(File.expand_path("../theme/*.html.erb", __dir__)),
|
||||
Dir.glob(File.expand_path("../theme/_*.html.erb", __dir__)),
|
||||
].flatten
|
||||
end
|
||||
|
||||
def style_and_script_files
|
||||
[
|
||||
Dir.glob(File.expand_path("../theme/*.css", __dir__)),
|
||||
Dir.glob(File.expand_path("../theme/*.js", __dir__)),
|
||||
].flatten
|
||||
end
|
||||
|
||||
def asset_files
|
||||
Dir.glob(File.expand_path("../theme/assets/**/*", __dir__))
|
||||
end
|
||||
|
||||
def build_script_files
|
||||
[
|
||||
File.expand_path("../scripts/parse_formulas.rb", __dir__),
|
||||
File.expand_path("../scripts/build_site.rb", __dir__),
|
||||
]
|
||||
end
|
||||
|
||||
def config_files
|
||||
[File.expand_path("../Makefile", __dir__)]
|
||||
end
|
||||
end
|
||||
|
||||
# Development server with file watching for homebrew tap documentation
|
||||
class DevServer
|
||||
def self.serve(port: 4000, host: 'localhost')
|
||||
include FileWatcher
|
||||
|
||||
def self.serve(port: 4000, host: "localhost")
|
||||
new(port: port, host: host).start
|
||||
end
|
||||
|
||||
def initialize(port: 4000, host: 'localhost')
|
||||
def initialize(port: 4000, host: "localhost")
|
||||
@port = port
|
||||
@host = host
|
||||
@site_dir = File.expand_path('../docs', __dir__)
|
||||
@docs_dir = File.expand_path('../docs', __dir__)
|
||||
@site_dir = File.expand_path("../docs", __dir__)
|
||||
@docs_dir = File.expand_path("../docs", __dir__)
|
||||
end
|
||||
|
||||
def start
|
||||
@@ -43,128 +167,45 @@ class DevServer
|
||||
|
||||
def start_server
|
||||
server = WEBrick::HTTPServer.new(
|
||||
Port: @port,
|
||||
Host: @host,
|
||||
Port: @port,
|
||||
Host: @host,
|
||||
DocumentRoot: @site_dir,
|
||||
Logger: WEBrick::Log.new($stderr, WEBrick::Log::INFO),
|
||||
AccessLog: [[
|
||||
Logger: WEBrick::Log.new($stderr, WEBrick::Log::INFO),
|
||||
AccessLog: [[
|
||||
$stderr,
|
||||
WEBrick::AccessLog::COMBINED_LOG_FORMAT
|
||||
]]
|
||||
WEBrick::AccessLog::COMBINED_LOG_FORMAT,
|
||||
]],
|
||||
)
|
||||
|
||||
# Handle Ctrl+C gracefully
|
||||
trap('INT') do
|
||||
trap("INT") do
|
||||
puts "\n👋 Stopping server..."
|
||||
server.shutdown
|
||||
end
|
||||
|
||||
# Add custom mime types if needed
|
||||
server.config[:MimeTypes]['json'] = 'application/json'
|
||||
server.config[:MimeTypes]["json"] = "application/json"
|
||||
|
||||
# Add auto-rebuild on file changes (simple polling)
|
||||
start_file_watcher
|
||||
|
||||
server.start
|
||||
end
|
||||
|
||||
def start_file_watcher
|
||||
Thread.new do
|
||||
last_mtime = get_max_mtime
|
||||
rebuild_pending = false
|
||||
watched_files = get_watched_files_count
|
||||
|
||||
puts "👀 Watching #{watched_files} files for changes..."
|
||||
|
||||
loop do
|
||||
sleep 1
|
||||
current_mtime = get_max_mtime
|
||||
|
||||
if current_mtime > last_mtime && !rebuild_pending
|
||||
rebuild_pending = true
|
||||
changed_file = find_changed_file(last_mtime)
|
||||
puts "📝 Changed: #{changed_file}" if changed_file
|
||||
puts "🔄 Rebuilding in 1 second..."
|
||||
|
||||
# Debounce: wait for additional changes
|
||||
sleep 1
|
||||
|
||||
# Check if more changes occurred during debounce period
|
||||
final_mtime = get_max_mtime
|
||||
|
||||
puts "🔨 Building site..."
|
||||
build_site
|
||||
last_mtime = final_mtime
|
||||
rebuild_pending = false
|
||||
puts "✅ Rebuild complete"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def get_watched_files_count
|
||||
files = get_all_watched_files
|
||||
files.select { |f| File.exist?(f) && !File.directory?(f) }.count
|
||||
end
|
||||
|
||||
def find_changed_file(since_time)
|
||||
files = get_all_watched_files
|
||||
files.select { |f| File.exist?(f) && !File.directory?(f) }
|
||||
.find { |f| File.mtime(f) > since_time }
|
||||
&.sub(File.expand_path('..', __dir__) + '/', '')
|
||||
end
|
||||
|
||||
def get_all_watched_files
|
||||
[
|
||||
# Watch Formula files for changes
|
||||
Dir.glob(File.expand_path('../Formula/**/*.rb', __dir__)),
|
||||
# Watch all theme files including partials
|
||||
Dir.glob(File.expand_path('../theme/**/*', __dir__)),
|
||||
# Specifically watch for erb templates and partials
|
||||
Dir.glob(File.expand_path('../theme/*.erb', __dir__)),
|
||||
Dir.glob(File.expand_path('../theme/_*.erb', __dir__)),
|
||||
Dir.glob(File.expand_path('../theme/*.html.erb', __dir__)),
|
||||
Dir.glob(File.expand_path('../theme/_*.html.erb', __dir__)),
|
||||
# Watch CSS and JS
|
||||
Dir.glob(File.expand_path('../theme/*.css', __dir__)),
|
||||
Dir.glob(File.expand_path('../theme/*.js', __dir__)),
|
||||
# Watch assets directory
|
||||
Dir.glob(File.expand_path('../theme/assets/**/*', __dir__)),
|
||||
# Watch build scripts for changes
|
||||
[File.expand_path('../scripts/parse_formulas.rb', __dir__)],
|
||||
[File.expand_path('../scripts/build_site.rb', __dir__)],
|
||||
# Watch Makefile
|
||||
[File.expand_path('../Makefile', __dir__)]
|
||||
].flatten.compact.uniq
|
||||
end
|
||||
|
||||
def get_max_mtime
|
||||
files_to_watch = get_all_watched_files
|
||||
|
||||
# Filter out non-existent files and directories, get modification times
|
||||
existing_files = files_to_watch.select { |f| File.exist?(f) && !File.directory?(f) }
|
||||
|
||||
if existing_files.empty?
|
||||
Time.at(0)
|
||||
else
|
||||
existing_files.map { |f| File.mtime(f) }.max
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Command line interface
|
||||
if __FILE__ == $PROGRAM_NAME
|
||||
# Check for --list-watched flag
|
||||
if ARGV.include?('--list-watched')
|
||||
if ARGV.include?("--list-watched")
|
||||
server = DevServer.new
|
||||
files = server.send(:get_all_watched_files).select { |f| File.exist?(f) && !File.directory?(f) }
|
||||
files = server.all_watched_files.select { |f| File.exist?(f) && !File.directory?(f) }
|
||||
puts "📋 Watching #{files.count} files:"
|
||||
files.sort.each { |f| puts " - #{f.sub(File.expand_path('..', __dir__) + '/', '')}" }
|
||||
files.sort.each { |f| puts " - #{f.sub("#{File.expand_path("..", __dir__)}/", "")}" }
|
||||
exit 0
|
||||
end
|
||||
|
||||
port = ARGV[0]&.to_i || 4000
|
||||
host = ARGV[1] || 'localhost'
|
||||
host = ARGV[1] || "localhost"
|
||||
|
||||
DevServer.serve(port: port, host: host)
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user