Skip to content

Commit

Permalink
Versioning rework (#349)
Browse files Browse the repository at this point in the history
  • Loading branch information
waj authored Apr 14, 2020
1 parent 5be28ac commit bba99f2
Show file tree
Hide file tree
Showing 20 changed files with 294 additions and 247 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
/bin/shards.dwarf
/spec/.repositories
/spec/.shards
/spec/.lib
/spec/unit/.lib
/tmp
70 changes: 55 additions & 15 deletions spec/integration/install_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ describe "install" do
end
end

it "won't fail if version file is missing (backward compatibility)" do
metadata = {dependencies: {web: "*"}}
with_shard(metadata) do
run "shards install"
File.delete("lib/web.version")
run "shards install"
end
end

it "won't install prerelease version" do
metadata = {
dependencies: {unstable: "*"},
Expand Down Expand Up @@ -79,7 +88,7 @@ describe "install" do
}
with_shard(metadata) do
run "shards install"
assert_installed "unstable", "0.3.0.beta"
assert_installed "unstable", "0.3.0.beta", git: git_commits(:unstable).first
end
end

Expand Down Expand Up @@ -124,7 +133,7 @@ describe "install" do
it "resolves dependency at head when no version tags" do
metadata = {dependencies: {"missing": "*"}}
with_shard(metadata) { run "shards install" }
assert_installed "missing", "0.1.0"
assert_installed "missing", "0.1.0", git: git_commits(:missing).first
end

it "installs dependency at locked commit when refs is a branch" do
Expand All @@ -133,23 +142,23 @@ describe "install" do
web: {git: git_url(:web), branch: "master"},
},
}
lock = {web: git_commits(:web)[-5]}
lock = {web: "1.2.0+git.commit.#{git_commits(:web)[-5]}"}

with_shard(metadata, lock) do
run "shards install"
assert_installed "web", "1.2.0"
assert_installed "web", "1.2.0", git: git_commits(:web)[-5]
end
end

it "installs dependency at locked commit when refs is a version tag" do
metadata = {
dependencies: {web: {git: git_url(:web), tag: "v1.1.1"}},
}
lock = {web: git_commits(:web)[-3]}
lock = {web: "1.1.1+git.commit.#{git_commits(:web)[-3]}"}

with_shard(metadata, lock) do
run "shards install"
assert_installed "web", "1.1.1"
assert_installed "web", "1.1.1", git: git_commits(:web)[-3]
end
end

Expand All @@ -164,11 +173,11 @@ describe "install" do
},
}
lock = {
"locked": git_commits(:"locked").last,
"locked": "0.1.0+git.commit.#{git_commits(:"locked").last}",
}
with_shard(metadata, lock) { run "shards install" }

assert_installed "locked", "0.1.0"
assert_installed "locked", "0.1.0", git: git_commits(:locked).last
refute_installed "pg"
end

Expand All @@ -177,14 +186,14 @@ describe "install" do
dependencies: {web: {git: git_url(:web), branch: "master"}},
}

with_shard(metadata, {web: git_commits(:web)[-5]}) do
with_shard(metadata, {web: "1.2.0+git.commit.#{git_commits(:web)[-5]}"}) do
run "shards install"
assert_installed "web", "1.2.0"
assert_installed "web", "1.2.0", git: git_commits(:web)[-5]
end

with_shard(metadata, {web: git_commits(:web)[0]}) do
with_shard(metadata, {web: "2.1.0+git.commit.#{git_commits(:web)[0]}"}) do
run "shards install"
assert_installed "web", "2.1.0"
assert_installed "web", "2.1.0", git: git_commits(:web)[0]
end
end

Expand All @@ -202,7 +211,7 @@ describe "install" do

it "fails to install when dependency requirement (commit) changed in production" do
metadata = {dependencies: {inprogress: {git: git_url(:inprogress), commit: git_commits(:inprogress)[1]}}}
lock = {inprogress: git_commits(:inprogress).first}
lock = {inprogress: "0.1.0+git.commit.#{git_commits(:inprogress).first}"}

with_shard(metadata, lock) do
ex = expect_raises(FailedCommand) { run "shards install --no-color --production" }
Expand Down Expand Up @@ -275,7 +284,7 @@ describe "install" do

with_shard(metadata) do
run "shards install"
assert_locked "web", git_commits(:web).first
assert_locked "web", "2.1.0", git: git_commits(:web).first
end
end

Expand Down Expand Up @@ -318,6 +327,37 @@ describe "install" do
end
end

it "install in production mode" do
metadata = {dependencies: {web: "*"}}
lock = {web: "1.0.0"}

with_shard(metadata, lock) do
run "shards install --production"
assert_installed "web", "1.0.0"
end
end

it "install in production mode with locked commit" do
metadata = {dependencies: {web: "*"}}
web_version = "2.1.0+git.commit.#{git_commits(:web).first}"
lock = {web: web_version}

