diff --git a/spec/compiler/crystal/tools/doc/project_info_spec.cr b/spec/compiler/crystal/tools/doc/project_info_spec.cr index 80bc36ddd447..e6c9b5a9742c 100644 --- a/spec/compiler/crystal/tools/doc/project_info_spec.cr +++ b/spec/compiler/crystal/tools/doc/project_info_spec.cr @@ -51,6 +51,27 @@ describe Crystal::Doc::ProjectInfo do ProjectInfo.new_with_defaults(nil, "1.1") { |name, version| "missing:#{name}:#{version}" }.should eq ProjectInfo.new("foo", "1.1") ProjectInfo.new_with_defaults("bar", "2.0") { |name, version| "missing:#{name}:#{version}" }.should eq ProjectInfo.new("bar", "2.0") end + + it "git non-tagged commit" do + `git init` + `git add shard.yml` + `git commit -m 'Initial commit' --no-gpg-sign` + + ProjectInfo.new_with_defaults(nil, nil) { |name, version| "missing:#{name}:#{version}" }.should eq ProjectInfo.new("foo", "master") + ProjectInfo.new_with_defaults(nil, "1.1") { |name, version| "missing:#{name}:#{version}" }.should eq ProjectInfo.new("foo", "1.1") + ProjectInfo.new_with_defaults("bar", "2.0") { |name, version| "missing:#{name}:#{version}" }.should eq ProjectInfo.new("bar", "2.0") + end + + it "git non-tagged commit dirty" do + `git init` + `git add shard.yml` + `git commit -m 'Initial commit' --no-gpg-sign` + File.write("foo.txt", "bar") + + ProjectInfo.new_with_defaults(nil, nil) { |name, version| "missing:#{name}:#{version}" }.should eq ProjectInfo.new("foo", "master-dev") + ProjectInfo.new_with_defaults(nil, "1.1") { |name, version| "missing:#{name}:#{version}" }.should eq ProjectInfo.new("foo", "1.1") + ProjectInfo.new_with_defaults("bar", "2.0") { |name, version| "missing:#{name}:#{version}" }.should eq ProjectInfo.new("bar", "2.0") + end end it "no shard.yml, but git tagged version" do @@ -70,28 +91,44 @@ describe Crystal::Doc::ProjectInfo do # Non-git directory ProjectInfo.find_git_version.should be_nil + # Empty git directory `git init` ProjectInfo.find_git_version.should be_nil + # Non-tagged commit File.write("file.txt", "foo") `git add file.txt` `git commit -m 'Initial commit' --no-gpg-sign` - ProjectInfo.find_git_version.should be_nil + ProjectInfo.find_git_version.should eq "master" + + # Non-tagged commit, dirty workdir + File.write("file.txt", "bar") + ProjectInfo.find_git_version.should eq "master-dev" + + `git checkout -- .` + # Tagged commit `git tag v0.1.0` ProjectInfo.find_git_version.should eq "0.1.0" + # Tagged commit, dirty workdir File.write("file.txt", "bar") - ProjectInfo.find_git_version.should be_nil + ProjectInfo.find_git_version.should eq "0.1.0-dev" + # Tagged commit, dirty index `git add file.txt` - ProjectInfo.find_git_version.should be_nil + ProjectInfo.find_git_version.should eq "0.1.0-dev" `git reset --hard v0.1.0` ProjectInfo.find_git_version.should eq "0.1.0" + # Multiple tags `git tag v0.2.0` - ProjectInfo.find_git_version.should be_nil + ProjectInfo.find_git_version.should eq "master" + + # Other branch + `git checkout -b foo` + ProjectInfo.find_git_version.should eq "foo" end describe ".read_shard_properties" do diff --git a/src/compiler/crystal/tools/doc/project_info.cr b/src/compiler/crystal/tools/doc/project_info.cr index 4f95ecd01060..6744253f4966 100644 --- a/src/compiler/crystal/tools/doc/project_info.cr +++ b/src/compiler/crystal/tools/doc/project_info.cr @@ -17,14 +17,30 @@ module Crystal::Doc end def self.find_git_version + if ref = git_ref + case git_clean? + when Nil + when true + ref + when false + "#{ref}-dev" + end + end + end + + def self.git_clean? # Use git to determine if index and working directory are clean io = IO::Memory.new status = Process.run("git", ["status", "--porcelain"], output: io) # If clean, output of `git status --porcelain` is empty. Still need to check # the status code, to make sure empty doesn't mean error. + return unless status.success? io.rewind - return unless status.success? && io.bytesize == 0 + io.bytesize == 0 + end + def self.git_ref + io = IO::Memory.new # Check if current HEAD is tagged status = Process.run("git", ["tag", "--points-at", "HEAD"], output: io) return unless status.success? @@ -35,6 +51,13 @@ module Crystal::Doc if versions.size == 1 return versions.first.byte_slice(1) end + + # Otherwise, return current branch name + io.clear + status = Process.run("git", ["rev-parse", "--abbrev-ref", "HEAD"], output: io) + return unless status.success? + + io.to_s.strip.presence end def self.read_shard_properties