bundle_depot 0.0.3 → 0.2.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 +4 -4
- data/Gemfile.lock +5 -1
- data/README.md +87 -10
- data/bundle_depot.gemspec +1 -0
- data/features/cli.feature +6 -0
- data/features/fetch.feature +26 -19
- data/features/step_definitions/cli_steps.rb +4 -1
- data/features/store.feature +27 -2
- data/features/support/env.rb +5 -2
- data/lib/bundle_depot/cache.rb +162 -72
- data/lib/bundle_depot/cli.rb +9 -17
- data/lib/bundle_depot/version.rb +1 -1
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9be713b4d9ac3679609e14010e93609ba007a147
|
4
|
+
data.tar.gz: d7912052a61da3ac04c079d3f8ebd3ae960a47f2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5e4115c9b586fb36382a7cd1a5869c1fb821f916d1d9b2fd37eaf168d382f7d6f19df66bb6426d4a66cf93979c04b18bde72c7c5355a7f7127c6a72ffa8d0c94
|
7
|
+
data.tar.gz: 75565c28483a91a1ad04fee040e0c60b152c883462daf051d1388445684002ecf94a61e2989b1e4bec7376ad05465dc45e2edf6c86889b66c5bf391f2c369430
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
bundle_depot (0.0
|
4
|
+
bundle_depot (0.2.0)
|
5
|
+
net-scp
|
5
6
|
thor
|
6
7
|
|
7
8
|
GEM
|
@@ -30,6 +31,9 @@ GEM
|
|
30
31
|
multi_json (~> 1.3)
|
31
32
|
multi_json (1.8.2)
|
32
33
|
multi_test (0.0.2)
|
34
|
+
net-scp (1.1.2)
|
35
|
+
net-ssh (>= 2.6.5)
|
36
|
+
net-ssh (2.7.0)
|
33
37
|
rack (1.5.2)
|
34
38
|
rack-protection (1.5.1)
|
35
39
|
rack
|
data/README.md
CHANGED
@@ -1,24 +1,101 @@
|
|
1
1
|
# BundleDepot
|
2
2
|
|
3
|
-
|
3
|
+
Utility for caching bundled gems.
|
4
4
|
|
5
|
-
|
5
|
+
Especially useful for CI servers that rely on clean build directories, or use
|
6
|
+
multiple build directories and need to run `bundle install` repeatedly.
|
6
7
|
|
7
|
-
Add this line to your application's Gemfile:
|
8
8
|
|
9
|
-
|
9
|
+
## How it works
|
10
10
|
|
11
|
-
|
11
|
+
bundle-depot fetch
|
12
|
+
bundle install --path .bundle/depot/current
|
13
|
+
bundle-depot store
|
12
14
|
|
13
|
-
|
15
|
+
This will:
|
14
16
|
|
15
|
-
|
17
|
+
1. Create a SHA2 hash from the project's `Gemfile.lock` (e.g. 314ff159)
|
18
|
+
2. If required, a folder `.bundle/depot/cache/314ff159` is created. This is the local cache.
|
19
|
+
3. A remote location is checked for a file `314ff159.tar.gz`. If available it is downloaded and unpacked.
|
20
|
+
4. A symlink is managed to point from `.bundle/depot/current` to `.bundle/depot/cache/314ff159`
|
21
|
+
5. `bundle install` is installing gems when both caches are cold. Otherwise, does nothing \o/
|
22
|
+
6. Tar and zip `.bundle/depot/cache/314ff159` into `.bundle/depot/cache/314ff159.tar.gz`
|
23
|
+
7. Upload `314ff159.tar.gz` to the remote cache
|
24
|
+
|
25
|
+
Whenever the Gemfile changes in subsequent runs this process will repeat
|
26
|
+
itself. `.bundle/depot/current` will point to the cache entry that contains the
|
27
|
+
most recent bundle gems.
|
28
|
+
|
29
|
+
|
30
|
+
## Shared Cache on the local machine
|
31
|
+
|
32
|
+
This can be used to setup a shared cache on the same machine by configuring the
|
33
|
+
environent variable `BUNDLE_DEPOT_CACHE`.
|
34
|
+
|
35
|
+
export BUNDLE_DEPOT_CACHE=/var/lib/bundle_depot
|
36
|
+
bundle-depot fetch
|
37
|
+
bundle install --path .bundle/depot/current
|
38
|
+
bundle-depot store
|
39
|
+
|
40
|
+
Instead of using `.bundle/depot/cache` this will then use `/var/lib/bundle_depot` as
|
41
|
+
a shared cache folder.
|
42
|
+
|
43
|
+
## Remote Caching
|
44
|
+
|
45
|
+
When a remote store is configured this sequence will check and update a remote
|
46
|
+
cache location:
|
47
|
+
|
48
|
+
export BUNDLE_DEPOT_SCP_USER=upload
|
49
|
+
export BUNDLE_DEPOT_SCP_PASS=upload
|
50
|
+
export BUNDLE_DEPOT_SCP_HOST=cache.example.com
|
51
|
+
|
52
|
+
bundle-depot fetch
|
53
|
+
bundle install --path .bundle/depot/current
|
54
|
+
bundle-depot store
|
55
|
+
|
56
|
+
In addition to checking the local cache on the file system, this will check
|
57
|
+
the existance of a zipped bundle on a remote location. Currently supported is
|
58
|
+
a connection via SCP.
|
16
59
|
|
17
|
-
$ gem install bundle_depot
|
18
60
|
|
19
|
-
##
|
61
|
+
## Configuration Options
|
62
|
+
|
63
|
+
* `BUNDLE_DEPOT_CACHE`
|
64
|
+
Point to where you want to keep your local cache. Defaults to `.bundle/depot/cache`
|
65
|
+
|
66
|
+
|
67
|
+
## Complete Example
|
68
|
+
|
69
|
+
#!/bin/sh
|
70
|
+
set -o errexit # abort after the first command that fails
|
71
|
+
|
72
|
+
fmt <<'EOF'
|
73
|
+
====================================================================================
|
74
|
+
Preparing Build Agent Environment
|
75
|
+
====================================================================================
|
76
|
+
EOF
|
77
|
+
gem install bundle_depot --install-dir .gems --bindir bin --no-rdoc --no-ri
|
78
|
+
|
79
|
+
|
80
|
+
fmt <<'EOF'
|
81
|
+
====================================================================================
|
82
|
+
Bundle it!
|
83
|
+
====================================================================================
|
84
|
+
EOF
|
85
|
+
export BUNDLE_DEPOT_HOME=/var/lib/bundle_depot
|
86
|
+
export BUNDLE_DEPOT_SCP_USER=upload
|
87
|
+
export BUNDLE_DEPOT_SCP_PASS=upload
|
88
|
+
export BUNDLD_DEPOT_SCP_HOST=cache.example.com
|
89
|
+
|
90
|
+
bin/bundle-depot fetch
|
91
|
+
bundle install --path .bundle/depot/current --frozen
|
92
|
+
bin/bundle-depot store
|
93
|
+
|
94
|
+
|
95
|
+
## Installation
|
96
|
+
|
97
|
+
$ gem install bundle_depot
|
20
98
|
|
21
|
-
TODO: Write usage instructions here
|
22
99
|
|
23
100
|
## Contributing
|
24
101
|
|
data/bundle_depot.gemspec
CHANGED
data/features/cli.feature
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
@announce
|
2
2
|
Feature: CLI
|
3
|
+
Background:
|
4
|
+
Given the following environment variables are set:
|
5
|
+
| variable | value |
|
6
|
+
| BUNDLE_DEPOT_SCP_USER | upload |
|
7
|
+
| BUNDLE_DEPOT_SCP_PASS | upload |
|
8
|
+
| BUNDLE_DEPOT_SCP_HOST | cache.example.com |
|
3
9
|
|
4
10
|
Scenario: Help screen
|
5
11
|
When I run `bundle-depot`
|
data/features/fetch.feature
CHANGED
@@ -9,8 +9,6 @@ Feature: Fetch remotely stored bundle
|
|
9
9
|
|
10
10
|
Scenario: Working directory defaults to ./bundle/depot
|
11
11
|
Given there is the project "json" in the current directory
|
12
|
-
And the remote cache contains the packed bundle for "json"
|
13
|
-
And the local cache does not contain the bundle "json"
|
14
12
|
When I run `bundle-depot fetch`
|
15
13
|
Then the following directories should exist:
|
16
14
|
| .bundle/depot/cache |
|
@@ -18,11 +16,9 @@ Feature: Fetch remotely stored bundle
|
|
18
16
|
|
19
17
|
Scenario: Local Cache can be overwritten by environment
|
20
18
|
Given there is the project "json" in the current directory
|
21
|
-
And the remote cache contains the packed bundle for "json"
|
22
|
-
And the local cache does not contain the bundle "json"
|
23
19
|
And the following environment variables are set:
|
24
|
-
| variable
|
25
|
-
|
|
20
|
+
| variable | value |
|
21
|
+
| BUNDLE_DEPOT_CACHE | special/depot/cache |
|
26
22
|
When I run `bundle-depot fetch`
|
27
23
|
Then the following directories should exist:
|
28
24
|
| special/depot/cache/bde95daa2ce7dede336b4367b9e3a0690027bd6f071e0fdcb1b3047cf988963c |
|
@@ -37,27 +33,38 @@ Feature: Fetch remotely stored bundle
|
|
37
33
|
When I run `bundle-depot fetch`
|
38
34
|
Then the exit status should be 0
|
39
35
|
|
40
|
-
Scenario:
|
36
|
+
Scenario: .bundle/depot/current points to
|
41
37
|
Given there is the project "json" in the current directory
|
42
|
-
And the remote cache does not contain the packed bundle "json"
|
43
38
|
When I run `bundle-depot fetch`
|
44
|
-
Then the
|
39
|
+
Then the following symlinks should exist:
|
40
|
+
| source | target |
|
41
|
+
| .bundle/depot/current | .bundle/depot/cache/bde95daa2ce7dede336b4367b9e3a0690027bd6f071e0fdcb1b3047cf988963c |
|
45
42
|
|
46
|
-
Scenario:
|
43
|
+
Scenario: Skip remote check if SCP is not setup
|
47
44
|
Given there is the project "json" in the current directory
|
48
|
-
And the remote cache contains the packed bundle for "json"
|
49
|
-
And the local cache does not contain the bundle "json"
|
50
45
|
When I run `bundle-depot fetch`
|
51
|
-
Then the
|
52
|
-
And the following directories should exist:
|
53
|
-
| .bundle/depot/cache/bde95daa2ce7dede336b4367b9e3a0690027bd6f071e0fdcb1b3047cf988963c |
|
46
|
+
Then the output should not contain "=> Bundle is not in remote cache"
|
54
47
|
|
55
|
-
Scenario:
|
48
|
+
Scenario: Check remote cache when SCP is setup
|
56
49
|
Given there is the project "json" in the current directory
|
50
|
+
And the following environment variables are set:
|
51
|
+
| variable | value |
|
52
|
+
| BUNDLE_DEPOT_SCP_USER | upload |
|
53
|
+
| BUNDLE_DEPOT_SCP_PASS | upload |
|
54
|
+
| BUNDLE_DEPOT_SCP_HOST | cache.example.com |
|
57
55
|
And the remote cache contains the packed bundle for "json"
|
58
56
|
And the local cache does not contain the bundle "json"
|
59
57
|
When I run `bundle-depot fetch`
|
60
|
-
Then the
|
61
|
-
| source | target |
|
62
|
-
| .bundle/depot/current | .bundle/depot/cache/bde95daa2ce7dede336b4367b9e3a0690027bd6f071e0fdcb1b3047cf988963c |
|
58
|
+
Then the output should contain "=> Bundle found in remote cache. Downloading!"
|
63
59
|
|
60
|
+
Scenario: Does nothing if the remote cache does not contain the bundle
|
61
|
+
Given there is the project "json" in the current directory
|
62
|
+
And the following environment variables are set:
|
63
|
+
| variable | value |
|
64
|
+
| BUNDLE_DEPOT_SCP_USER | upload |
|
65
|
+
| BUNDLE_DEPOT_SCP_PASS | upload |
|
66
|
+
| BUNDLE_DEPOT_SCP_HOST | cache.example.com |
|
67
|
+
And the remote cache does not contain the packed bundle "json"
|
68
|
+
And the local cache does not contain the bundle "json"
|
69
|
+
When I run `bundle-depot fetch`
|
70
|
+
Then the exit status should be 0
|
@@ -7,7 +7,10 @@ When(/^I run `([^`]*)` in a bundler sandbox$/) do |cmd|
|
|
7
7
|
set_env(key, nil)
|
8
8
|
end
|
9
9
|
run_simple(unescape(cmd), false)
|
10
|
-
|
10
|
+
|
11
|
+
%w[RUBYOPT BUNDLE_PATH BUNDLE_BIN_PATH BUNDLE_GEMFILE GEM_HOME GEM_PATH].each do |key|
|
12
|
+
ENV[key] = original_env[key]
|
13
|
+
end
|
11
14
|
end
|
12
15
|
|
13
16
|
Then(/^bundler did not install gems$/) do
|
data/features/store.feature
CHANGED
@@ -3,19 +3,39 @@ Feature: Store Local Package Remotely
|
|
3
3
|
|
4
4
|
Scenario: No Gemfile (store)
|
5
5
|
Given there is no Gemfile.lock in the current directory
|
6
|
+
And the following environment variables are set:
|
7
|
+
| variable | value |
|
8
|
+
| BUNDLE_DEPOT_SCP_USER | upload |
|
9
|
+
| BUNDLE_DEPOT_SCP_PASS | upload |
|
10
|
+
| BUNDLE_DEPOT_SCP_HOST | cache.example.com |
|
6
11
|
When I run `bundle-depot store`
|
7
12
|
Then the output should contain "Couldn't find Gemfile.lock"
|
8
13
|
And the exit status should not be 0
|
9
14
|
|
15
|
+
Scenario: No SCP environment configured
|
16
|
+
Given there is the project "json" in the current directory
|
17
|
+
When I run `bundle-depot store`
|
18
|
+
Then the output should contain "Remote cache is not configured. Configured the SCP environment variables to run 'bundle-depot store'"
|
19
|
+
And the exit status should not be 0
|
20
|
+
|
10
21
|
Scenario: Does nothing if remote cache contains the bundle
|
11
22
|
Given there is the project "json" in the current directory
|
23
|
+
And the following environment variables are set:
|
24
|
+
| variable | value |
|
25
|
+
| BUNDLE_DEPOT_SCP_USER | upload |
|
26
|
+
| BUNDLE_DEPOT_SCP_PASS | upload |
|
27
|
+
| BUNDLE_DEPOT_SCP_HOST | cache.example.com |
|
12
28
|
And the remote cache contains the packed bundle for "json"
|
13
29
|
When I run `bundle-depot store`
|
14
30
|
Then the exit status should be 0
|
15
31
|
|
16
32
|
Scenario: Fails if local cache does not contain the bundle
|
17
|
-
Given
|
18
|
-
And the
|
33
|
+
Given there is the project "json" in the current directory
|
34
|
+
And the following environment variables are set:
|
35
|
+
| variable | value |
|
36
|
+
| BUNDLE_DEPOT_SCP_USER | upload |
|
37
|
+
| BUNDLE_DEPOT_SCP_PASS | upload |
|
38
|
+
| BUNDLE_DEPOT_SCP_HOST | cache.example.com |
|
19
39
|
And the local cache does not contain the bundle "json"
|
20
40
|
When I run `bundle-depot store`
|
21
41
|
Then the output should contain "Couldn't find the cached bundle."
|
@@ -23,6 +43,11 @@ Feature: Store Local Package Remotely
|
|
23
43
|
|
24
44
|
Scenario: Uploads the Bundle to remote cache
|
25
45
|
Given there is the project "json" in the current directory
|
46
|
+
And the following environment variables are set:
|
47
|
+
| variable | value |
|
48
|
+
| BUNDLE_DEPOT_SCP_USER | upload |
|
49
|
+
| BUNDLE_DEPOT_SCP_PASS | upload |
|
50
|
+
| BUNDLE_DEPOT_SCP_HOST | cache.example.com |
|
26
51
|
And the remote cache does not contain the packed bundle "json"
|
27
52
|
And the local cache contains the bundle "json"
|
28
53
|
When I run `bundle-depot store`
|
data/features/support/env.rb
CHANGED
@@ -5,12 +5,14 @@ require 'bundle_depot'
|
|
5
5
|
|
6
6
|
World(RSpec::Matchers)
|
7
7
|
|
8
|
+
ENV["TEST"] = "true"
|
9
|
+
|
8
10
|
def local_cache_path
|
9
|
-
|
11
|
+
BundleDepot::Cache.cache_path
|
10
12
|
end
|
11
13
|
|
12
14
|
def remote_cache_path
|
13
|
-
File.join(
|
15
|
+
File.join(".bundle", "depot","remote")
|
14
16
|
end
|
15
17
|
|
16
18
|
def fixture_project_path(project)
|
@@ -40,3 +42,4 @@ end
|
|
40
42
|
def remote_cache_packed_bundle_path(bundle)
|
41
43
|
File.join(remote_cache_path, fixtures_bundle_name(bundle) + ".tar.gz")
|
42
44
|
end
|
45
|
+
|
data/lib/bundle_depot/cache.rb
CHANGED
@@ -1,143 +1,233 @@
|
|
1
1
|
require "digest"
|
2
|
+
require "delegate"
|
3
|
+
require 'net/scp'
|
2
4
|
|
3
5
|
module BundleDepot
|
4
6
|
class BundleDepotError < StandardError; end
|
7
|
+
class GemfileNotFound < BundleDepotError; end
|
8
|
+
class RemoteConfigurationMissing < BundleDepotError; end
|
5
9
|
class BundleNotFound < BundleDepotError; end
|
6
10
|
class RemoteBundleNotFound < BundleNotFound; end
|
7
11
|
class LocalBundleNotFound < BundleNotFound; end
|
8
12
|
class ArchivingFailed < BundleDepotError; end
|
9
13
|
|
10
|
-
class
|
14
|
+
class Store
|
15
|
+
def cached?(file)
|
16
|
+
raise NotImplementedError
|
17
|
+
end
|
18
|
+
|
19
|
+
def store(file)
|
20
|
+
raise NotImplementedError
|
21
|
+
end
|
22
|
+
|
23
|
+
def fetch(file, dest_dir)
|
24
|
+
raise NotImplementedError
|
25
|
+
end
|
26
|
+
|
27
|
+
def with_packing
|
28
|
+
PackingDecorator.new(self)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class SCPStore < Store
|
33
|
+
attr_reader :host, :user, :password, :path
|
34
|
+
|
35
|
+
def initialize(host, user, password, path = ".")
|
36
|
+
@host = host
|
37
|
+
@user = user
|
38
|
+
@password = password
|
39
|
+
@path = path
|
40
|
+
end
|
41
|
+
|
42
|
+
def cached?(file)
|
43
|
+
target = File.join(path, File.basename(file))
|
44
|
+
output = "false"
|
45
|
+
|
46
|
+
Net::SSH.start(host, user, { password: password}) do |session|
|
47
|
+
output = session.exec! "test -e #{target} && echo 'true'"
|
48
|
+
end
|
49
|
+
|
50
|
+
output.strip == "true"
|
51
|
+
end
|
52
|
+
|
53
|
+
def store(file)
|
54
|
+
Net::SSH.start(host, user, { password: password}) do |session|
|
55
|
+
session.exec! "mkdir -p #{path}"
|
56
|
+
session.scp.upload! file, File.join(path, File.basename(file))
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def fetch(file, dest_dir)
|
61
|
+
Net::SCP.download!(host, user, File.join(path, file), file, ssh: { password: password })
|
62
|
+
rescue Net::SCP::Error
|
63
|
+
raise BundleNotFound
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
class FileSystemStore < Store
|
11
69
|
attr_reader :path
|
12
70
|
|
71
|
+
def cached?(file)
|
72
|
+
File.exists? File.join(path, file)
|
73
|
+
end
|
74
|
+
|
13
75
|
def initialize(path)
|
14
76
|
@path = path
|
15
77
|
FileUtils.mkdir_p(path)
|
16
78
|
end
|
17
79
|
|
80
|
+
def store(file)
|
81
|
+
FileUtils.cp_r file, File.join(path, File.basename(file))
|
82
|
+
end
|
83
|
+
|
84
|
+
def fetch(file, dest_dir)
|
85
|
+
FileUtils.cp_r File.join(path, file), dest_dir
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
class PackingDecorator < SimpleDelegator
|
90
|
+
|
18
91
|
def cached?(file)
|
19
|
-
|
92
|
+
super(packed_file(file))
|
20
93
|
end
|
21
94
|
|
22
95
|
def store(file)
|
23
|
-
|
96
|
+
working_dir = File.expand_path(File.dirname(file))
|
97
|
+
source = File.basename(file)
|
98
|
+
target = packed_file(file)
|
99
|
+
|
100
|
+
raise BundleNotFound unless File.exists? file
|
101
|
+
|
102
|
+
unless File.exist?(target)
|
103
|
+
puts "=> Packing bundle"
|
104
|
+
`tar -C #{working_dir} -czf #{target} #{source}`
|
105
|
+
raise ArchivingFailed unless $?.exitstatus == 0
|
106
|
+
end
|
107
|
+
|
108
|
+
super(target)
|
24
109
|
end
|
25
110
|
|
26
111
|
def fetch(file, dest_dir)
|
27
|
-
|
112
|
+
source = packed_file(file)
|
113
|
+
target = File.join(dest_dir, source)
|
114
|
+
|
115
|
+
super(source, dest_dir)
|
116
|
+
|
117
|
+
puts "=> Unpacking #{target}"
|
118
|
+
`tar -C #{dest_dir} -xf #{target}`
|
119
|
+
raise ArchivingFailed unless $?.exitstatus == 0
|
120
|
+
end
|
121
|
+
|
122
|
+
def packed_file(file)
|
123
|
+
file + ".tar.gz"
|
28
124
|
end
|
29
125
|
end
|
30
126
|
|
31
127
|
class Cache
|
32
|
-
|
128
|
+
DEFAULT_BUNDLE_DEPOT_CURRENT = File.join(".bundle", "depot", "current")
|
129
|
+
DEFAULT_BUNDLE_DEPOT_CACHE = File.join(".bundle", "depot", "cache")
|
33
130
|
|
34
131
|
attr_reader :local, :remote
|
35
132
|
|
36
133
|
def initialize(local = FileSystemStore.new(Cache.cache_path),
|
37
|
-
remote = FileSystemStore.new(File.join(
|
134
|
+
remote = FileSystemStore.new(File.join(".bundle", "depot", "remote")).with_packing)
|
135
|
+
|
136
|
+
if remote_configured? && !ENV["TEST"]
|
137
|
+
remote = SCPStore.new(ENV["BUNDLE_DEPOT_SCP_HOST"],
|
138
|
+
ENV["BUNDLE_DEPOT_SCP_USER"],
|
139
|
+
ENV["BUNDLE_DEPOT_SCP_PASS"], "cache").with_packing
|
140
|
+
end
|
38
141
|
|
39
142
|
@local = local
|
40
143
|
@remote = remote
|
41
144
|
end
|
42
145
|
|
43
146
|
def store
|
44
|
-
|
45
|
-
|
46
|
-
else
|
47
|
-
raise BundleNotFound unless local.cached?(digest)
|
48
|
-
pack
|
49
|
-
upload
|
50
|
-
end
|
147
|
+
setup
|
148
|
+
store_remote
|
51
149
|
end
|
52
150
|
|
53
151
|
def fetch
|
152
|
+
setup
|
153
|
+
fetch_remote unless fetch_local
|
154
|
+
manage_symlink
|
155
|
+
end
|
156
|
+
|
157
|
+
def fetch_local
|
54
158
|
if local.cached?(digest)
|
55
159
|
puts "=> Bundle found in local cache"
|
160
|
+
true
|
56
161
|
else
|
57
162
|
puts "=> Bundle is not in local cache"
|
58
|
-
if remote.cached?(digest + ".tar.gz")
|
59
|
-
download
|
60
|
-
unpack
|
61
|
-
else
|
62
|
-
puts "=> Bundle is not in remote cache"
|
63
|
-
FileUtils.mkdir_p(unpacked_bundle)
|
64
|
-
end
|
65
163
|
end
|
66
|
-
link
|
67
164
|
end
|
68
165
|
|
166
|
+
def fetch_remote
|
167
|
+
return unless remote_configured?
|
168
|
+
|
169
|
+
if remote.cached?(digest)
|
170
|
+
puts "=> Bundle found in remote cache. Downloading!"
|
171
|
+
remote.fetch(digest, local.path)
|
172
|
+
else
|
173
|
+
puts "=> Bundle is not in remote cache"
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def store_remote
|
178
|
+
raise RemoteConfigurationMissing unless remote_configured?
|
69
179
|
|
70
|
-
|
71
|
-
|
180
|
+
if remote.cached?(digest)
|
181
|
+
puts "=> Bundle is already in remote cache. Skipping upload."
|
182
|
+
else
|
183
|
+
puts "=> Uploading bundle to remote cache"
|
184
|
+
remote.store(File.join(local.path, digest))
|
185
|
+
end
|
72
186
|
end
|
73
187
|
|
74
188
|
def self.cache_path
|
75
|
-
ENV["
|
189
|
+
ENV["BUNDLE_DEPOT_CACHE"] || DEFAULT_BUNDLE_DEPOT_CACHE
|
76
190
|
end
|
77
191
|
|
78
192
|
def self.current_bundle_path
|
79
|
-
ENV["
|
193
|
+
ENV["DEFAULT_BUNDLE_DEPOT_CURRENT"] || DEFAULT_BUNDLE_DEPOT_CURRENT
|
80
194
|
end
|
81
195
|
|
82
|
-
|
83
|
-
|
84
|
-
def link
|
85
|
-
source = unpacked_bundle
|
86
|
-
target = Cache.current_bundle_path
|
87
|
-
|
88
|
-
if File.exist?(target)
|
89
|
-
if File.symlink?(target)
|
90
|
-
if File.readlink(File.expand_path(target)) == File.expand_path(source)
|
91
|
-
return
|
92
|
-
else
|
93
|
-
File.unlink(target)
|
94
|
-
end
|
95
|
-
else
|
96
|
-
raise "Shit. #{target} is not a symlink. Aborting to not mess stuff up..."
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
puts "=> Linking #{target} -> #{source}"
|
101
|
-
File.symlink File.expand_path(source), target
|
196
|
+
def remote_configured?
|
197
|
+
ENV["BUNDLE_DEPOT_SCP_HOST"]
|
102
198
|
end
|
103
199
|
|
104
|
-
|
105
|
-
return if File.exist?(packed_file)
|
106
|
-
puts "=> Packing bundle"
|
107
|
-
|
108
|
-
`tar -C #{File.expand_path(local.path)} -czf #{packed_file} #{digest}`
|
109
|
-
raise ArchivingFailed unless $?.exitstatus == 0
|
110
|
-
end
|
200
|
+
private
|
111
201
|
|
112
|
-
def
|
113
|
-
|
114
|
-
raise ArchivingFailed unless $?.exitstatus == 0
|
202
|
+
def setup
|
203
|
+
FileUtils.mkdir_p(File.dirname(Cache.current_bundle_path))
|
115
204
|
end
|
116
205
|
|
117
|
-
def
|
118
|
-
|
119
|
-
|
120
|
-
end
|
206
|
+
def manage_symlink
|
207
|
+
source = File.join(local.path, digest)
|
208
|
+
target = Cache.current_bundle_path
|
121
209
|
|
122
|
-
|
123
|
-
|
124
|
-
|
210
|
+
FileUtils.mkdir_p(source) unless File.exists?(source)
|
211
|
+
|
212
|
+
if remove_outdated_symlink(source, target)
|
213
|
+
puts "=> Linking #{target} -> #{source}"
|
214
|
+
File.symlink File.expand_path(source), target
|
215
|
+
else
|
216
|
+
puts "=> #{target} is pointing to the right bundle"
|
217
|
+
end
|
125
218
|
end
|
126
219
|
|
127
|
-
def
|
128
|
-
|
129
|
-
|
220
|
+
def remove_outdated_symlink(source, target)
|
221
|
+
return true unless File.exist?(target)
|
222
|
+
raise "#{target} is not a symlink. Aborting to not mess stuff up..." unless File.symlink?(target)
|
223
|
+
return false if File.symlink?(target) && File.readlink(File.expand_path(target)) == File.expand_path(source)
|
130
224
|
|
131
|
-
|
132
|
-
File.join(local.path, digest)
|
225
|
+
File.unlink(target)
|
133
226
|
end
|
134
227
|
|
135
228
|
def digest
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
def lock_file
|
140
|
-
File.expand_path("Gemfile.lock")
|
229
|
+
raise GemfileNotFound unless File.exist?("Gemfile.lock")
|
230
|
+
Digest::SHA2.file("Gemfile.lock").hexdigest
|
141
231
|
end
|
142
232
|
end
|
143
233
|
|
data/lib/bundle_depot/cli.rb
CHANGED
@@ -15,12 +15,10 @@ module BundleDepot
|
|
15
15
|
tenderloin bresaola rump pastrami turkey kevin flank.
|
16
16
|
D
|
17
17
|
def fetch
|
18
|
-
unless File.exist?("Gemfile.lock")
|
19
|
-
say "Couldn't find Gemfile.lock"
|
20
|
-
exit 1
|
21
|
-
end
|
22
|
-
|
23
18
|
BundleDepot::Cache.new.fetch
|
19
|
+
rescue GemfileNotFound
|
20
|
+
say "Couldn't find Gemfile.lock"
|
21
|
+
exit 1
|
24
22
|
end
|
25
23
|
|
26
24
|
desc "store", "Store bundle to remote location"
|
@@ -30,22 +28,16 @@ module BundleDepot
|
|
30
28
|
tenderloin bresaola rump pastrami turkey kevin flank.
|
31
29
|
D
|
32
30
|
def store
|
33
|
-
unless File.exist?("Gemfile.lock")
|
34
|
-
say "Couldn't find Gemfile.lock"
|
35
|
-
exit 1
|
36
|
-
end
|
37
|
-
|
38
31
|
BundleDepot::Cache.new.store
|
39
|
-
|
32
|
+
rescue GemfileNotFound
|
33
|
+
say "Couldn't find Gemfile.lock"
|
34
|
+
exit 1
|
40
35
|
rescue BundleNotFound
|
41
36
|
say "Couldn't find the cached bundle. Please run 'bundle-depot fetch' before calling this command..."
|
42
37
|
exit 2
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
# Check remote cache
|
47
|
-
# Pack
|
48
|
-
# Upload
|
38
|
+
rescue RemoteConfigurationMissing
|
39
|
+
say "Remote cache is not configured. Configured the SCP environment variables to run 'bundle-depot store'"
|
40
|
+
exit 3
|
49
41
|
end
|
50
42
|
end
|
51
43
|
end
|
data/lib/bundle_depot/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bundle_depot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Schmidt
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-11-
|
11
|
+
date: 2013-11-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: net-scp
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: cucumber
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|