with_shard(metadata, lock) do
run "shards install --production"
assert_installed "web", "2.1.0", git: git_commits(:web).first
end
end

it "install in production mode with locked commit by a previous shards version" do
metadata = {dependencies: {web: "*"}}

with_shard(metadata) do
File.write "shard.lock", {version: "1.0", shards: {web: {git: git_url(:web), commit: git_commits(:web).first}}}
run "shards install --production"
assert_installed "web", "2.1.0", git: git_commits(:web).first
end
end

it "doesn't generate lockfile when project has no dependencies" do
with_shard({name: "test"}) do
run "shards install"
Expand Down Expand Up @@ -458,7 +498,7 @@ describe "install" do
}
with_shard(metadata) do
run "shards install"
assert_installed "another_name", "0.3.0"
assert_installed "another_name", "0.3.0", git: git_commits(:renamed).first
end
end

Expand Down
4 changes: 3 additions & 1 deletion spec/integration/prune_spec.cr
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
require "./spec_helper"

private def installed_dependencies
Dir.glob(File.join(application_path, "lib", "*"), match_hidden: true).map { |path| File.basename(path) }
Dir.glob(File.join(application_path, "lib", "*"), match_hidden: true)
.map { |path| File.basename(path) }
.reject(&.ends_with?(".version"))
end

describe "prune" do
Expand Down
21 changes: 6 additions & 15 deletions spec/integration/spec_helper.cr
Original file line number Diff line number Diff line change
Expand Up @@ -111,18 +111,12 @@ private def refute(value, message, file, line)
fail(message, file, line) if value
end

def assert_installed(name, version = nil, file = __FILE__, line = __LINE__)
def assert_installed(name, version = nil, file = __FILE__, line = __LINE__, *, git = nil)
assert Dir.exists?(install_path(name)), "expected #{name} dependency to have been installed", file, line

if version
assert File.exists?(install_path(name, "shard.yml")), "expected shard.yml for installed #{name} dependency was not found", file, line
spec = Shards::Spec.from_file(install_path(name, "shard.yml"))

if spec.version == "0" && File.exists?(install_path("#{name}.sha1"))
File.read(install_path("#{name}.sha1")).should eq(version), file, line
else
spec.version.should eq(version), file, line
end
expected_version = git ? "#{version}+git.commit.#{git}" : version
File.read(install_path("#{name}.version")).should eq(expected_version), file, line
end
end

Expand All @@ -142,18 +136,15 @@ def assert_installed_file(path, file = __FILE__, line = __LINE__)
assert File.exists?(File.join(install_path(name), path)), "Expected #{path} to have been installed", file, line
end

def assert_locked(name, version = nil, file = __FILE__, line = __LINE__)
def assert_locked(name, version = nil, file = __FILE__, line = __LINE__, *, git = nil)
path = File.join(application_path, "shard.lock")
assert File.exists?(path), "expected shard.lock to have been generated", file, line
locks = Shards::Lock.from_file(path)
assert lock = locks.find { |d| d.name == name }, "expected #{name} dependency to have been locked", file, line

if lock && version
if version =~ Shards::VERSION_REFERENCE
assert version == lock.version, "expected #{name} dependency to have been locked at version #{version}", file, line
else
assert version == lock.refs, "expected #{name} dependency to have been locked at commit #{version}", file, line
end
expected_version = git ? "#{version}+git.commit.#{git}" : version
assert expected_version == lock.version, "expected #{name} dependency to have been locked at version #{version}", file, line
end
end

Expand Down
3 changes: 2 additions & 1 deletion spec/integration/update_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,8 @@ describe "update" do

with_shard(metadata, lock) do
run "shards update"
assert_installed "web", "2.1.0"
assert_installed "web", "2.1.0", git: git_commits(:web).first
assert_locked "web", "2.1.0", git: git_commits(:web).first
end
end

Expand Down
21 changes: 6 additions & 15 deletions spec/support/cli.cr
Original file line number Diff line number Diff line change
Expand Up @@ -70,21 +70,12 @@ end
def to_lock_yaml(lock)
return unless lock

String.build do |yml|
yml << "version: 1.0\n"
yml << "shards:\n"

lock.each do |name, version|
yml << " " << name << ":\n"
yml << " git: " << git_url(name).inspect << '\n'

if version =~ /^[\d\.]+$/
yml << " version: " << version.inspect << '\n'
else
yml << " commit: " << version.inspect << '\n'
end
end
end
YAML.dump({
version: "1.0",
shards: lock.to_a.to_h do |name, version|
{name, {git: git_url(name), version: version}}
end,
})
end

module Shards::Specs
Expand Down
16 changes: 14 additions & 2 deletions spec/support/factories.cr
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,18 @@ def create_git_commit(project, message = "new commit")
end
end

