-
-
Notifications
You must be signed in to change notification settings - Fork 93
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
204 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# frozen_string_literal: true | ||
require "shakapacker/version" | ||
require "package_json" | ||
|
||
module Shakapacker | ||
class ManagerChecker | ||
class Error < StandardError; end | ||
|
||
MANAGER_LOCKS = { | ||
bun: "bun.lockb", | ||
npm: "package-lock.json", | ||
pnpm: "pnpm-lock.yaml", | ||
yarn: "yarn.lock" | ||
} | ||
|
||
# Emits a warning if it's not obvious what package manager to use | ||
def warn_unless_package_manager_is_obvious! | ||
return if package_manager_set? | ||
|
||
guessed_manager = guess_manager | ||
|
||
return if guess_manager == :npm | ||
|
||
Shakapacker.puts_deprecation_message(<<~MSG) | ||
You have not got "packageManager" set in your package.json meaning that Shakapacker will use npm | ||
but you've got a #{MANAGER_LOCKS[guessed_manager]} file meaning you probably want | ||
to be using #{guessed_manager} instead. | ||
To make this happen, set "packageManager" in your package.json to #{guessed_manager}@#{guess_manager_version} | ||
MSG | ||
end | ||
|
||
def package_manager_set? | ||
!PackageJson.read.fetch("packageManager", nil).nil? | ||
end | ||
|
||
def guess_manager_version | ||
require "open3" | ||
|
||
command = "#{guess_manager} --version" | ||
stdout, stderr, status = Open3.capture3(command) | ||
|
||
unless status.success? | ||
raise Error, "#{command} failed with exit code #{status.exitstatus}: #{stderr}" | ||
end | ||
|
||
stdout.chomp | ||
end | ||
|
||
def guess_manager | ||
MANAGER_LOCKS.find { |_, lock| File.exist?(lock) }&.first || :npm | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
require_relative "spec_helper_initializer" | ||
require "shakapacker/version" | ||
|
||
Struct.new("Status", :exit_code) do | ||
def success? | ||
exit_code.zero? | ||
end | ||
|
||
def exitstatus | ||
exit_code | ||
end | ||
end | ||
|
||
def within_temp_directory(tmpdir = nil, &block) | ||
Dir.mktmpdir("shakapacker-", tmpdir) do |dir| | ||
Dir.chdir(dir, &block) | ||
end | ||
end | ||
|
||
describe "ManagerChecker" do | ||
around do |example| | ||
within_temp_directory { example.run } | ||
end | ||
|
||
describe "#warn_unless_package_manager_is_obvious!" do | ||
before do | ||
allow(Shakapacker).to receive(:puts_deprecation_message) | ||
end | ||
|
||
context "when 'packageManager' is set in the package.json" do | ||
before do | ||
File.write("package.json", { "packageManager" => "pnpm" }.to_json) | ||
end | ||
|
||
it "does nothing" do | ||
Shakapacker::ManagerChecker.new.warn_unless_package_manager_is_obvious! | ||
|
||
expect(Shakapacker).not_to have_received(:puts_deprecation_message) | ||
end | ||
end | ||
|
||
context "when the guessed manager is npm" do | ||
it "does nothing" do | ||
File.write("package.json", {}.to_json) | ||
FileUtils.touch("package-lock.json") | ||
|
||
Shakapacker::ManagerChecker.new.warn_unless_package_manager_is_obvious! | ||
|
||
expect(Shakapacker).not_to have_received(:puts_deprecation_message) | ||
end | ||
end | ||
|
||
Shakapacker::ManagerChecker::MANAGER_LOCKS.reject { |manager| manager == :npm }.each do |manager, lock| | ||
context "when there is a #{lock}" do | ||
before do | ||
allow(Open3).to receive(:capture3).and_return(["1.2.3\n", "", Struct::Status.new(0)]) | ||
end | ||
|
||
it "recommends setting 'packageManager' for #{manager}" do | ||
File.write("package.json", {}.to_json) | ||
FileUtils.touch(lock) | ||
|
||
Shakapacker::ManagerChecker.new.warn_unless_package_manager_is_obvious! | ||
|
||
expect(Shakapacker).to have_received(:puts_deprecation_message).with(<<~MSG) | ||
You have not got "packageManager" set in your package.json meaning that Shakapacker will use npm | ||
but you've got a #{lock} file meaning you probably want | ||
to be using #{manager} instead. | ||
To make this happen, set "packageManager" in your package.json to #{manager}@1.2.3 | ||
MSG | ||
end | ||
end | ||
end | ||
end | ||
|
||
describe "#package_manager_set?" do | ||
it "returns true when the 'packageManager' property is set" do | ||
File.write("package.json", { "packageManager" => "npm" }.to_json) | ||
|
||
expect(Shakapacker::ManagerChecker.new.package_manager_set?).to be true | ||
end | ||
|
||
it "returns false when the 'packageManager' property is not set" do | ||
File.write("package.json", {}.to_json) | ||
|
||
expect(Shakapacker::ManagerChecker.new.package_manager_set?).to be false | ||
end | ||
end | ||
|
||
describe "#guess_manager_version" do | ||
before do | ||
allow(Open3).to receive(:capture3).and_return(["1.2.3\n", "", Struct::Status.new(0)]) | ||
end | ||
|
||
Shakapacker::ManagerChecker::MANAGER_LOCKS.each do |manager, lock| | ||
context "when a #{lock} exists" do | ||
before { FileUtils.touch(lock) } | ||
|
||
it "calls #{manager} with --version" do | ||
Shakapacker::ManagerChecker.new.guess_manager_version | ||
|
||
expect(Open3).to have_received(:capture3).with("#{manager} --version") | ||
end | ||
end | ||
end | ||
|
||
it "returns the output without a trailing newline" do | ||
FileUtils.touch("package-lock.json") | ||
|
||
expect(Shakapacker::ManagerChecker.new.guess_manager_version).to eq("1.2.3") | ||
end | ||
|
||
context "when the command errors" do | ||
before do | ||
allow(Open3).to receive(:capture3).and_return(["", "oh noes!", Struct::Status.new(1)]) | ||
end | ||
|
||
it "raises an error" do | ||
FileUtils.touch("package-lock.json") | ||
|
||
expect { Shakapacker::ManagerChecker.new.guess_manager_version }.to raise_error( | ||
Shakapacker::ManagerChecker::Error, | ||
"npm --version failed with exit code 1: oh noes!" | ||
) | ||
end | ||
end | ||
end | ||
|
||
describe "#guess_manager" do | ||
Shakapacker::ManagerChecker::MANAGER_LOCKS.each do |manager, lock| | ||
context "when a #{lock} exists" do | ||
before { FileUtils.touch(lock) } | ||
|
||
it "guesses #{manager}" do | ||
expect(Shakapacker::ManagerChecker.new.guess_manager).to eq manager | ||
end | ||
end | ||
end | ||
|
||
context "when there is no lockfile" do | ||
it "returns npm" do | ||
expect(Shakapacker::ManagerChecker.new.guess_manager).to eq :npm | ||
end | ||
end | ||
end | ||
end |