Skip to content

Commit

Permalink
Refactor ProjectInfo defaults
Browse files Browse the repository at this point in the history
  • Loading branch information
straight-shoota committed Apr 10, 2020
1 parent 637191b commit b5695ae
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 89 deletions.
116 changes: 116 additions & 0 deletions spec/compiler/crystal/tools/doc/project_info_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
require "../../../../spec_helper"
require "../../../../support/tempfile"

describe Crystal::Doc::ProjectInfo do
it ".new_with_defaults" do
with_tempfile("docs-defaults") do |tempdir|
Dir.mkdir tempdir
Dir.cd(tempdir) do
# Empty dir
Crystal::Doc::ProjectInfo.new_with_defaults(nil, nil) { |name, version| "missing:#{name}:#{version}" }.should eq "missing::"
Crystal::Doc::ProjectInfo.new_with_defaults("foo", "1.0") { |name, version| "missing:#{name}:#{version}" }.should eq Crystal::Doc::ProjectInfo.new("foo", "1.0")

# shard.yml
File.write("shard.yml", "name: foo\nversion: 1.0")
Crystal::Doc::ProjectInfo.new_with_defaults(nil, nil) { |name, version| "missing:#{name}:#{version}" }.should eq Crystal::Doc::ProjectInfo.new("foo", "1.0")
Crystal::Doc::ProjectInfo.new_with_defaults("bar", "2.0") { |name, version| "missing:#{name}:#{version}" }.should eq Crystal::Doc::ProjectInfo.new("bar", "2.0")
Crystal::Doc::ProjectInfo.new_with_defaults(nil, "2.0") { |name, version| "missing:#{name}:#{version}" }.should eq Crystal::Doc::ProjectInfo.new("foo", "2.0")

# git tagged version
`git init`
`git add shard.yml`
`git commit -m 'Initial commit' --no-gpg-sign`
`git tag v3.0`
Crystal::Doc::ProjectInfo.new_with_defaults(nil, nil) { |name, version| "missing:#{name}:#{version}" }.should eq Crystal::Doc::ProjectInfo.new("foo", "3.0")
Crystal::Doc::ProjectInfo.new_with_defaults("bar", "2.0") { |name, version| "missing:#{name}:#{version}" }.should eq Crystal::Doc::ProjectInfo.new("bar", "2.0")

# git dirty dir
File.write("foo.txt", "bar")
Crystal::Doc::ProjectInfo.new_with_defaults(nil, nil) { |name, version| "missing:#{name}:#{version}" }.should eq Crystal::Doc::ProjectInfo.new("foo", "1.0")
Crystal::Doc::ProjectInfo.new_with_defaults(nil, "1.1") { |name, version| "missing:#{name}:#{version}" }.should eq Crystal::Doc::ProjectInfo.new("foo", "1.1")
Crystal::Doc::ProjectInfo.new_with_defaults("bar", "2.0") { |name, version| "missing:#{name}:#{version}" }.should eq Crystal::Doc::ProjectInfo.new("bar", "2.0")
File.delete("foo.txt")

# No shard.yml, but git version
`git rm shard.yml`
`git commit -m 'Remove shard.yml' --no-gpg-sign`
`git tag v4.0`
Crystal::Doc::ProjectInfo.new_with_defaults(nil, nil) { |name, version| "missing:#{name}:#{version}" }.should eq "missing::4.0"
Crystal::Doc::ProjectInfo.new_with_defaults("foo", nil) { |name, version| "missing:#{name}:#{version}" }.should eq Crystal::Doc::ProjectInfo.new("foo", "4.0")
Crystal::Doc::ProjectInfo.new_with_defaults("bar", "2.0") { |name, version| "missing:#{name}:#{version}" }.should eq Crystal::Doc::ProjectInfo.new("bar", "2.0")
end
end
end

it ".find_git_version" do
with_tempfile("docs-git-version") do |tempdir|
Dir.mkdir tempdir
Dir.cd(tempdir) do
# Non-git directory
Crystal::Doc::ProjectInfo.find_git_version.should be_nil

`git init`
Crystal::Doc::ProjectInfo.find_git_version.should be_nil