def checkout_new_git_branch(project, branch)
Dir.cd(git_path(project)) do
run "git checkout -b #{branch}"
end
end

def checkout_git_branch(project, branch)
Dir.cd(git_path(project)) do
run "git checkout #{branch}"
end
end

def create_shard(project, contents)
create_file project, "shard.yml", contents
end
Expand All @@ -71,9 +83,9 @@ def create_file(project, filename, contents, perm = nil)
File.chmod(path, perm) if perm
end

def git_commits(project)
def git_commits(project, rev = "HEAD")
Dir.cd(git_path(project)) do
run("git log --format='%H'").strip.split('\n')
run("git log --format='%H' #{rev}").strip.split('\n')
end
end

Expand Down
52 changes: 42 additions & 10 deletions spec/unit/git_resolver_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,60 @@ private def resolver(name)
end

module Shards
describe PathResolver do
describe GitResolver do
before_each do
create_git_repository "empty"
create_git_commit "empty", "initial release"

create_git_repository "unreleased"
create_git_version_commit "unreleased", "0.1.0"
checkout_new_git_branch "unreleased", "branch"
create_git_commit "unreleased", "testing"
checkout_git_branch "unreleased", "master"

create_git_repository "library", "0.0.1", "0.1.0", "0.1.1", "0.1.2"
create_git_release "library", "0.2.0", shard: "name: library\nversion: 0.2.0\nauthors:\n - julien <[email protected]>"

# Create a version tag not prefixed by 'v' which should be ignored
create_git_tag "library", "99.9.9"
end

it "available versions" do
resolver("empty").available_versions.should eq(["HEAD"])
resolver("library").available_versions.should eq(["0.0.1", "0.1.0", "0.1.1", "0.1.2", "0.2.0"])
it "available releases" do
resolver("empty").available_releases.should be_empty
resolver("library").available_releases.should eq(["0.0.1", "0.1.0", "0.1.1", "0.1.2", "0.2.0"])
end

it "latest version for ref" do
resolver("empty").latest_version_for_ref("master").should be_nil
resolver("empty").latest_version_for_ref(nil).should be_nil
resolver("unreleased").latest_version_for_ref("master").should eq("0.1.0+git.commit.#{git_commits(:unreleased)[0]}")
resolver("unreleased").latest_version_for_ref("branch").should eq("0.1.0+git.commit.#{git_commits(:unreleased, "branch")[0]}")
resolver("unreleased").latest_version_for_ref(nil).should eq("0.1.0+git.commit.#{git_commits(:unreleased)[0]}")
resolver("library").latest_version_for_ref("master").should eq("0.2.0+git.commit.#{git_commits(:library)[0]}")
resolver("library").latest_version_for_ref(nil).should eq("0.2.0+git.commit.#{git_commits(:library)[0]}")
resolver("library").latest_version_for_ref("foo").should be_nil
end

it "versions for" do
resolver("empty").versions_for(Dependency.new("empty")).should be_empty
resolver("library").versions_for(Dependency.new("library")).should eq(["0.0.1", "0.1.0", "0.1.1", "0.1.2", "0.2.0"])
resolver("library").versions_for(Dependency.new("library", version: "~> 0.1.0")).should eq(["0.1.0", "0.1.1", "0.1.2"])
resolver("library").versions_for(Dependency.new("library", branch: "master")).should eq(["0.2.0+git.commit.#{git_commits(:library)[0]}"])
resolver("unreleased").versions_for(Dependency.new("unreleased", branch: "master")).should eq(["0.1.0+git.commit.#{git_commits(:unreleased)[0]}"])
resolver("unreleased").versions_for(Dependency.new("unreleased")).should eq(["0.1.0+git.commit.#{git_commits(:unreleased)[0]}"])
end

it "read spec for release" do
spec = resolver("library").spec("0.1.1")
spec.original_version.should eq("0.1.1")
spec.version.should eq("0.1.1")
end

it "read spec" do
expect_raises(Error) { resolver("empty").read_spec }
resolver("library").read_spec.should eq("name: library\nversion: 0.2.0\nauthors:\n - julien <[email protected]>")
resolver("library").read_spec("0.1.1").should eq("name: library\nversion: 0.1.1\n")
resolver("library").read_spec("0.1.1").should eq("name: library\nversion: 0.1.1\n")
it "read spec for commit" do
version = "0.2.0+git.commit.#{git_commits(:library)[0]}"
spec = resolver("library").spec(version)
spec.original_version.should eq("0.2.0")
spec.version.should eq(version)
end

it "install" do
Expand All @@ -39,7 +71,7 @@ module Shards
library.installed_spec.not_nil!.version.should eq("0.1.2")
# File.exists?(install_path("library", "LICENSE")).should be_true

library.install
library.install("0.2.0")
library.installed_spec.not_nil!.version.should eq("0.2.0")
end

Expand Down
Loading

0 comments on commit bba99f2

Please sign in to comment.