nexus_client 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+