nexus_client 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.
@@ -0,0 +1,105 @@
1
+ require 'filesize'
2
+ require 'etc'
3
+
4
+ module Nexus
5
+ class Cache
6
+ attr_reader :cache_base, :analytics_enabled
7
+ attr_accessor :analytics, :log
8
+
9
+ def initialize(base_dir='/tmp/cache', enable_analytics=false, logger=nil)
10
+ @analytics_enabled = enable_analytics
11
+ @cache_base = base_dir
12
+ @log = logger
13
+ create_base
14
+ end
15
+
16
+ def analytics
17
+ if analytics_enabled
18
+ if @analytics.nil?
19
+ begin
20
+ @analytics = Nexus::Analytics.new(@cache_base, nil, log)
21
+ if @analytics.nil?
22
+ @analytics_enabled = false
23
+ log.warn("Unable to create analytics class, skipping analytics and disabling analytics usage")
24
+ end
25
+ rescue
26
+ log.warn("Unable to create analytics class, skipping analytics and disabling analytics usage")
27
+ @analytics_enabled = false
28
+ return @analytics
29
+ end
30
+ end
31
+ end
32
+ @analytics
33
+ end
34
+
35
+
36
+ def log
37
+ if @log.nil?
38
+ @log = Logger.new(STDOUT)
39
+ end
40
+ @log
41
+ end
42
+
43
+ def create_base
44
+ if not File.exists?(@cache_base)
45
+ FileUtils.mkdir_p(@cache_base)
46
+ end
47
+ end
48
+
49
+ def init_cache_info(gav)
50
+ if gav.attributes[:size].nil?
51
+ gav.attributes[:size] = File.size(file_path(gav))
52
+ end
53
+ if analytics_enabled
54
+ analytics.add_item(gav, file_path(gav))
55
+ end
56
+ end
57
+
58
+ def record_hit(gav)
59
+ analytics.update_item(gav) if analytics_enabled
60
+ end
61
+
62
+ def add_file(gav, dstfile)
63
+ if not File.exists?(location(gav))
64
+ FileUtils.mkdir_p(location(gav))
65
+ end
66
+ if File.exists?(dstfile)
67
+ FileUtils.copy(dstfile, file_path(gav))
68
+ init_cache_info(gav)
69
+ else
70
+ log.warn "file #{dstfile } will not be cached as it doesn't exist"
71
+ end
72
+
73
+ end
74
+
75
+ # location is the directory where the files should be cached
76
+ def location(gav)
77
+ File.join(cache_base, gav.dir_location)
78
+ end
79
+
80
+ # the file path of the gav, the name of the file is the <sha1>.cache
81
+ def file_path(gav)
82
+ if gav.sha1.nil?
83
+ raise('Need sha1 for gav')
84
+ end
85
+ File.join(location(gav), "#{gav.sha1}.cache")
86
+ end
87
+
88
+ # is_cached? returns a bool true if the file is cached
89
+ # the sha1 checksum should be the file name and if it exists, it means its cached
90
+ def exists?(gav)
91
+ file = file_path(gav)
92
+ File.exists?(file)
93
+ end
94
+
95
+ # the fastest way to prune this is to use the local find command
96
+ def prune_cache(mtime=15)
97
+ # get old, unused entries and discard from DB and filesystem
98
+ entries = remove_old_items(mtime)
99
+ entries.each do |key, entry|
100
+ FileUtils.rm_f(entry[:file])
101
+ end
102
+ end
103
+
104
+ end
105
+ end
@@ -0,0 +1,44 @@
1
+ module Nexus
2
+ class Gav
3
+ attr_accessor :group, :artifact, :version, :repo, :classifier, :extension, :sha1, :attributes
4
+ attr_reader :gav_value
5
+
6
+ def initialize(gav_string)
7
+ raise(err) if gav_match.match(gav_string).nil?
8
+ @group,@artifact,@version,@repo,@classifier,@extension = gav_string.split(":")
9
+ @gav_value = gav_string
10
+ @attributes = {}
11
+ end
12
+
13
+ def to_s
14
+ gav_value
15
+ end
16
+
17
+ def filename
18
+ if classifier.empty?
19
+ "#{artifact}-#{version}.#{extension}"
20
+ else
21
+ "#{artifact}-#{version}-#{classifier}.#{extension}"
22
+ end
23
+ end
24
+
25
+ def to_hash
26
+ {:g => group, :a => artifact, :v => version, :r => repo, :c => classifier, :e => extension}
27
+ end
28
+
29
+ # returns a directory location given the gav ie. /org/glassfish/main/external/ant/
30
+ def dir_location
31
+ File.join(group.gsub('.', '/'), artifact)
32
+ end
33
+
34
+ private
35
+ def gav_match
36
+ /([\w\.\-]+:[\w\.\-]+:[\.\w\-]+:[\w\.\-]*:[\w\.\-]*:[\w\.\-]*)/
37
+ end
38
+
39
+ def err
40
+ 'Must provide gav_str in the form of "<group>:<artifact>:<version>:<repo>:<classifier>:<extension>"'
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,9 @@
1
+ module Nexus
2
+ class Client
3
+ VERSION = "0.3.0"
4
+
5
+ def self.version
6
+ VERSION
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'nexus_client/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "nexus_client"
8
+ spec.version = Nexus::Client::VERSION
9
+ spec.authors = ["Jason Thigpen", "Corey Osman"]
10
+ spec.email = ["darwin@senet.us", "corey@logicminds.biz"]
11
+ spec.description = %q{Simple Ruby client for dealing with Nexus}
12
+ spec.summary = %q{Simple Nexus Ruby Client}
13
+ spec.homepage = "https://github.com/logicminds/nexus-client"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+ spec.add_runtime_dependency "trollop", "= 2.0"
21
+ spec.add_runtime_dependency "json" if Gem.ruby_version < Gem::Version.new('2.0')
22
+ spec.add_runtime_dependency "typhoeus", "= 0.6.9"
23
+ spec.add_runtime_dependency "filesize", "= 0.0.3"
24
+ spec.add_development_dependency "sqlite3", '~> 1.3'
25
+ spec.add_development_dependency "bundler", "~> 1.3"
26
+ spec.add_development_dependency "rake", "~> 10.3"
27
+ spec.add_development_dependency "rspec", "~> 2.99"
28
+ spec.add_development_dependency "fakefs", "= 0.5"
29
+
30
+ end
@@ -0,0 +1,137 @@
1
+ require "spec_helper"
2
+ require 'sqlite3'
3
+
4
+ describe "Integration Nexus::Analytics" do
5
+ before(:all) do
6
+ FileUtils.mkdir_p('/tmp/cache') if not File.exists?('/tmp/cache')
7
+ end
8
+ file = '/tmp/ant-4.0.pom'
9
+ shafile = '/tmp/ant-4.0.pom.sha1'
10
+
11
+ after(:all) do
12
+ FileUtils.rm(file) if File.exists?(file)
13
+ FileUtils.rm_rf('/tmp/cache/analytics.db')
14
+
15
+ end
16
+ before(:each) do
17
+ FileUtils.rm_rf('/tmp/cache/analytics.db') if File.exists?('/tmp/cache/analytics.db')
18
+ @gav = Nexus::Gav.new('org.glassfish.main.external:ant:4.0:central::pom')
19
+ @gav.sha1 = '387951c0aa333024b25085d76a8ad77441b9e55f'
20
+ @gav.attributes[:total_time] = 0.332
21
+ @gav.attributes[:size] = 123837
22
+ @gav2 = Nexus::Gav.new('org.apache.maven:maven:3.2.1:central::pom')
23
+ @gav2.sha1 = '54af5be0a5677e896e9eaa356bbb82abda06bd76'
24
+ @gav2.attributes[:total_time] = 0.532
25
+ @gav2.attributes[:size] = 12389
26
+ @analytics = Nexus::Analytics.new('/tmp/cache', 'analytics.db')
27
+ end
28
+
29
+ it 'db exists' do
30
+ expect(File.exists?('/tmp/cache/analytics.db')).to be_true
31
+ end
32
+
33
+ it 'table exists' do
34
+ expect(@analytics.db.execute("select * from artifacts")).to eq([])
35
+ end
36
+
37
+ it 'gavs return' do
38
+ @analytics.add_item(@gav, '/tmp/cache/org/glassfish/main/external/ant/387951c0aa333024b25085d76a8ad77441b9e55f.cache')
39
+ expect(@analytics.gavs.length).to eq(1)
40
+ end
41
+
42
+ it 'total view exists' do
43
+ @analytics.add_item(@gav, '/tmp/cache/org/glassfish/main/external/ant/387951c0aa333024b25085d76a8ad77441b9e55f.cache')
44
+ @analytics.update_item(@gav)
45
+ @analytics.update_item(@gav)
46
+ @analytics.update_item(@gav)
47
+ @analytics.update_item(@gav)
48
+ expected = [["896f6a67964939a62f6b29e3d6fa13139ee92f9a",
49
+ "org.glassfish.main.external:ant:4.0:central::pom",
50
+ 123837, 0.332, "2014-06-11 00:44:07 -0700",
51
+ "/tmp/cache/org/glassfish/main/external/ant/387951c0aa333024b25085d76a8ad77441b9e55f.cache",
52
+ 4, 495348, 1.328]]
53
+ expect(@analytics.db.execute("select * from totals").length).to eq(1)
54
+ end
55
+
56
+ it '#old_items' do
57
+ @analytics.add_item(@gav, '/tmp/cache/org/glassfish/main/external/ant/387951c0aa333024b25085d76a8ad77441b9e55f.cache')
58
+ expect(@analytics.old_items((Time.now + 10000).to_i).length).to eq(1)
59
+ expect(@analytics.old_items((Time.now - 10000).to_i).length).to eq(0)
60
+
61
+ end
62
+
63
+ it '#remove_old_items' do
64
+ @analytics.add_item(@gav, '/tmp/cache/org/glassfish/main/external/ant/387951c0aa333024b25085d76a8ad77441b9e55f.cache')
65
+ expect(@analytics.old_items((Time.now + 10000).to_i).length).to eq(1)
66
+ @analytics.remove_old_items((Time.now + 10000).to_i)
67
+ expect(@analytics.old_items((Time.now + 10000).to_i).length).to eq(0)
68
+ end
69
+
70
+ it 'top works' do
71
+ @analytics.add_item(@gav, '/tmp/cache/org/glassfish/main/external/ant/387951c0aa333024b25085d76a8ad77441b9e55f.cache')
72
+ @analytics.update_item(@gav)
73
+ @analytics.update_item(@gav)
74
+ @analytics.update_item(@gav)
75
+ @analytics.update_item(@gav)
76
+ expected = [["896f6a67964939a62f6b29e3d6fa13139ee92f9a",
77
+ "org.glassfish.main.external:ant:4.0:central::pom",
78
+ 123837, 0.332, "2014-06-11 00:44:07 -0700",
79
+ "/tmp/cache/org/glassfish/main/external/ant/387951c0aa333024b25085d76a8ad77441b9e55f.cache",
80
+ 4, 495348, 1.328]]
81
+ expect(@analytics.top_x(3).length).to eq(1)
82
+ end
83
+
84
+ it 'can add item' do
85
+ @analytics.add_item(@gav, '/tmp/cache/org/glassfish/main/external/ant/387951c0aa333024b25085d76a8ad77441b9e55f.cache')
86
+ @analytics.add_item(@gav2, '/tmp/cache/org/apache/maven/54af5be0a5677e896e9eaa356bbb82abda06bd76.cache')
87
+ expect(@analytics.db.execute("select * from artifacts")).to be_a Array
88
+ end
89
+
90
+ it 'should not error out when duplicate item is added' do
91
+ expect{@analytics.add_item(@gav, '/tmp/cache/org/glassfish/main/external/ant/387951c0aa333024b25085d76a8ad77441b9e55f.cache')}.to_not raise_error
92
+ expect{@analytics.add_item(@gav, '/tmp/cache/org/glassfish/main/external/ant/387951c0aa333024b25085d76a8ad77441b9e55f.cache')}.to_not raise_error
93
+
94
+ end
95
+
96
+ it 'can update item' do
97
+ expect{@analytics.add_item(@gav, '/tmp/cache/org/glassfish/main/external/ant/387951c0aa333024b25085d76a8ad77441b9e55f.cache')}.to_not raise_error
98
+ @analytics.update_item(@gav)
99
+ @analytics.update_item(@gav)
100
+ expect(@analytics.hit_count(@gav)).to eq(2)
101
+
102
+ end
103
+
104
+ it '#totals_bytes with pretty' do
105
+ expect{@analytics.add_item(@gav, '/tmp/cache/org/glassfish/main/external/ant/387951c0aa333024b25085d76a8ad77441b9e55f.cache')}.to_not raise_error
106
+ @analytics.update_item(@gav)
107
+ @analytics.update_item(@gav)
108
+ expect(@analytics.total_bytes(@gav, true)).to eq('241.87 kiB')
109
+ end
110
+
111
+ it '#totals_bytes without pretty' do
112
+ expect{@analytics.add_item(@gav, '/tmp/cache/org/glassfish/main/external/ant/387951c0aa333024b25085d76a8ad77441b9e55f.cache')}.to_not raise_error
113
+ @analytics.update_item(@gav)
114
+ @analytics.update_item(@gav)
115
+ expect(@analytics.total_bytes(@gav)).to eq(247674)
116
+ end
117
+
118
+ it '#totals_time' do
119
+ expect{@analytics.add_item(@gav, '/tmp/cache/org/glassfish/main/external/ant/387951c0aa333024b25085d76a8ad77441b9e55f.cache')}.to_not raise_error
120
+ @analytics.update_item(@gav)
121
+ @analytics.update_item(@gav)
122
+ expect(@analytics.total_time(@gav)).to eq(0.664)
123
+ end
124
+
125
+ it '#to_json' do
126
+ @analytics.add_item(@gav, '/tmp/cache/org/glassfish/main/external/ant/387951c0aa333024b25085d76a8ad77441b9e55f.cache')
127
+ @analytics.update_item(@gav)
128
+ @analytics.update_item(@gav)
129
+ @analytics.update_item(@gav)
130
+ @analytics.update_item(@gav)
131
+ @analytics.update_item(@gav)
132
+ data = JSON.parse(@analytics.to_json)
133
+
134
+ expect(data).to be_a(Array)
135
+ end
136
+
137
+ end
@@ -0,0 +1,37 @@
1
+ require "spec_helper"
2
+
3
+ describe "Integration Nexus::Cache" do
4
+ gav_str = 'org.glassfish.main.external:ant:4.0:central::pom'
5
+ gav_str2 = 'org.apache.maven:maven:3.2.1:central::pom'
6
+ after(:all) do
7
+
8
+ end
9
+
10
+ before(:each) do
11
+ let(:gav) do
12
+ Nexus::Gav.new(gav_str)
13
+ end
14
+ let(:gav2) do
15
+ Nexus::Gav.new(gav_str2)
16
+ end
17
+ gav2.sha1 = '387951c0aa333024b25085d76a8ad77441b9e55f'
18
+ gav1.sha1 = ''
19
+ end
20
+
21
+ context 'turn analytics on' do
22
+ let(:cache) do
23
+ Nexus::Cache.new('/tmp/cache', true)
24
+ end
25
+ end
26
+
27
+ context 'turn analytics off' do
28
+ let(:cache) do
29
+ Nexus::Cache.new('/tmp/cache', false)
30
+ end
31
+
32
+ gav2 = Nexus::Gav.new(gav_str)
33
+ gav2.sha1 = '387951c0aa333024b25085d76a8ad77441b9e55f'
34
+
35
+ end
36
+
37
+ end
File without changes
@@ -0,0 +1,76 @@
1
+ require "spec_helper"
2
+
3
+ describe 'Integration Nexus::Client' do
4
+
5
+ file = '/tmp/ant-4.0.pom'
6
+ shafile = '/tmp/ant-4.0.pom.sha1'
7
+
8
+ after(:all) do
9
+ FileUtils.rm(file) if File.exists?(file)
10
+ FileUtils.rm(shafile) if File.exists?(shafile)
11
+
12
+ FileUtils.rm_rf('/tmp/cache') if File.exists?('/tmp/cache')
13
+ end
14
+
15
+ subject(:client) { Nexus::Client.new('https://repository.jboss.org/nexus','/tmp/cache') }
16
+
17
+ let(:gav) do
18
+ Nexus::Gav.new('org.glassfish.main.external:ant:4.0:central::pom')
19
+ end
20
+
21
+
22
+ it 'can read sha1 gav data' do
23
+ expect(client.gav_data(gav)['sha1']).to eq('387951c0aa333024b25085d76a8ad77441b9e55f')
24
+ end
25
+ it 'can download using Class method' do
26
+ expect(Nexus::Client.download('/tmp',gav.to_s,'/tmp/cache', true, true,'https://repository.jboss.org/nexus') == true)
27
+ expect(File.exists?(file) == true )
28
+ end
29
+
30
+ it 'cache on' do
31
+ expect(Nexus::Client.download('/tmp',gav.to_s,'/tmp/cache', true, true,'https://repository.jboss.org/nexus') == true )
32
+ expect(File.exists?(file)).to be_true
33
+ expect(File.exists?('/tmp/cache/org/glassfish/main/external/ant/387951c0aa333024b25085d76a8ad77441b9e55f.cache')).to be_true
34
+
35
+ end
36
+
37
+ # it 'cache analytics file is created' do
38
+ # FileUtils.rm(file)
39
+ # FileUtils.rm_rf('/tmp/cache')
40
+ # expect(client.download_gav('/tmp',gav.to_s) == true )
41
+ # expect(File.exists?('/tmp/cache/cache_analytics.json') == true )
42
+ # cache = client.cache
43
+ # # expect(cache.analytics['896f6a67964939a62f6b29e3d6fa13139ee92f9a']['time_saved']).to eq(0)
44
+ # # expect(cache.analytics['896f6a67964939a62f6b29e3d6fa13139ee92f9a']['bandwidth_saved']).to eq('0 B')
45
+ # end
46
+
47
+ # it 'cache analytics file is populated correctly' do
48
+ # FileUtils.rm(file)
49
+ # FileUtils.rm_rf('/tmp/cache')
50
+ # n_client = Nexus::Client.new(nil,'/tmp/cache')
51
+ # n_client.download_gav('/tmp',gav.to_s)
52
+ # bytes = n_client.cache.analytics['896f6a67964939a62f6b29e3d6fa13139ee92f9a']['size']
53
+ # bytes = Filesize.from(bytes).to_i
54
+ # time = n_client.cache.analytics['896f6a67964939a62f6b29e3d6fa13139ee92f9a']['total_time_secs']
55
+ # (0..10).each do | num |
56
+ # n_client.download_gav('/tmp',gav.to_s)
57
+ # cache = n_client.cache.analytics['896f6a67964939a62f6b29e3d6fa13139ee92f9a']
58
+ # expect(cache['hit_count']).to eq(num)
59
+ # #expect(cache['time_saved']).to eq(time * num) # errors out due to rounding error
60
+ # #expect(Filesize.from(cache['bandwidth_saved']).to_i).to eq((num * bytes ))
61
+ # FileUtils.rm(file)
62
+ # end
63
+ #
64
+ # end
65
+
66
+ it 'cache off' do
67
+ FileUtils.rm(file) if File.exists?(file)
68
+ FileUtils.rm_rf('/tmp/cache/com')
69
+ expect(Nexus::Client.download('/tmp',gav.to_s,'/tmp/cache', false,false,'https://repository.jboss.org/nexus') == true)
70
+ expect(File.exists?(file) == true )
71
+ expect(File.exists?('/tmp/cache/org/glassfish/main/external/ant/*.cache') == false )
72
+
73
+ end
74
+
75
+ end
76
+