dply 0.2.19 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.rspec +4 -0
- data/Rakefile +0 -14
- data/TODO +0 -1
- data/code_dump/old_remote_task.rb +2 -0
- data/{dev_bin → dev_exe}/dplyr +0 -0
- data/{dev_bin → dev_exe}/drake +1 -1
- data/dply.gemspec +2 -2
- data/{bin → exe}/dplyr +0 -0
- data/{bin → exe}/drake +12 -14
- data/lib/dply/TEST_TODO +50 -0
- data/lib/dply/app_config.rb +108 -0
- data/lib/dply/base_config.rb +110 -0
- data/lib/dply/build.rb +17 -11
- data/lib/dply/build_config.rb +28 -96
- data/lib/dply/bundle.rb +7 -30
- data/lib/dply/cli/build.rb +5 -12
- data/lib/dply/cli/ctl.rb +7 -8
- data/lib/dply/cli/deploy.rb +6 -10
- data/lib/dply/cli/devbuild.rb +6 -10
- data/lib/dply/cli/install_pkgs.rb +2 -3
- data/lib/dply/cli/run.rb +27 -0
- data/lib/dply/cli/status.rb +1 -2
- data/lib/dply/cli/task.rb +6 -12
- data/lib/dply/code_archive.rb +123 -0
- data/lib/dply/command.rb +57 -0
- data/lib/dply/config_downloader.rb +3 -2
- data/lib/dply/curl.rb +1 -5
- data/lib/dply/custom_logger.rb +18 -1
- data/lib/dply/deplist.rb +16 -48
- data/lib/dply/deploy_config.rb +34 -0
- data/lib/dply/elf.rb +60 -0
- data/lib/dply/env.rb +9 -0
- data/lib/dply/git.rb +15 -8
- data/lib/dply/helper.rb +21 -33
- data/lib/dply/linker.rb +27 -27
- data/lib/dply/lock.rb +2 -9
- data/lib/dply/logger.rb +1 -1
- data/lib/dply/pkgs.rb +9 -11
- data/lib/dply/release.rb +2 -2
- data/lib/dply/{archive.rb → remote_archive.rb} +1 -1
- data/lib/dply/repo.rb +3 -3
- data/lib/dply/rpm.rb +12 -20
- data/lib/dply/scripts/depcheck.rb +4 -0
- data/lib/dply/shared_dirs.rb +1 -1
- data/lib/dply/strategy/archive.rb +15 -22
- data/lib/dply/strategy/base.rb +82 -0
- data/lib/dply/strategy/git.rb +18 -19
- data/lib/dply/task_dsl.rb +101 -0
- data/lib/dply/util.rb +75 -0
- data/lib/dply/venv.rb +53 -0
- data/lib/dply/version.rb +1 -1
- data/lib/dply/yum.rb +21 -31
- data/lib/dplyr/consul.rb +1 -1
- data/spec/dply/base_config_spec.rb +178 -0
- data/spec/dply/bundle_spec.rb +100 -0
- data/spec/dply/command_spec.rb +190 -0
- data/spec/dply/curl_spec.rb +41 -0
- data/spec/dply/deplist_spec.rb +48 -0
- data/spec/dply/elf_spec.rb +64 -0
- data/spec/dply/env_spec.rb +57 -0
- data/spec/dply/git_spec.rb +136 -0
- data/spec/dply/helper_spec.rb +168 -0
- data/spec/dply/linker_spec.rb +81 -0
- data/spec/dply/lock_spec.rb +24 -0
- data/spec/dply/pkgs_spec.rb +105 -0
- data/spec/dply/repo_spec.rb +58 -0
- data/spec/dply/rpm_spec.rb +32 -0
- data/spec/dply/yum_spec.rb +29 -0
- data/spec/integration/archive_flow_spec.rb +87 -0
- data/spec/integration/git_flow_spec.rb +63 -0
- data/spec/repo.rb +27 -0
- data/spec/spec_helper.rb +44 -0
- data/spec/test_data/build.tar.gz +0 -0
- data/spec/test_data/build.tar.gz.md5 +1 -0
- data/spec/test_data/bundle/gems_installed/Gemfile +1 -0
- data/spec/test_data/bundle/gems_not_installed/Gemfile +2 -0
- data/spec/test_data/bundle/no_gemfile/.gitkeep +0 -0
- data/spec/test_data/command/test.rb +7 -0
- data/spec/test_data/elf/elf +0 -0
- data/spec/test_data/elf/libpgtypes.so.3 +0 -0
- data/spec/test_data/elf/not_elf +1 -0
- data/spec/test_data/sample_repo/.dply.lock +0 -0
- data/spec/test_data/sample_repo/Gemfile +2 -0
- data/spec/test_data/sample_repo/Rakefile +3 -0
- data/spec/test_data/sample_repo/app.rb +1 -0
- data/spec/test_data/sample_repo/dply/app.rb +33 -0
- data/spec/test_data/sample_repo/lib/libacl.so.1 +0 -0
- data/spec/test_data/sample_repo/pkgs.yml +2 -0
- data/spec/webserver.rb +21 -0
- metadata +96 -28
- data/lib/dply/cli/app_task.rb +0 -38
- data/lib/dply/config.rb +0 -120
- data/lib/dply/config_struct.rb +0 -52
- data/lib/dply/rakelib/drake.rake +0 -33
- data/lib/dply/tasks.rb +0 -136
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require 'dply/curl'
|
|
2
|
+
|
|
3
|
+
module Dply
|
|
4
|
+
describe Curl do
|
|
5
|
+
|
|
6
|
+
let(:url) { "http://127.0.0.1:8000/build.tar.gz" }
|
|
7
|
+
|
|
8
|
+
describe "#download(url, file)" do
|
|
9
|
+
it "downloads the url to file" do
|
|
10
|
+
Dir.mktmpdir do |dir|
|
|
11
|
+
f = "#{dir}/f"
|
|
12
|
+
curl = Curl.new
|
|
13
|
+
expect(Logger.logger).to receive(:bullet).with("downloading #{url}")
|
|
14
|
+
curl.download(url, f)
|
|
15
|
+
expect(File).to exist(f)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "raises error when url doesn't exist" do
|
|
20
|
+
url = "http://127.0.0.1:8000/build"
|
|
21
|
+
Dir.mktmpdir do |dir|
|
|
22
|
+
f = "#{dir}/f"
|
|
23
|
+
curl = Curl.new
|
|
24
|
+
expect(Logger.logger).to receive(:bullet).with("downloading #{url}")
|
|
25
|
+
expect { curl.download(url, f) }.to raise_error(Error)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "logs message to debug when quiet: true" do
|
|
30
|
+
Dir.mktmpdir do |dir|
|
|
31
|
+
f = "#{dir}/f"
|
|
32
|
+
curl = Curl.new(quiet: true)
|
|
33
|
+
expect(Logger.logger).to receive(:debug).with("downloading #{url}")
|
|
34
|
+
curl.download(url, f)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
silence_warnings do
|
|
2
|
+
require 'dply/deplist'
|
|
3
|
+
end
|
|
4
|
+
|
|
5
|
+
module Dply
|
|
6
|
+
describe Deplist do
|
|
7
|
+
|
|
8
|
+
before :all do
|
|
9
|
+
@work_dir = "tmp/deplist"
|
|
10
|
+
FileUtils.rm_rf @work_dir
|
|
11
|
+
FileUtils.mkdir_p @work_dir
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def tmp_dir(&block)
|
|
15
|
+
d = Dir.mktmpdir nil, "#{Dir.pwd}/#{@work_dir}"
|
|
16
|
+
FileUtils.cp "spec/test_data/sample_repo/lib/libacl.so.1", "#{d}/libacl.so.1"
|
|
17
|
+
Dir.chdir(d) { yield d }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe "#verify!" do
|
|
21
|
+
|
|
22
|
+
it "doesn't throw an error when pkgs.yml has the required pkgs" do
|
|
23
|
+
pkgs_data = { "pkgs" => ["libattr"], "build_pkgs" => [] }
|
|
24
|
+
tmp_dir do
|
|
25
|
+
File.write "pkgs.yml", YAML.dump(pkgs_data)
|
|
26
|
+
system! "tar czf test.tar.gz pkgs.yml libacl.so.1"
|
|
27
|
+
deplist = Deplist.new("test.tar.gz")
|
|
28
|
+
silence_warnings do
|
|
29
|
+
expect { deplist.verify! }.to output(/all dependencies satisfied/).to_stdout_from_any_process
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "throws an error when pkgs.yml doesn't have the required pkgs" do
|
|
35
|
+
pkgs_data = { "pkgs" => [], "build_pkgs" => [] }
|
|
36
|
+
tmp_dir do
|
|
37
|
+
File.write "pkgs.yml", YAML.dump(pkgs_data)
|
|
38
|
+
system! "tar czf test.tar.gz pkgs.yml libacl.so.1"
|
|
39
|
+
deplist = Deplist.new("test.tar.gz")
|
|
40
|
+
silence_warnings do
|
|
41
|
+
expect { deplist.verify! }.to raise_error(Error).and output(/any of \["libattr"\]/).to_stdout_from_any_process
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
silence_warnings do
|
|
2
|
+
require 'elf'
|
|
3
|
+
end
|
|
4
|
+
require 'dply/elf'
|
|
5
|
+
require 'pathname'
|
|
6
|
+
|
|
7
|
+
module Dply
|
|
8
|
+
describe Elf do
|
|
9
|
+
|
|
10
|
+
before :all do
|
|
11
|
+
@verbose = $VERBOSE
|
|
12
|
+
$VERBOSE = false
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
let(:work_dir) { Pathname.new("#{__dir__}/../test_data/elf").realpath }
|
|
16
|
+
|
|
17
|
+
def map_64bit(list)
|
|
18
|
+
list.map { |i| "#{i}()(64bit)" }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
describe ".elf?" do
|
|
22
|
+
it "returns true if file is an ELF" do
|
|
23
|
+
expect(Elf.elf? "#{work_dir}/elf").to eq(true)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "returns false if file is not an ELF" do
|
|
27
|
+
expect(Elf.elf? "#{work_dir}/not_elf").to eq(false)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "returns false if file doesn't exist" do
|
|
31
|
+
expect(Elf.elf? "#{work_dir}/nofile").to eq(false)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
describe "#external_libs" do
|
|
36
|
+
it "returns a list of external libs when elf has no rpath section" do
|
|
37
|
+
libs = map_64bit ["libattr.so.1", "libc.so.6"]
|
|
38
|
+
elf = Elf.new("#{work_dir}/elf")
|
|
39
|
+
expect(elf.external_libs).to match_array(libs)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
context "when elf has absolute rpath or runpath" do
|
|
43
|
+
it "returns all external libs ignoring rpath" do
|
|
44
|
+
libs = map_64bit ["libpq.so.5", "libc.so.6", "libpgtypes.so.3", "libpthread.so.0"]
|
|
45
|
+
elf = Elf.new("#{work_dir}/libecpg.so")
|
|
46
|
+
expect(elf.external_libs).to match_array(libs)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
context "when elf contains a relative rpath or runpath" do
|
|
51
|
+
it "returns all external libs excluding the ones found in relative rpath" do
|
|
52
|
+
libs = map_64bit ["libpq.so.5", "libc.so.6", "libpthread.so.0"]
|
|
53
|
+
elf = Elf.new("#{work_dir}/rpath_libecpg.so")
|
|
54
|
+
expect(elf.external_libs).to match_array(libs)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
after :all do
|
|
60
|
+
$VERBOSE = @verbose
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
require 'dply/env'
|
|
2
|
+
|
|
3
|
+
module Dply
|
|
4
|
+
describe Env do
|
|
5
|
+
|
|
6
|
+
ORIGINAL_ENV = { "O1" => "1", "O2" => "2" }
|
|
7
|
+
CURRENT_ENV = { "C1" => "1", "C2" => "2" }
|
|
8
|
+
EXTRA_ENV = { "O1" => "E", "C1" => "E" }
|
|
9
|
+
|
|
10
|
+
def stub_env(with_bundler:)
|
|
11
|
+
allow(ENV).to receive(:to_h).and_return(CURRENT_ENV)
|
|
12
|
+
if with_bundler
|
|
13
|
+
stub_const("Bundler", "bundler")
|
|
14
|
+
allow(Bundler).to receive(:original_env).and_return(ORIGINAL_ENV)
|
|
15
|
+
else
|
|
16
|
+
hide_const("Bundler")
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe '.build_env (extra_env, bundled_env:)' do
|
|
21
|
+
context "when bundler is defined and bundled_env: true" do
|
|
22
|
+
it "merges current_env with extra_env" do
|
|
23
|
+
stub_env with_bundler: true
|
|
24
|
+
env = Env.build_env(EXTRA_ENV, bundled_env: true)
|
|
25
|
+
expect(env).to eq(CURRENT_ENV.merge(EXTRA_ENV))
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
context "when bundler is defined and bundled_env: false" do
|
|
30
|
+
it "merges original_env with extra_env" do
|
|
31
|
+
stub_env with_bundler: true
|
|
32
|
+
env = Env.build_env(EXTRA_ENV, bundled_env: false)
|
|
33
|
+
expect(env).to eq(ORIGINAL_ENV.merge(EXTRA_ENV))
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
context "when bundler is not defined and bundled_env: true" do
|
|
38
|
+
it "merges current_env with extra_env" do
|
|
39
|
+
stub_env with_bundler: false
|
|
40
|
+
env = Env.build_env(EXTRA_ENV, bundled_env: true)
|
|
41
|
+
expect(env).to eq(CURRENT_ENV.merge(EXTRA_ENV))
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
context "when bundler is defined and bundled_env: false" do
|
|
46
|
+
it "merges current_env with extra_env" do
|
|
47
|
+
stub_env with_bundler: false
|
|
48
|
+
env = Env.build_env(EXTRA_ENV, bundled_env: true)
|
|
49
|
+
expect(env).to eq(CURRENT_ENV.merge(EXTRA_ENV))
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
require 'dply/git'
|
|
2
|
+
require 'repo'
|
|
3
|
+
|
|
4
|
+
module Dply
|
|
5
|
+
describe Git do
|
|
6
|
+
|
|
7
|
+
before :all do
|
|
8
|
+
@work_dir = "tmp/git"
|
|
9
|
+
@source_repo = "#{Dir.pwd}/tmp/repo.git"
|
|
10
|
+
FileUtils.rm_rf @work_dir
|
|
11
|
+
FileUtils.mkdir_p @work_dir
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def source_repo
|
|
15
|
+
@source_repo
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def tmp_dir(&block)
|
|
19
|
+
d = Dir.mktmpdir nil, "#{Dir.pwd}/#{@work_dir}"
|
|
20
|
+
Dir.chdir(d) { yield d }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe ".pull" do
|
|
24
|
+
it "checks out the given branch and pulls any changes to it from upstream" do
|
|
25
|
+
tmp_dir do |d|
|
|
26
|
+
upstream = "#{d}/upstream"
|
|
27
|
+
system! "git clone #{source_repo} upstream"
|
|
28
|
+
system! "git clone #{upstream} repo"
|
|
29
|
+
Dir.chdir "upstream" do
|
|
30
|
+
system! "git checkout -b new_data"
|
|
31
|
+
system! "echo 'new_data' > new_data"
|
|
32
|
+
system! "git add new_data; git commit -m 'commit'"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
Dir.chdir "repo" do
|
|
36
|
+
suppress_output { Git.pull "new_data" }
|
|
37
|
+
expect(`git rev-parse --abbrev-ref HEAD`.chomp).to eq('new_data')
|
|
38
|
+
expect(File).to exist('new_data')
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
describe ".checkout" do
|
|
45
|
+
it "checks out the given branch" do
|
|
46
|
+
upstream = source_repo
|
|
47
|
+
tmp_dir do
|
|
48
|
+
system! "git clone #{upstream} repo", quiet: true
|
|
49
|
+
Dir.chdir "repo" do
|
|
50
|
+
# local tracking branch doesn't exist
|
|
51
|
+
suppress_output { Git.checkout "some_branch" }
|
|
52
|
+
expect(`git rev-parse --abbrev-ref HEAD`.chomp).to eq("some_branch")
|
|
53
|
+
|
|
54
|
+
#local tracking branch exists
|
|
55
|
+
suppress_output { Git.checkout "master" }
|
|
56
|
+
expect(`git rev-parse --abbrev-ref HEAD`.chomp).to eq("master")
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
describe ".clone" do
|
|
63
|
+
it "clones the repo from mirror and sets the upstream to original" do
|
|
64
|
+
mirror = source_repo
|
|
65
|
+
original = "/some/original/repo.git"
|
|
66
|
+
tmp_dir do
|
|
67
|
+
suppress_output { Git.clone original, "repo", mirror: mirror }
|
|
68
|
+
Dir.chdir "repo" do
|
|
69
|
+
expect(Git.remote_url).to eq(original)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "clones the repo from original source when mirror is not specified" do
|
|
75
|
+
original = source_repo
|
|
76
|
+
tmp_dir do
|
|
77
|
+
suppress_output { Git.clone original, "repo", mirror: nil }
|
|
78
|
+
Dir.chdir "repo" do
|
|
79
|
+
expect(Git.remote_url).to eq(original)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
describe ".clean" do
|
|
86
|
+
it "cleans any changes made to the working tree (resets HEAD state and removes untracked files)" do
|
|
87
|
+
upstream = source_repo
|
|
88
|
+
tmp_dir do
|
|
89
|
+
system! "git clone #{upstream} repo", quiet: true
|
|
90
|
+
Dir.chdir "repo" do
|
|
91
|
+
system! "echo asda > my_new_file" #new
|
|
92
|
+
system! "echo existing > Gemfile" #existing
|
|
93
|
+
suppress_output { Git.clean }
|
|
94
|
+
lines = IO.popen(%w(git status --porcelain)) { |f| f.readlines }
|
|
95
|
+
expect(lines.size).to eq(0)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
describe ".tracking_branch" do
|
|
102
|
+
it "returns the tracking branch for given branch" do
|
|
103
|
+
upstream = source_repo
|
|
104
|
+
branch = "some_branch"
|
|
105
|
+
tmp_dir do
|
|
106
|
+
system! "git clone #{upstream} repo", quiet: true
|
|
107
|
+
Dir.chdir "repo" do
|
|
108
|
+
system! "git checkout -b #{branch} -t origin/#{branch}", quiet: true
|
|
109
|
+
expect(Git.tracking_branch(branch)).to eq("origin/#{branch}")
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
describe ".remote_url" do
|
|
116
|
+
it "returns the url for origin upstream" do
|
|
117
|
+
upstream = source_repo
|
|
118
|
+
tmp_dir do |d|
|
|
119
|
+
system! "git clone #{upstream} repo", quiet: true
|
|
120
|
+
Dir.chdir("repo") do
|
|
121
|
+
expect(Git.remote_url).to eq(upstream)
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
describe ".commit_id" do
|
|
128
|
+
it "returns the commit id" do
|
|
129
|
+
Dir.chdir source_repo do
|
|
130
|
+
commit_id = `git rev-parse HEAD`.chomp
|
|
131
|
+
expect(Git.commit_id).to eq(commit_id)
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
require 'dply/helper'
|
|
2
|
+
require 'pathname'
|
|
3
|
+
|
|
4
|
+
module Dply
|
|
5
|
+
describe Helper do
|
|
6
|
+
|
|
7
|
+
before :all do
|
|
8
|
+
@work_dir = "tmp/helper"
|
|
9
|
+
FileUtils.rm_rf @work_dir
|
|
10
|
+
FileUtils.mkdir_p @work_dir
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
klass = Class.new { include Helper }
|
|
14
|
+
subject { klass.new }
|
|
15
|
+
|
|
16
|
+
def tmp_dir(&block)
|
|
17
|
+
d = Dir.mktmpdir nil, "#{Dir.pwd}/#{@work_dir}"
|
|
18
|
+
Dir.chdir(d) { yield d }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
describe "#cmd" do
|
|
22
|
+
command = "touch a"
|
|
23
|
+
display = :a
|
|
24
|
+
env = {"a" => "1" }
|
|
25
|
+
bundled_env = :benv
|
|
26
|
+
new_env = {"e" => "1"}
|
|
27
|
+
|
|
28
|
+
let(:cmd_proc) do
|
|
29
|
+
Proc.new do |return_output|
|
|
30
|
+
subject.cmd command, env: env, bundled_env: bundled_env,
|
|
31
|
+
return_output: return_output, display: display
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "runs the command as expected when return_output: true" do
|
|
36
|
+
return_output = true
|
|
37
|
+
cmd_double = double
|
|
38
|
+
output = "output"
|
|
39
|
+
expect(Logger.logger).to receive(:command).with(command, mode: display)
|
|
40
|
+
expect(Env).to receive(:build_env).with(env, bundled_env: bundled_env).and_return(new_env)
|
|
41
|
+
expect(Command).to receive(:new).with(command, env: new_env, shell: false).and_return(cmd_double)
|
|
42
|
+
expect(cmd_double).to receive(:capture).and_return(output)
|
|
43
|
+
out = cmd_proc.call(return_output)
|
|
44
|
+
expect(out).to eq(output)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "runs the command as expected when return_output: false" do
|
|
48
|
+
return_output = false
|
|
49
|
+
cmd_double = double
|
|
50
|
+
expect(Logger.logger).to receive(:command).with(command, mode: display)
|
|
51
|
+
expect(Env).to receive(:build_env).with(env, bundled_env: bundled_env).and_return(new_env)
|
|
52
|
+
expect(Command).to receive(:new).with(command, env: new_env, shell: false).and_return(cmd_double)
|
|
53
|
+
expect(cmd_double).to receive(:run)
|
|
54
|
+
cmd_proc.call(return_output)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
describe "#sh" do
|
|
59
|
+
command = "touch a"
|
|
60
|
+
display = :a
|
|
61
|
+
env = {"a" => "1" }
|
|
62
|
+
bundled_env = :benv
|
|
63
|
+
new_env = {"e" => "1"}
|
|
64
|
+
|
|
65
|
+
let(:sh_proc) do
|
|
66
|
+
Proc.new do |return_output|
|
|
67
|
+
subject.sh command, env: env, bundled_env: bundled_env,
|
|
68
|
+
return_output: return_output, display: display
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it "runs the command as expected when return_output: true" do
|
|
73
|
+
return_output = true
|
|
74
|
+
sh_double = double
|
|
75
|
+
output = "output"
|
|
76
|
+
expect(Logger.logger).to receive(:command).with(command, mode: display)
|
|
77
|
+
expect(Env).to receive(:build_env).with(env, bundled_env: bundled_env).and_return(new_env)
|
|
78
|
+
expect(Command).to receive(:new).with(command, env: new_env, shell: true).and_return(sh_double)
|
|
79
|
+
expect(sh_double).to receive(:capture).and_return(output)
|
|
80
|
+
out = sh_proc.call(return_output)
|
|
81
|
+
expect(out).to eq(output)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "runs the command as expected when return_output: false" do
|
|
85
|
+
return_output = false
|
|
86
|
+
sh_double = double
|
|
87
|
+
expect(Logger.logger).to receive(:command).with(command, mode: display)
|
|
88
|
+
expect(Env).to receive(:build_env).with(env, bundled_env: bundled_env).and_return(new_env)
|
|
89
|
+
expect(Command).to receive(:new).with(command, env: new_env, shell: true).and_return(sh_double)
|
|
90
|
+
expect(sh_double).to receive(:run)
|
|
91
|
+
sh_proc.call(return_output)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
describe "#symlink" do
|
|
96
|
+
it "creates symlink dst -> src" do
|
|
97
|
+
tmp_dir do
|
|
98
|
+
FileUtils.touch "src"
|
|
99
|
+
subject.symlink "src", "dst"
|
|
100
|
+
expect(File.realpath("dst")).to eq(File.realpath("src"))
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it "does nothing if the link exists" do
|
|
105
|
+
tmp_dir do
|
|
106
|
+
FileUtils.touch "src"
|
|
107
|
+
FileUtils.ln_s "src", "dst"
|
|
108
|
+
expect(FileUtils).not_to receive(:ln_s)
|
|
109
|
+
subject.symlink "src", "dst"
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it "does not call ln_s when link exists and src/dest are Pathnames" do
|
|
114
|
+
tmp_dir do
|
|
115
|
+
FileUtils.touch "src"
|
|
116
|
+
FileUtils.ln_s "src", "dst"
|
|
117
|
+
expect(FileUtils).not_to receive(:ln_s)
|
|
118
|
+
subject.symlink Pathname.new("src"), Pathname.new("dst")
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it "replaces existing dst -> src(file) link atomically (using move op)" do
|
|
123
|
+
tmp_dir do
|
|
124
|
+
FileUtils.touch "src"
|
|
125
|
+
FileUtils.touch "src1"
|
|
126
|
+
FileUtils.ln_s "src1", "dst"
|
|
127
|
+
prev_inode = File.stat("dst").ino
|
|
128
|
+
|
|
129
|
+
#atomic rename
|
|
130
|
+
dir = File.dirname("dst")
|
|
131
|
+
expect(subject).to receive(:cmd).with(array_including("mv", dir), display: false).and_call_original
|
|
132
|
+
|
|
133
|
+
subject.symlink "src", "dst"
|
|
134
|
+
current_inode = File.stat("dst").ino
|
|
135
|
+
expect(File.realpath("dst")).to eq(File.realpath("src"))
|
|
136
|
+
expect(prev_inode).not_to eq(current_inode)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
it "replaces existing dst -> src(dir) link atomically" do
|
|
141
|
+
tmp_dir do
|
|
142
|
+
FileUtils.mkdir "src1"
|
|
143
|
+
FileUtils.mkdir "src"
|
|
144
|
+
FileUtils.ln_s "src1", "dst"
|
|
145
|
+
prev_inode = File.stat("dst").ino
|
|
146
|
+
|
|
147
|
+
dir = File.dirname("dst")
|
|
148
|
+
|
|
149
|
+
expect(subject).to receive(:cmd).with(array_including("mv", dir), display: false).and_call_original
|
|
150
|
+
|
|
151
|
+
subject.symlink "src", "dst"
|
|
152
|
+
current_inode = File.stat("dst").ino
|
|
153
|
+
expect(File.realpath("dst")).to eq(File.realpath("src"))
|
|
154
|
+
expect(prev_inode).not_to eq(current_inode)
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
it "raises an error when dst file already exists" do
|
|
159
|
+
tmp_dir do
|
|
160
|
+
FileUtils.touch "src"
|
|
161
|
+
FileUtils.touch "dst"
|
|
162
|
+
expect { subject.symlink "src", "dst" }.to raise_error(Error)
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|