gem-checkout 0.0.5 → 0.1.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/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
|