File.write("file.txt", "foo")
`git add file.txt`
`git commit -m 'Initial commit' --no-gpg-sign`
Crystal::Doc::ProjectInfo.find_git_version.should be_nil

`git tag v0.1.0`
Crystal::Doc::ProjectInfo.find_git_version.should eq "0.1.0"

File.write("file.txt", "bar")
Crystal::Doc::ProjectInfo.find_git_version.should be_nil

`git add file.txt`
Crystal::Doc::ProjectInfo.find_git_version.should be_nil

`git reset --hard v0.1.0`
Crystal::Doc::ProjectInfo.find_git_version.should eq "0.1.0"

`git tag v0.2.0`
Crystal::Doc::ProjectInfo.find_git_version.should be_nil
end
end
end

it ".read_shard_properties" do
with_tempfile("docs-shard.yml") do |tempdir|
Dir.mkdir tempdir
Dir.cd(tempdir) do
Crystal::Doc::ProjectInfo.read_shard_properties.should eq({nil, nil})

File.write("shard.yml", "foo: bar\n")
Crystal::Doc::ProjectInfo.read_shard_properties.should eq({nil, nil})

File.write("shard.yml", "name: \nversion: ")
Crystal::Doc::ProjectInfo.read_shard_properties.should eq({nil, nil})

File.write("shard.yml", " name: bar\n version: 1.0")
Crystal::Doc::ProjectInfo.read_shard_properties.should eq({nil, nil})

File.write("shard.yml", "name: bar\n")
Crystal::Doc::ProjectInfo.read_shard_properties.should eq({"bar", nil})

File.write("shard.yml", "name: bar\nversion: 1.0")
Crystal::Doc::ProjectInfo.read_shard_properties.should eq({"bar", "1.0"})

File.write("shard.yml", "name: bar\nversion: 1.0\nname: foo\nversion: foo")
Crystal::Doc::ProjectInfo.read_shard_properties.should eq({"bar", "1.0"})

File.write("shard.yml", "name: bar \nversion: 1.0 ")
Crystal::Doc::ProjectInfo.read_shard_properties.should eq({"bar", "1.0"})

File.write("shard.yml", "name: 'bar'\nversion: '1.0'")
Crystal::Doc::ProjectInfo.read_shard_properties.should eq({"bar", "1.0"})

File.write("shard.yml", "name: bar # comment\nversion: 1.0 # comment")
Crystal::Doc::ProjectInfo.read_shard_properties.should eq({"bar", "1.0"})

File.write("shard.yml", "name: # comment\nversion: # comment")
Crystal::Doc::ProjectInfo.read_shard_properties.should eq({nil, nil})
end
end
end
end
62 changes: 0 additions & 62 deletions spec/compiler/crystal/tools/doc_spec.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
require "../../../spec_helper"
require "../../../support/tempfile"

private def assert_matches_pattern(url, **options)
match = Crystal::Doc::Generator::GIT_REMOTE_PATTERNS.each_key.compact_map(&.match(url)).first?
Expand Down Expand Up @@ -61,64 +60,3 @@ describe Crystal::Doc::Generator do
end
end
end

describe Crystal::Doc::ProjectInfo do
it "find_default_version" do
with_tempfile("docs-git-version") do |tempdir|
Dir.mkdir tempdir
Dir.cd(tempdir) do
# Non-git directory
Crystal::Doc::ProjectInfo.find_default_version.should be_nil

`git init`
Crystal::Doc::ProjectInfo.find_default_version.should be_nil

File.write("file.txt", "foo")
`git add file.txt`
`git commit -m 'Initial commit' --no-gpg-sign`
Crystal::Doc::ProjectInfo.find_default_version.should be_nil

`git tag v0.1.0`
`git tag --list`
`git log`
Crystal::Doc::ProjectInfo.find_default_version.should eq "v0.1.0"

File.write("file.txt", "bar")
Crystal::Doc::ProjectInfo.find_default_version.should be_nil

`git add file.txt`
Crystal::Doc::ProjectInfo.find_default_version.should be_nil

