gem-checkout 0.0.5 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +10 -9
- data/lib/gem-checkout/source.rb +5 -1
- data/lib/gem-checkout/spec.rb +2 -3
- data/lib/gem-checkout/verifier.rb +146 -0
- data/lib/gem-checkout/version.rb +5 -0
- data/lib/rubygems/commands/checkout_command.rb +14 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3c3ac04887cf0d974da2a2c50c35f1a74410515b
|
4
|
+
data.tar.gz: 0cb624321ec30843de7b3e2e7093e10d836c83b5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 083a70f4aa6bb4826494d20a062da913c32f530e5260a294456e22ad8000a664b5579a3582f77765b4759d6a0bded7fcab8cbd1c2aaa8696ec9bb97467aabeb2
|
7
|
+
data.tar.gz: 30a7347b10ed81c0e6464dc00e96ebfa2b38521a53d1b90a8dc213a9e1a5abe2b63878ff0b1aca7f308016ad868ea005b032c85531c74531b846eb2f67b9be47
|
data/README.md
CHANGED
@@ -17,34 +17,35 @@ will checkout the GitHub source code (into the current dir) for the `nenv` gem a
|
|
17
17
|
|
18
18
|
## Installation
|
19
19
|
|
20
|
-
Add this line to your application's Gemfile:
|
21
|
-
|
22
20
|
```sh
|
23
21
|
gem install gem-checkout
|
24
22
|
```
|
25
23
|
|
26
24
|
## Usage
|
27
25
|
|
28
|
-
Proof of concept right now, so open issues and/or PRs for improvements.
|
26
|
+
Proof of concept right now, so check or open issues and/or PRs for improvements.
|
29
27
|
|
30
28
|
Options:
|
31
29
|
|
32
30
|
```
|
33
|
-
-d LEVEL
|
31
|
+
-d LEVEL # sets debug level, where 0=debug, 1=warn, and so on...
|
34
32
|
```
|
35
|
-
sets the debug level, where 0=debug, 1=warn, and so on...
|
36
33
|
|
37
34
|
```
|
38
|
-
-v, --version VERSION
|
35
|
+
-v, --version VERSION # gem version to you want the sources for.
|
39
36
|
```
|
40
37
|
|
41
|
-
The version of the gem to you want to hack on - the repo and revision will be discovered.
|
42
|
-
|
43
38
|
(If you don't provide this option, the latest version will be used).
|
44
39
|
|
40
|
+
```
|
41
|
+
-s, --verify # compare gem built from sources with released version
|
42
|
+
```
|
43
|
+
|
44
|
+
(If it's identical, you can assume the released gem was build from these exact chechecked out sources).
|
45
|
+
|
45
46
|
## FAQ
|
46
47
|
|
47
|
-
None yet, so open
|
48
|
+
None yet, so open issues and ask for improvements/features ...
|
48
49
|
|
49
50
|
|
50
51
|
## Development
|
data/lib/gem-checkout/source.rb
CHANGED
@@ -97,10 +97,14 @@ module Gem
|
|
97
97
|
end
|
98
98
|
end
|
99
99
|
|
100
|
+
attr_reader :version
|
101
|
+
|
100
102
|
def initialize(name, version=nil)
|
101
|
-
Gem::Checkout.logger.debug "Gathering
|
103
|
+
Gem::Checkout.logger.debug "Gathering info about #{name} (#{version || 'latest'})"
|
102
104
|
object = Spec.info(name, version)
|
103
105
|
|
106
|
+
@version = object.version
|
107
|
+
|
104
108
|
@name = name
|
105
109
|
|
106
110
|
repository = RepositoryInfo.detect(object)
|
data/lib/gem-checkout/spec.rb
CHANGED
@@ -63,7 +63,6 @@ module Gem
|
|
63
63
|
def initialize(name, version, remote)
|
64
64
|
@data = find_by_name(name, version)
|
65
65
|
@name = name
|
66
|
-
@version = version
|
67
66
|
@remote = remote
|
68
67
|
end
|
69
68
|
|
@@ -90,7 +89,7 @@ module Gem
|
|
90
89
|
end
|
91
90
|
|
92
91
|
def version
|
93
|
-
read(:version)
|
92
|
+
read(:version).to_s
|
94
93
|
end
|
95
94
|
|
96
95
|
def alternative
|
@@ -212,7 +211,7 @@ module Gem
|
|
212
211
|
info['number'] == version
|
213
212
|
end
|
214
213
|
|
215
|
-
fail Error::NoSuchGem, "Could not find #{name} on rubygems.org" unless version
|
214
|
+
fail Error::NoSuchGem, "Could not find #{name} at #{version} on rubygems.org (yanked gem?)" unless version
|
216
215
|
Gem::Checkout.logger.debug "Found info matching gem version #{@version}"
|
217
216
|
OpenStruct.new(version)
|
218
217
|
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
require 'digest/sha1'
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
require 'gem-checkout/logger'
|
5
|
+
|
6
|
+
module Gem
|
7
|
+
module Checkout
|
8
|
+
class Verifier
|
9
|
+
class Gem
|
10
|
+
class << self
|
11
|
+
def fetch(name, version)
|
12
|
+
version_opts = ['-v', version]
|
13
|
+
fail "failed to fetch gem #{name}" unless system("gem", "fetch", "-V", *version_opts, name)
|
14
|
+
end
|
15
|
+
|
16
|
+
def build(gemspec)
|
17
|
+
fail "failed to build using #{gemspec}" unless system("gem", "build", gemspec)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class Tar
|
23
|
+
class << self
|
24
|
+
def extract_file(archive, file)
|
25
|
+
fail "failed to untar #{file} from #{archive}" unless system("tar", "xf", archive, file)
|
26
|
+
end
|
27
|
+
|
28
|
+
def extract_compressed(archive)
|
29
|
+
fail "failed to untar#{archive}" unless system("tar", "zxf", archive)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class Error < RuntimeError
|
35
|
+
class DataMismatch < Error
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def initialize(name, version)
|
40
|
+
@name = name
|
41
|
+
@version = version
|
42
|
+
end
|
43
|
+
|
44
|
+
def verify!
|
45
|
+
file = build_local_gem
|
46
|
+
local = get_payload_sum(file)
|
47
|
+
remote = get_remote_payload_sum
|
48
|
+
|
49
|
+
unless local == remote
|
50
|
+
local_files = local.map(&:last)
|
51
|
+
remote_files = remote.map(&:last)
|
52
|
+
if local_files != remote_files
|
53
|
+
logger.debug "Files present only in published gem: #{remote_files - local_files }"
|
54
|
+
logger.debug "Files present only in local gem: #{local_files - remote_files }"
|
55
|
+
else
|
56
|
+
diff = remote - local
|
57
|
+
diff.each do |checksum, f|
|
58
|
+
logger.debug "Checksum mismatch: #{checksum} #{f}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
fail Error::DataMismatch, "checksum mismatch (run in debug mode to see details)"
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def name
|
69
|
+
@name
|
70
|
+
end
|
71
|
+
|
72
|
+
def version
|
73
|
+
@version
|
74
|
+
end
|
75
|
+
|
76
|
+
def digest(f)
|
77
|
+
Digest::SHA256.file(f).hexdigest
|
78
|
+
end
|
79
|
+
|
80
|
+
def logger
|
81
|
+
Checkout.logger
|
82
|
+
end
|
83
|
+
|
84
|
+
def build_local_gem
|
85
|
+
logger.debug "Building #{name}-#{version}.gem from sources..."
|
86
|
+
gemspec = detect_gemspec
|
87
|
+
Gem.build(gemspec)
|
88
|
+
File.expand_path("#{name}-#{version}.gem")
|
89
|
+
end
|
90
|
+
|
91
|
+
def detect_gemspec
|
92
|
+
gemspecs = Dir['*.gemspec']
|
93
|
+
fail "Too many gemspecs: #{gemspecs.inspect}" unless gemspecs.size == 1
|
94
|
+
gemspecs.first
|
95
|
+
end
|
96
|
+
|
97
|
+
def tempdir
|
98
|
+
Dir.mktmpdir do |dir|
|
99
|
+
Dir.chdir(dir) do
|
100
|
+
yield
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def get_payload_sum(file)
|
106
|
+
full_path = File.expand_path(file)
|
107
|
+
logger.debug "Getting SHA digests for #{full_path}"
|
108
|
+
|
109
|
+
results = []
|
110
|
+
tempdir do
|
111
|
+
data_file = "data.tar.gz"
|
112
|
+
Tar.extract_file(full_path, data_file)
|
113
|
+
|
114
|
+
archive_path = File.expand_path(data_file)
|
115
|
+
|
116
|
+
tempdir do
|
117
|
+
Tar.extract_compressed(archive_path)
|
118
|
+
add_directory_sums(results, '.')
|
119
|
+
end
|
120
|
+
end
|
121
|
+
results
|
122
|
+
end
|
123
|
+
|
124
|
+
def get_remote_payload_sum
|
125
|
+
logger.debug "Fetching remote gem for verification"
|
126
|
+
tempdir do
|
127
|
+
Gem.fetch(name, version)
|
128
|
+
file = "#{name}-#{version}.gem"
|
129
|
+
return get_payload_sum(file)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def add_directory_sums(results, dir)
|
134
|
+
# TODO: check for filesystem loops/symlinks?
|
135
|
+
Pathname.new(dir).children.each do |f|
|
136
|
+
if File.directory?(f)
|
137
|
+
add_directory_sums(results, f)
|
138
|
+
else
|
139
|
+
logger.debug "SHA digest #{File.expand_path(f)}"
|
140
|
+
results << [digest(f), f]
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'logger'
|
2
2
|
|
3
3
|
require 'gem-checkout/source'
|
4
|
+
require 'gem-checkout/verifier'
|
4
5
|
|
5
6
|
class Gem::Commands::CheckoutCommand < Gem::Command
|
6
7
|
def initialize
|
@@ -12,6 +13,10 @@ class Gem::Commands::CheckoutCommand < Gem::Command
|
|
12
13
|
add_option('-d', '--debug LEVEL', 'set debug mode (0=debug)') do |level, options|
|
13
14
|
options[:debug_level] = Integer(level)
|
14
15
|
end
|
16
|
+
|
17
|
+
add_option('-s', '--[no-]verify', 'verify sources match gem exactly') do |verify, options|
|
18
|
+
options[:verify] = verify
|
19
|
+
end
|
15
20
|
end
|
16
21
|
|
17
22
|
def arguments # :nodoc:
|
@@ -37,13 +42,22 @@ class Gem::Commands::CheckoutCommand < Gem::Command
|
|
37
42
|
|
38
43
|
name = get_one_gem_name
|
39
44
|
source = Gem::Checkout::Source.new(name, options[:version])
|
45
|
+
version = source.version
|
46
|
+
|
40
47
|
repository = source.repository
|
41
48
|
repository.clone(directory: name)
|
42
49
|
Dir.chdir(name) do
|
43
50
|
repository.checkout(source.source_reference)
|
51
|
+
if options[:verify]
|
52
|
+
verifier = Gem::Checkout::Verifier.new(name, version)
|
53
|
+
verifier.verify!
|
54
|
+
end
|
44
55
|
end
|
45
56
|
rescue Gem::Checkout::Repository::Error => ex
|
46
57
|
alert_error ex.message
|
47
58
|
terminate_interaction 1
|
59
|
+
rescue Gem::Checkout::Verifier::Error => ex
|
60
|
+
alert_error ex.message
|
61
|
+
terminate_interaction 1
|
48
62
|
end
|
49
63
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gem-checkout
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cezary Baginski
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-10-
|
11
|
+
date: 2015-10-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gems
|
@@ -54,6 +54,8 @@ files:
|
|
54
54
|
- lib/gem-checkout/repository/git.rb
|
55
55
|
- lib/gem-checkout/source.rb
|
56
56
|
- lib/gem-checkout/spec.rb
|
57
|
+
- lib/gem-checkout/verifier.rb
|
58
|
+
- lib/gem-checkout/version.rb
|
57
59
|
- lib/rubygems/commands/checkout_command.rb
|
58
60
|
- lib/rubygems_plugin.rb
|
59
61
|
homepage: https://github.com/e2/gem-checkout
|