zypper-upgraderepo 1.0.2 → 1.5.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,42 @@
1
+ require 'delegate'
2
+ require_relative 'traversable.rb'
3
+ require_relative 'requests/local.rb'
4
+ require_relative 'requests/http.rb'
5
+
6
+ module Zypper
7
+ module Upgraderepo
8
+
9
+
10
+ class Request
11
+
12
+ def self.build(repo, timeout)
13
+ @@registry ||= self.load_requests
14
+
15
+ raise InvalidProtocol, repo unless @@registry.include? repo.protocol
16
+
17
+ Object.const_get(@@registry[repo.protocol]).new(repo, timeout)
18
+ end
19
+
20
+ def self.protocols
21
+ self.load_requests.keys
22
+ end
23
+
24
+ private
25
+
26
+ def self.load_requests
27
+ res = {}
28
+ Requests.constants.each do |klass|
29
+ Object.const_get("Zypper::Upgraderepo::Requests::#{klass}").register_protocol.each do |protocol|
30
+ res[protocol] = "Zypper::Upgraderepo::Requests::#{klass}"
31
+ end
32
+ end
33
+
34
+ res
35
+ end
36
+
37
+ end
38
+
39
+
40
+
41
+ end
42
+ end
@@ -0,0 +1,131 @@
1
+ require 'delegate'
2
+ require 'net/http'
3
+
4
+ module Zypper
5
+ module Upgraderepo
6
+
7
+ class PageRequest < SimpleDelegator
8
+
9
+ attr_reader :page
10
+
11
+ USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0'
12
+
13
+ def initialize(obj, timeout = 60)
14
+ super obj
15
+ @timeout = timeout
16
+ end
17
+
18
+ def available?
19
+ ping.is_a?(Net::HTTPSuccess)
20
+ end
21
+
22
+ def redirected?
23
+ ping.is_a?(Net::HTTPRedirection)
24
+ end
25
+
26
+ def redirected_to
27
+ ping['location']
28
+ end
29
+
30
+ def not_found?
31
+ ping.is_a?(Net::HTTPNotFound)
32
+ end
33
+
34
+ def forbidden?
35
+ ping.is_a?(Net::HTTPForbidden)
36
+ end
37
+
38
+ def timeout?
39
+ ping.is_a?(Net::HTTPRequestTimeOut)
40
+ end
41
+
42
+ def status
43
+ ping.class.to_s
44
+ end
45
+
46
+ def cache!
47
+ @page = nil
48
+ end
49
+
50
+
51
+ private
52
+
53
+ def get_request(uri, head)
54
+
55
+ if head
56
+ request = Net::HTTP::Head.new(uri.request_uri)
57
+ else
58
+ request = Net::HTTP::Get.new(uri.request_uri)
59
+ end
60
+
61
+ request['User-Agent'] = USER_AGENT
62
+
63
+ http = Net::HTTP.new(uri.host, uri.port)
64
+ http.use_ssl = (uri.scheme == 'https')
65
+ http.open_timeout = @timeout
66
+
67
+ http.request(request)
68
+ end
69
+
70
+ def ping(uri = nil, head = true)
71
+ begin
72
+ if @page.nil? || uri
73
+ @page = get_request(uri, head)
74
+ end
75
+ rescue SocketError
76
+ raise NoConnection
77
+ rescue Net::OpenTimeout
78
+ @page = Net::HTTPRequestTimeOut.new('1.1', '', '')
79
+ end
80
+ @page
81
+ end
82
+
83
+ end
84
+
85
+
86
+ module Requests
87
+
88
+ class HttpRequest < PageRequest
89
+
90
+ include Traversable
91
+
92
+ def max_drop_back; 0; end
93
+
94
+ def self.register_protocol; ['https', 'http'] end
95
+
96
+ def evaluate_alternative(version)
97
+ if not_found?
98
+ return traverse_url(URI(url), version)
99
+ elsif redirected?
100
+ return { url: redirected_to, message: 'Redirected to:' }
101
+ end
102
+ end
103
+
104
+
105
+ private
106
+
107
+ def get_request(uri, head)
108
+ #super uri || URI(url), head
109
+ super uri || repodata_uri, head
110
+ end
111
+
112
+ def has_repodata?(uri)
113
+ ping(repodata_uri(uri))
114
+ available?
115
+ end
116
+
117
+ def subfolders
118
+ res = ping.body.to_s.scan(Regexp.new('href=[\'\"][^\/\"]+\/[\'\"]')).delete_if do |x|
119
+ x =~ /^\// || x =~ /^\.\./ || x =~ /\:\/\// || x =~ /href=[\"\'](media\.1|boot|EFI)\/[\"\']/
120
+ end.uniq.map do |d|
121
+ d.scan(/href=[\"\']([^"]+)[\'\"]/).pop.pop
122
+ end
123
+
124
+ res
125
+ end
126
+ end
127
+
128
+ end
129
+
130
+ end
131
+ end
@@ -0,0 +1,94 @@
1
+ require 'delegate'
2
+
3
+ module Zypper
4
+ module Upgraderepo
5
+
6
+
7
+ class DirRequest < SimpleDelegator
8
+
9
+ attr_reader :dir_path
10
+
11
+ def initialize(obj, timeout)
12
+ super obj
13
+ end
14
+
15
+ def available?
16
+ Dir.exist? ping
17
+ end
18
+
19
+ def redirected?
20
+ File.symlink? ping
21
+ end
22
+
23
+ def redirected_to
24
+ File.realpath ping
25
+ end
26
+
27
+ def not_found?
28
+ !available?
29
+ end
30
+
31
+ def forbidden?
32
+ File.readable? ping
33
+ end
34
+
35
+ def timeout?
36
+ false
37
+ end
38
+
39
+ def status
40
+ File.stat ping
41
+ end
42
+
43
+ def cache!
44
+ @dir_path = nil
45
+ end
46
+
47
+
48
+ private
49
+
50
+ def ping(uri = nil, head = true)
51
+ @dir_path ||= URI(url).path
52
+
53
+ @dir_path = uri.to_s =~ /^\// ? uri.to_s : URI(uri.to_s).path if uri
54
+
55
+ URI.unescape(@dir_path)
56
+ end
57
+
58
+ end
59
+
60
+
61
+ module Requests
62
+
63
+ class LocalRequest < DirRequest
64
+
65
+ include Traversable
66
+
67
+ def max_drop_back; 1 end
68
+
69
+ def self.register_protocol; ['dir'] end
70
+
71
+ def evaluate_alternative(version)
72
+ if not_found?
73
+ return traverse_url(URI(url), version)
74
+ elsif redirected?
75
+ return { url: redirected_to, message: 'Linked to' }
76
+ end
77
+ end
78
+
79
+
80
+ private
81
+
82
+ def has_repodata?(uri)
83
+ File.exist? URI.unescape(repodata_uri(uri).path)
84
+ end
85
+
86
+ def subfolders
87
+ Dir.glob(ping.gsub(/\/$/, '') + '/*/').map { |x| URI.escape(x.gsub(/\/$/, '').gsub(ping, '').gsub(/^\//, '')) }
88
+ end
89
+ end
90
+
91
+ end
92
+
93
+ end
94
+ end
@@ -0,0 +1,93 @@
1
+ module Zypper
2
+ module Upgraderepo
3
+
4
+ module Traversable
5
+
6
+ def traverse_url(uri, version)
7
+ ping(uri)
8
+
9
+ if forbidden?
10
+ res = { url: url, message: 'Can\'t navigate through the repository!' }
11
+ elsif available? && uri.to_s =~ /#{version}/
12
+ res = traverse_url_forward(uri, version)
13
+ else
14
+ res = traverse_url_backward(uri, version)
15
+ end
16
+
17
+ res || { url: '', message: 'Can\'t find a valid alternative, try manually!' }
18
+ end
19
+
20
+
21
+ private
22
+
23
+ def traverse_url_backward(uri, version)
24
+ uri.path = File.dirname(uri.path)
25
+
26
+ return nil if uri.path == '/' || uri.path == '.' || (versioned? && (drop_back_level(uri) > max_drop_back))
27
+
28
+ uri.path += '/' if uri.path[-1] != '/'
29
+ ping(uri, false)
30
+
31
+ if not_found?
32
+ return traverse_url_backward(uri, version)
33
+ elsif available?
34
+ if res = traverse_url_forward(uri, version)
35
+ return res
36
+ else
37
+ return traverse_url_backward(uri, version)
38
+ end
39
+ elsif forbidden?
40
+ return { url: uri.to_s, message: 'Try to replace with this one' } if has_repodata?(uri)
41
+
42
+ return traverse_url_backward(uri, version)
43
+ end
44
+
45
+ nil
46
+ end
47
+
48
+ def traverse_url_forward(uri, version)
49
+ uri.path += '/' if uri.path[-1] != '/'
50
+ ping(uri, false)
51
+
52
+ subfolders.each do |dir|
53
+ u = URI(uri.to_s)
54
+ u.path += dir
55
+
56
+ if has_repodata?(u)
57
+ if (versioned?) && (u.to_s =~ /#{version}/)
58
+ return { url: u.to_s, message: 'Override with this one' }
59
+ end
60
+ else
61
+ res = traverse_url_forward(u, version)
62
+ return res if res.class == Hash
63
+ end
64
+ end
65
+
66
+ nil
67
+ end
68
+
69
+ def repodata_uri(uri = nil)
70
+ if uri
71
+ uri = URI(uri.to_s)
72
+ else
73
+ uri = URI(url)
74
+ end
75
+
76
+ uri.path = uri.path.gsub(/\/$/, '') + '/repodata/repomd.xml'
77
+
78
+ uri
79
+ end
80
+
81
+ def drop_back_level(uri)
82
+ URI(url).path.split('/').index { |x| x =~ /\d\d.\d/ } - uri.path.split('/').count
83
+ end
84
+
85
+ # to implement on each repository type class
86
+ #
87
+ # def has_repodata?(uri)
88
+ #
89
+ # def subfolders
90
+
91
+ end
92
+ end
93
+ end
@@ -25,12 +25,19 @@ module Zypper
25
25
  def new_line; "\n#{self}" end
26
26
  end
27
27
 
28
+ class ::StandardError
29
+ def error_code
30
+ 1
31
+ end
32
+ end
28
33
 
29
34
  class Messages
30
35
 
31
36
  def self.error(e)
32
37
  if e.class == String
33
38
  puts ' [E] '.bold.red + e
39
+ elsif e.class == Interruption
40
+ STDERR.puts e.message =~ /\(/ ? e.message.gsub(/.*\((.*)\).*/, '\1').green : e.message.green
34
41
  else
35
42
  STDERR.puts 'Error! '.bold.red + e.message
36
43
  end
@@ -44,59 +51,89 @@ module Zypper
44
51
  puts ' [W] '.bold.yellow + m
45
52
  end
46
53
 
47
- def self.available(num, name, url, max_col)
48
- Messages.ok("| #{num.to_s.rjust(2)} | #{name.ljust(max_col, ' ')} |")
54
+ end
55
+
56
+ class FileNotFound < StandardError
57
+ def initialize(filename)
58
+ super "The File #{filename} doesn't exist."
59
+ end
60
+ end
61
+
62
+ class ReleaseFileNotFound < StandardError
63
+ def initialize
64
+ super 'The release file is not found.'
49
65
  end
66
+ end
50
67
 
51
- def self.redirected(num, name, url, max_col, redirected)
52
- Messages.warning("| #{num.to_s.rjust(2)} | #{name.ljust(max_col, ' ')} | Redirection of #{url} ")
53
- puts " #{' ' * 3} | #{' ' * 2} | #{ ' ' * max_col} | #{'To:'.bold.yellow} #{redirected}"
68
+ class InvalidProtocol < StandardError
69
+ def initialize(repo)
70
+ super "The repository #{repo.name} has an unknown protocol: #{repo.protocol}; disable it to continue."
54
71
  end
72
+ end
55
73
 
56
- def self.not_found(num, name, url, max_col)
57
- Messages.error("| #{num.to_s.rjust(2)} | #{name.ljust(max_col, ' ')}")
74
+ class InvalidVersion < StandardError
75
+ def initialize(version)
76
+ super "The version #{version} is not valid"
58
77
  end
78
+ end
59
79
 
60
- def self.alternative(num, name, url, max_col, res)
61
- Messages.error("| #{num.to_s.rjust(2)} | #{name.ljust(max_col, ' ')} | #{res[:message].bold.yellow}")
62
- puts " #{' ' * 3} | #{' ' * 2} | #{' ' * max_col} | #{res[:url]}" unless res[:url].to_s.empty?
80
+ class InvalidWritePermissions < StandardError
81
+ def initialize(filename)
82
+ super "Don't have the right permission to write #{filename}"
63
83
  end
64
84
 
65
- def self.separator
66
- puts '-' * 90
85
+ def error_code
86
+ 4
67
87
  end
88
+ end
68
89
 
69
- def self.header(max_col)
70
- puts " St. | # | #{'Name'.ljust(max_col, ' ')} | Hint"
90
+ class SystemUpdateRunning < StandardError
91
+ def initialize(args)
92
+ super "The application #{args[:process].bold} with pid #{args[:pid].bold} is running a system update!"
71
93
  end
72
94
 
73
- def self.footer
74
- self.separator
95
+ def error_code
96
+ 5
75
97
  end
76
98
  end
77
99
 
100
+ class UnableToUpgrade < StandardError
101
+ def initialize(args)
102
+ super "The repository n.#{args[:num].to_s.bold.red} named #{args[:repo].name.bold.red} can't be upgraded, a manual check is required!"
103
+ end
78
104
 
79
- class ReleaseFileNotFound < StandardError
80
- def initialize
81
- super 'The release file is not found.'
105
+ def error_code
106
+ 7
82
107
  end
83
108
  end
84
-
85
- class InvalidVersion < StandardError
86
- def initialize(version)
87
- super "The version #{version} is not valid"
109
+
110
+ class MissingOverride < StandardError
111
+ def initialize(args)
112
+ super "The repository n.#{args[:num].to_s.bold.red} named #{args[:ini]['name'].bold.red} doesn't contain the URL key!"
113
+ end
114
+
115
+ def error_code
116
+ 8
88
117
  end
89
118
  end
90
119
 
91
- class InvalidPermissions < StandardError
92
- def initialize(filename)
93
- super "Don't have the right permission to write #{filename}"
120
+ class UnmatchingOverrides < StandardError
121
+ def initialize(args)
122
+ super "The repository n.#{args[:num]} named #{args[:repo].name.bold.red} doesn't match with the repository named #{args[:ini]['name'].bold.red} in the ini file"
123
+ end
124
+
125
+ def error_code
126
+ 9
94
127
  end
95
128
  end
96
129
 
97
130
  class AlreadyUpgraded < StandardError
98
131
  def initialize(version)
99
- super "The system is already upgraded to #{version}"
132
+ super "The system is already upgraded to the #{version} version"
133
+ end
134
+
135
+ def error_code
136
+ 2
100
137
  end
101
138
  end
102
139
 
@@ -104,6 +141,20 @@ module Zypper
104
141
  def initialize
105
142
  super 'Internet connection has some trouble'
106
143
  end
144
+
145
+ def error_code
146
+ 6
147
+ end
107
148
  end
149
+
150
+ class Interruption < StandardError
151
+ def initialize
152
+ super 'Ok ok... Exiting!'
153
+ end
154
+ end
155
+
156
+ Signal.trap('INT') { raise Interruption }
157
+
158
+ Signal.trap('TERM') { raise Interruption }
108
159
  end
109
160
  end