`git reset --hard v0.1.0`
Crystal::Doc::ProjectInfo.find_default_version.should eq "v0.1.0"

`git tag v0.2.0`
Crystal::Doc::ProjectInfo.find_default_version.should be_nil
end
end
end

it "find_default_name" do
with_tempfile("docs-shard-name") do |tempdir|
Dir.mkdir tempdir
Dir.cd(tempdir) do
Crystal::Doc::ProjectInfo.find_default_name.should be_nil

File.write("shard.yml", "foo: bar\n")
Crystal::Doc::ProjectInfo.find_default_name.should be_nil

File.write("shard.yml", "name: \n")
Crystal::Doc::ProjectInfo.find_default_name.should be_nil

File.write("shard.yml", " name: bar\n")
Crystal::Doc::ProjectInfo.find_default_name.should be_nil

File.write("shard.yml", "name: bar\n")
Crystal::Doc::ProjectInfo.find_default_name.should eq "bar"

File.write("shard.yml", "name: bar # comment\n")
Crystal::Doc::ProjectInfo.find_default_name.should eq "bar"
end
end
end
end
28 changes: 9 additions & 19 deletions src/compiler/crystal/command/docs.cr
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,15 @@ class Crystal::Command
setup_compiler_warning_options(opts, compiler)
end

project_info = create_project_info(project_name, project_version)
project_info = ProjectInfo.new_with_defaults(project_name, project_version) do |name, version|
unless name
STDERR.puts "Couldn't determine name from shard.yml, please provide --project-name option"
end
unless version
STDERR.puts "Couldn't determine version from git or shard.yml, please provide --project-version option"
end
abort
end

if options.empty?
sources = [Compiler::Source.new("require", %(require "./src/**"))]
Expand All @@ -120,22 +128,4 @@ class Crystal::Command
report_warnings result
exit 1 if warnings_fail_on_exit?(result)
end

private def create_project_info(name, version)
name ||= Doc::ProjectInfo.find_default_name
unless name
STDERR.puts "Couldn't determine name from shard.yml, please provide --project-name option"
end

version ||= Doc::ProjectInfo.find_default_version
unless version
STDERR.puts "Couldn't determine version from git, please provide --project-version option"
end

unless name && version
abort
end

Doc::ProjectInfo.new(name, version)
end
end
43 changes: 35 additions & 8 deletions src/compiler/crystal/tools/doc/project_info.cr
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
module Crystal::Doc
record ProjectInfo, name : String, version : String do
def self.find_default_version
def self.new_with_defaults(name, version)
version ||= find_git_version

unless name && version
shard_name, shard_version = read_shard_properties
name ||= shard_name
version ||= shard_version

unless name && version
return yield name, version
end
end

new(name, version)
end

def self.find_git_version
# Use git to determine if index and working directory are clean
io = IO::Memory.new
status = Process.run("git", ["status", "--porcelain"], output: io)
Expand All @@ -14,22 +30,33 @@ module Crystal::Doc
return unless status.success?
io.rewind
tags = io.to_s.lines
# Only accept when there's exactly one tag pointing at HEAD.
if tags.size == 1
tags.first
versions = tags.select(&.starts_with?("v"))
# Only accept when there's exactly one version tag pointing at HEAD.
if versions.size == 1
return versions.first.byte_slice(1)
end
end

def self.find_default_name
return unless File.readable?("shard.yml")
def self.read_shard_properties
return {nil, nil} unless File.readable?("shard.yml")

name = nil
version = nil

# Poor man's YAML reader
File.each_line("shard.yml") do |line|
if line.starts_with?("name:")
if name.nil? && line.starts_with?("name:")
end_pos = line.byte_index("#") || line.bytesize
return line.byte_slice(5, end_pos - 5).strip.presence
name = line.byte_slice(5, end_pos - 5).strip.strip(%("'))
elsif version.nil? && line.starts_with?("version:")
end_pos = line.byte_index("#") || line.bytesize
version = line.byte_slice(8, end_pos - 8).strip.strip(%("'))
elsif version && name
break
end
end

return name.presence, version.presence
end
end
end

0 comments on commit b5695ae

Please sign in to comment.