ass_updater 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e0034241f1fb0697994f2b1c81db89bc645aae7e
4
+ data.tar.gz: f25a9d22248cd218f570cef410f7569ac8b832f1
5
+ SHA512:
6
+ metadata.gz: 8b6da7b420b4395f0064c9ef8b0d6b956a6094f4e478cb0b5a64daa59166653e96371e386ac22d2e99d2a93722acd6c0afba61abf15969c2122b223fa4a53081
7
+ data.tar.gz: 9fc79fa2116717b86d55c3a284cc930e4bf74b67ba062b603977a1813a801183c84996824bfc1488fe2c7d7c86ea252a8e4c63f285a89b01d44a64921530c621
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rubocop.yml ADDED
@@ -0,0 +1,13 @@
1
+ AllCops:
2
+ Exclude:
3
+ - 'test/**/*'
4
+ - 'tmp/**/*'
5
+ - 'bin/**/*'
6
+ - 'Rakefile'
7
+ - '*.gemspec'
8
+ Metrics/AbcSize:
9
+ Max: 16 # TODO Lower to default 15
10
+
11
+ Metrics/MethodLength:
12
+ CountComments: false
13
+ Max: 15 # TODO Lower to default 10
data/.travis.yml ADDED
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - 2.1
6
+ - 2.2
7
+ - ruby-head
8
+
9
+ sudo: false
10
+
11
+ before_install: gem install bundler -v 1.10.5
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ass_updater.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,122 @@
1
+ [![Build Status](https://travis-ci.org/leoniv/ass_updater.png)](https://travis-ci.org/leoniv/ass_updater)
2
+ [![Inline docs](http://inch-ci.org/github/leoniv/ass_updater.png)](http://inch-ci.org/github/leoniv/ass_updater)
3
+ [![Code Climate](https://codeclimate.com/github/leoniv/ass_updater/badges/gpa.png)](https://codeclimate.com/github/leoniv/ass_updater)
4
+
5
+ # AssUpdater
6
+
7
+ This gem make easy monitoring of release and to get 1C configuration's updates
8
+ from service http://dounloads.v8.1c.ru.
9
+ For read more about 1C configurations see http://v8.1c.ru
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ ```ruby
16
+ gem 'ass_updater'
17
+ ```
18
+
19
+ And then execute:
20
+
21
+ $ bundle
22
+
23
+ Or install it yourself as:
24
+
25
+ $ gem install ass_updater
26
+
27
+ ## Usage
28
+
29
+ ### Monitoring release configuration's update
30
+
31
+ Write your script `update_monitor.rb` like this:
32
+
33
+ ```ruby
34
+ require 'ass_updater'
35
+
36
+ CONFIGS_ON_SUPPORT = ['HRM 3.0',
37
+ 'Accounting 3.0',
38
+ 'Accounting 2.0',
39
+ 'AccountingKz 2.0'
40
+ ]
41
+ def tmplt_root
42
+ # Default path for windows:
43
+ File.join ENV['APPDATA'].gsub('\\', '/'), '1c', '1cv8', 'tmplts'
44
+ # Or you can set other value
45
+ end
46
+
47
+ def secrets(conf_code_name)
48
+ case conf_code_name
49
+ when 'AccountingKz' then ['user_kz', 'pass_kz']
50
+ else ['user','pass']
51
+ end
52
+ end
53
+
54
+ def new_updates(updater)
55
+ updater.update_history.all_versions.map do |v|
56
+ max = updater.instaled_versions(tmplt_root).max ||\
57
+ AssUpdater::AssVersion.zerro_version
58
+ v if v > max
59
+ end.compact
60
+ end
61
+
62
+ def send_mail(subject, message, attachments=nil)
63
+ #FIXME puts your code
64
+ puts "#{subject} #{message} #{attachments}"
65
+ end
66
+
67
+ def success_report(distrib)
68
+ subject = '1C update monitor report'
69
+ message = "Reseived update for '#{distrib.ass_updater.conf_code_name}' "\
70
+ "version: #{distrib.version}"
71
+ attachments = distrib.file_list.map do |file|
72
+ file if file =~ /(.*readme.*|.*новое.*\.htm)/i
73
+ end.compact
74
+ [subject,message,attachments]
75
+ end
76
+
77
+ def error_report(e)
78
+ subject = '1C update monitor report'
79
+ message = "Error: #{e.to_s}"
80
+ [subject, message]
81
+ end
82
+
83
+ CONFIGS_ON_SUPPORT.each do |i|
84
+ conf_code_name, conf_redaction = *i.split(' ')
85
+ updater = AssUpdater.new(conf_code_name,conf_redaction)
86
+ begin
87
+ updater.get_updates(*secrets(conf_code_name),
88
+ new_updates(updater),
89
+ tmplt_root) do |distrib|
90
+ send_mail *success_report(distrib)
91
+ end
92
+ rescue Exception => e
93
+ send_mail *error_report(e)
94
+ end
95
+ end
96
+ ```
97
+
98
+ and put string into `crontab`:
99
+
100
+ 0 */6 * * * ruby your_path/update_monitor.rb
101
+
102
+ ### Get required upadates
103
+
104
+ If you whant get all updates for your 1C infobase from current version to last release:
105
+
106
+ ```ruby
107
+ require 'ass_updater'
108
+
109
+ updater = AssUpdater.new 'HRM', '3.0'
110
+
111
+ updater.get_updates('user',
112
+ 'password',
113
+ updater.required_versions_for_update(@curen_version),
114
+ @tmplt_root) do |disrib|
115
+ puts "Reseived update #{disrib.version}"
116
+ end
117
+ ```
118
+
119
+ ## Contributing
120
+
121
+ Bug reports and pull requests are welcome on GitHub at https://github.com/leoniv/ass_updater.
122
+
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task :default => :test
11
+
12
+ desc 'Run tests with simplecov'
13
+ task :test_with_simplecov do
14
+ ENV["SIMPLECOV"] = 'YES'
15
+ Rake::Task["test"].invoke
16
+ 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 'ass_updater/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ass_updater"
8
+ spec.version = AssUpdater::VERSION
9
+ spec.authors = ["Leonid Vlasov"]
10
+ spec.email = ["leoniv.vlasov@gmail.com"]
11
+
12
+ spec.summary = %q{Wrapper for 1C configuration updates service}
13
+ spec.description = spec.summary
14
+ spec.homepage = "https://github.com/leoniv/ass_updater"
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_dependency "rubyzip", "~> 1.1"
23
+ spec.add_dependency "nori", "~> 2.6"
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.10"
26
+ spec.add_development_dependency "rake", "~> 10.0"
27
+ spec.add_development_dependency "minitest"
28
+ spec.add_development_dependency "pry"
29
+ spec.add_development_dependency "simplecov"
30
+ end
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "ass_updater"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "pry"
14
+ Pry.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,181 @@
1
+ #-- incoding utf-8
2
+ require 'zip'
3
+ require 'nori'
4
+ require 'ass_updater/version'
5
+
6
+ # AssUpdater - make easy download and install updates for 1C configuration from
7
+ # service http://dounloads.v8.1c.ru. For read more about 1C configurations
8
+ # visit site http://v8.1c.ru
9
+ class AssUpdater
10
+ class Error < StandardError; end
11
+
12
+ require 'ass_updater/ass_version'
13
+ require 'ass_updater/http'
14
+ require 'ass_updater/update_info_service'
15
+ require 'ass_updater/update_info'
16
+ require 'ass_updater/update_history'
17
+ require 'ass_updater/update_distrib'
18
+
19
+ PLATFORM_VERSIONS = { :"8.2" => '8.2', :"8.3" => '8.3' }
20
+ KNOWN_CONF_CODENAME = { HRM: 'Зарплата и управление персоналом',
21
+ Accounting: 'Бухгалтерия предприятия',
22
+ AccountingKz: 'Бухгалтерия для Казахстана' }
23
+ UPDATEREPO_BASE = 'http://downloads.v8.1c.ru/tmplts/'
24
+ UPDATEINFO_BASE = 'http://downloads.1c.ru/ipp/ITSREPV/V8Update/Configs/'
25
+ UPD11_ZIP = 'v8upd11.zip'
26
+
27
+ # See arguments of {#initialize}
28
+ # @return [String]
29
+ attr_reader :conf_code_name, :conf_redaction, :platform_version
30
+ # Object for access to 1C services. It's public for configure http connection.
31
+ # @return [AssUpdater::HTTP]
32
+ attr_accessor :http
33
+
34
+ # @param conf_code_name [String] code name of configuration
35
+ # @param conf_redaction [String] redaction is major version nuber of
36
+ # configuration. See {AssUpdater::AssVersion#redaction}
37
+ # @param platform_version [String] major version namber of target platform
38
+ # 1C:Enterprese.
39
+ # @yield self. It's good place for configure http object. See
40
+ # {AssUpdater::HTTP}
41
+ # @raise [AssUpdater::Error] if given invalid <conf_redaction> or
42
+ # <platform_version>
43
+ def initialize(conf_code_name,
44
+ conf_redaction,
45
+ platform_version = PLATFORM_VERSIONS.keys.last
46
+ )
47
+ @conf_code_name = conf_code_name
48
+ @http = AssUpdater::HTTP.new
49
+ @conf_redaction = AssUpdater.valid_redaction(conf_redaction)
50
+ @platform_version = AssUpdater.valid_platform_version(platform_version)
51
+ yield self if block_given?
52
+ end
53
+
54
+ # Return info about last configuration release from file UpdInfo.txt
55
+ # @note (see AssUpdater::UpdateInfo)
56
+ # @return [AssUpdater::UpdateInfo]
57
+ def update_info
58
+ @update_info ||= AssUpdater::UpdateInfo.new(self)
59
+ end
60
+
61
+ # Return updates history from v8upd11.xml
62
+ # @note (see AssUpdater::UpdateHistory)
63
+ # @return [Hash]
64
+ def update_history
65
+ @update_history ||= AssUpdater::UpdateHistory.new(self)
66
+ end
67
+
68
+ # Evaluate versions required for update configuration
69
+ # from version <from_ver> to version <to_ver>. Return array
70
+ # iclude <to_ver> and exclude <from_ver> If called whithout
71
+ # arguments return versions required for update from version
72
+ # '0.0.0.0' to last release.
73
+ # @param from_ver [String,AssUpdater::AssVersion] if nil from_ver set to
74
+ # '0.0.0.0'
75
+ # @param to_ver [String,AssUpdater::AssVersion] if nill to_ver set to last
76
+ # release
77
+ # @return [Array<AssUpdater::AssVersion>]
78
+ # @raise [ArgumentError] if <from_ver> more then <to_ver>
79
+ def required_versions_for_update(from_ver = nil, to_ver = nil)
80
+ from_ver = AssUpdater::AssVersion.new(from_ver)
81
+ to_ver = AssUpdater::AssVersion.new(to_ver || update_history.max_version)
82
+ if from_ver >= to_ver
83
+ fail ArgumentError, 'from_ver must be less than to_ver'
84
+ end
85
+ r = []
86
+ c_ver = to_ver
87
+ loop do
88
+ r << c_ver
89
+ targets = update_history.target c_ver
90
+ break if targets.size == 0 || targets.index(from_ver)
91
+ c_ver = targets.min
92
+ end
93
+ r
94
+ end
95
+
96
+ # (see AssUpdater::UpdateDistrib)
97
+ # @note (see AssUpdater::UpdateDistrib#get)
98
+ # @param user (see AssUpdater::UpdateDistrib#get)
99
+ # @param password (see AssUpdater::UpdateDistrib#get)
100
+ # @param version (see AssUpdater::UpdateDistrib#initialize)
101
+ # @param tmplt_root (see AssUpdater::UpdateDistrib#initialize)
102
+ # @return (see AssUpdater::UpdateDistrib#get)
103
+ def get_update(user, password, version, tmplt_root)
104
+ distrib = new_update_distrib(version, tmplt_root)
105
+ distrib.get(user, password)
106
+ end
107
+
108
+ # Get updates included in array <versions>. See {#get_update}
109
+ # @param user (see #get_update)
110
+ # @param password (see #get_update)
111
+ # @param versions [Array<String,AssUpdater::AssVersion>]
112
+ # @param tmplt_root (see #get_update)
113
+ # @return [Array<AssUpdater::UpdateDistrib>] returned {#get_update}
114
+ # @yield [AssUpdater::UpdateDistrib] for each getted distrib
115
+ def get_updates(user, password, versions, tmplt_root)
116
+ r = []
117
+ versions.each do |version|
118
+ r << get_update(user, password, version, tmplt_root)
119
+ yield r.last if block_given?
120
+ end
121
+ r
122
+ end
123
+
124
+ # Return versions all instaled updates finded in 1C templates directory
125
+ # <tmplt_root>
126
+ # @param tmplt_root (see #get_update)
127
+ # @return [Array<AssUpdater::AssVersion>]
128
+ def instaled_versions(tmplt_root)
129
+ (Dir.entries(conf_distribs_local_path(tmplt_root)).map do |e|
130
+ next if e == '.' || e == '..'
131
+ begin
132
+ v = AssUpdater::AssVersion.new(e.split('_').join('.'))
133
+ v if v.redaction == conf_redaction
134
+ rescue ArgumentError
135
+ nil
136
+ end
137
+ end).compact
138
+ end
139
+
140
+ # Return all instaled updates findet in 1C templates directory
141
+ # @note return distirbs present in {#update_history} only
142
+ # @param tmplt_root (see #get_update)
143
+ # @return [Array<AssUpdater::UpdateDistrib>]
144
+ def instaled_distribs(tmplt_root)
145
+ instaled_versions(tmplt_root).map do |v|
146
+ begin
147
+ new_update_distrib(v, tmplt_root)
148
+ rescue AssUpdater::Error
149
+ nil
150
+ end
151
+ end.compact
152
+ end
153
+
154
+ # Wrapper return UpdateDistrib object
155
+ # @param version (see #get_update)
156
+ # @param tmplt_root (see #get_update)
157
+ # @return [AssUpdater::UpdateDistrib]
158
+ def new_update_distrib(version, tmplt_root)
159
+ AssUpdater::UpdateDistrib.new(version, tmplt_root, self)
160
+ end
161
+
162
+ private
163
+
164
+ def conf_distribs_local_path(tmplt_root)
165
+ File.join(tmplt_root, '1c', conf_code_name)
166
+ end
167
+
168
+ def self.valid_platform_version(v)
169
+ unless PLATFORM_VERSIONS.key?(v.to_sym)
170
+ fail AssUpdater::Error,
171
+ "Invalid platform_version `#{v}'."\
172
+ "Support #{PLATFORM_VERSIONS.keys.join(' | ')} versions only."
173
+ end
174
+ PLATFORM_VERSIONS[v.to_sym]
175
+ end
176
+
177
+ def self.valid_redaction(r)
178
+ fail AssUpdater::Error, "Invalid redaction #{r}" unless r =~ /\d\.\d/
179
+ r
180
+ end
181
+ end
@@ -0,0 +1,107 @@
1
+ class AssUpdater
2
+ # Class implement 1C version numbering. 1C version consist from 4 digt group.
3
+ # Major 1st and 2nd group called *Redaction*.
4
+ class AssVersion
5
+ # Value of digit group
6
+ # @return [Fixrnum]
7
+ attr_reader :_1, :_2, :_3, :_4
8
+
9
+ class << self
10
+ # Return zerro vesion number '0.0.0.0'
11
+ # @return [AssUpdater::AssVersion]
12
+ def zerro_version
13
+ new('0.0.0.0')
14
+ end
15
+
16
+ # Convert [Array<String>] to [Array<AssUpdater::AssVersion>]
17
+ # @return [Array<AssUpdater::AssVersion>]
18
+ def convert_array(a)
19
+ a.map do |i|
20
+ new(i)
21
+ end
22
+ end
23
+ end
24
+
25
+ # Return true if it is zerro version see
26
+ # {.zerro_version}
27
+ def zerro?
28
+ to_s == '0.0.0.0'
29
+ end
30
+
31
+ # @param v [String AssUpdater::AssVersion] if not given return
32
+ # {.zerro_version}
33
+ def initialize(v = nil)
34
+ v ||= '0.0.0.0'
35
+ unless v.to_s =~ /^(\d)+\.(\d+)\.(\d+)\.(\d+)$/
36
+ fail ArgumentError,
37
+ "Invalid version string `#{v}'. Expect 'd.d.d.d' format"
38
+ end
39
+ @_1 = Regexp.last_match(1).to_i
40
+ @_2 = Regexp.last_match(2).to_i
41
+ @_3 = Regexp.last_match(3).to_i
42
+ @_4 = Regexp.last_match(4).to_i
43
+ end
44
+
45
+ # Conver version to array of digit group
46
+ # @return [Array<Fixnum>]
47
+ def to_a
48
+ [@_1, @_2, @_3, @_4]
49
+ end
50
+
51
+ # Convert version to string
52
+ # @return [Stgring]
53
+ def to_s
54
+ to_a.join('.')
55
+ end
56
+
57
+ # Return redaction number
58
+ # @return [String]
59
+ def redaction
60
+ to_a.shift(2).join('.')
61
+ end
62
+
63
+ # Compare versions
64
+ # @return [Boollean]
65
+ def <=>(other)
66
+ merge(other).each do |v|
67
+ if v[0] > v[1]
68
+ return 1
69
+ elsif v[0] < v[1]
70
+ return -1
71
+ end
72
+ end
73
+ 0
74
+ end
75
+
76
+ # (see #<=>)
77
+ def ==(other)
78
+ (self <=> other) == 0
79
+ end
80
+
81
+ # (see #<=>)
82
+ def >(other)
83
+ (self <=> other) == 1
84
+ end
85
+
86
+ # (see #<=>)
87
+ def <(other)
88
+ (self <=> other) == -1
89
+ end
90
+
91
+ # (see #<=>)
92
+ def >=(other)
93
+ (self <=> other) >= 0
94
+ end
95
+
96
+ # (see #<=>)
97
+ def <=(other)
98
+ (self <=> other) <= 0
99
+ end
100
+
101
+ private
102
+
103
+ def merge(o)
104
+ to_a.zip o.to_a
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,79 @@
1
+ require 'net/http'
2
+
3
+ class AssUpdater
4
+ # HTTP access to 1C services.
5
+ # @note 1C servise often unavaileble and {#get} fail on timeout
6
+ class HTTP
7
+ # Value of useragent controled 1C web server and server may return 403 error
8
+ USER_AGENT_DEFAULT = '1C+Enterprise/8.2'
9
+ # (see USER_AGENT_DEFAULT)
10
+ # @return [String]
11
+ attr_accessor :user_agent
12
+ # see {#initialize} param
13
+ # @return [Hash]
14
+ attr_accessor :proxy_options
15
+ # see Net::HTTP#open_timeout
16
+ # @note (see AssUpdater::HTTP)
17
+ attr_accessor :open_timeout
18
+ # see Net::HTTP#read_timeout
19
+ # @note (see AssUpdater::HTTP)
20
+ attr_accessor :read_timeout
21
+
22
+ # @param proxy_options [Hash] options for proxy server
23
+ def initialize(proxy_options = {})
24
+ self.open_timeout = 30 # fucking 1C
25
+ self.user_agent = USER_AGENT_DEFAULT
26
+ self.proxy_options = { addr: nil,
27
+ port: nil,
28
+ user: nil,
29
+ pass: nil }.merge(proxy_options)
30
+ yeld self if block_given?
31
+ end
32
+
33
+ # @note (see AssUpdater::HTTP)
34
+ # @param uri_str [String]
35
+ # @param user_name [String] user 1C sevice
36
+ # @param password [String]
37
+ def get(uri_str, user_name = nil, password = nil)
38
+ response = _http(URI(uri_str)).request(_get(user_name,
39
+ password,
40
+ URI(uri_str)
41
+ )
42
+ )
43
+ _body(response, uri_str)
44
+ end
45
+
46
+ private
47
+
48
+ def _body(response, uri_str)
49
+ if response.code != '200'
50
+ fail AssUpdater::Error,
51
+ "#{response.code} #{response.message} for `#{uri_str}'"
52
+ end
53
+ response.body
54
+ end
55
+
56
+ def _http(uri)
57
+ h = Net::HTTP.new(uri.host,
58
+ uri.port,
59
+ proxy_options[:addr],
60
+ proxy_options[:port],
61
+ proxy_options[:user],
62
+ proxy_options[:pass]
63
+ )
64
+ timeouts h
65
+ end
66
+
67
+ def timeouts(h)
68
+ h.open_timeout = open_timeout
69
+ h.read_timeout = read_timeout
70
+ h
71
+ end
72
+
73
+ def _get(user, pass, uri)
74
+ g = Net::HTTP::Get.new(uri.path, 'User-Agent' => user_agent)
75
+ g.basic_auth user, pass if user
76
+ g
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,89 @@
1
+ #-- encoding utf-8
2
+
3
+ class AssUpdater
4
+ # Implement work with distributives of configuration update
5
+ class UpdateDistrib
6
+ attr_reader :ass_updater, :version_info, :version, :target, :tmplt_root
7
+
8
+ # @param ass_updater [AssUpdater] owner object
9
+ # @param version [String AssUpdater::AssVersion]
10
+ # @param tmplt_root [String] path to 1C update templates
11
+ def initialize(version, tmplt_root, ass_updater)
12
+ @ass_updater = ass_updater
13
+ @version = AssUpdater::AssVersion.new(version)
14
+ @version_info = @ass_updater.update_history[@version]
15
+ @tmplt_root = tmplt_root
16
+ @target = AssUpdater::AssVersion.convert_array version_info['target']
17
+ end
18
+
19
+ # Download <version> distributive of configuration update and uzip into
20
+ # tmplt_root. Exists in template_root distrib will be overwritten.
21
+ # @note Require authorization.
22
+ # @note Service http://downloads.v8.1c.ru
23
+ # often unavailable and it fail on timeout. Don't worry and try again.
24
+ # @param user [String] authorization user name
25
+ # @param password [String] authorization password
26
+ # @return [AssUpdater::UpdateDistrib] self
27
+ def get(user, password)
28
+ zip_f = Tempfile.new('1cv8_zip')
29
+ begin
30
+ download_distrib(zip_f, user, password)
31
+ zip_f.rewind
32
+ unzip_all(zip_f)
33
+ ensure
34
+ zip_f.close
35
+ zip_f.unlink
36
+ end
37
+ self
38
+ end
39
+
40
+ # Return path to distributive zip file on http server
41
+ def file
42
+ File.join(AssUpdater::UPDATEREPO_BASE, fix_path(version_info_file))
43
+ end
44
+
45
+ # Return local path where distributive installed
46
+ def local_path
47
+ File.join(tmplt_root, File.dirname(version_info_file))
48
+ end
49
+
50
+ # Return files included in distributive. Files find in {#local_path}
51
+ # @param pattern (see Dir::glob)
52
+ def file_list(pattern = '*')
53
+ Dir.glob(File.join(local_path, pattern)).map do |f|
54
+ f.force_encoding 'UTF-8'
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ def version_info_file
61
+ fix_path version_info['file']
62
+ end
63
+
64
+ def fix_path(path)
65
+ path.tr '\\', '/'
66
+ end
67
+
68
+ def unzip_all(zip_f)
69
+ dest_dir = ''
70
+ Zip::File.open(zip_f.path) do |zf|
71
+ dest_dir = FileUtils.mkdir_p(local_path)[0]
72
+ zf.each do |entry|
73
+ dest_file = File.join(dest_dir, entry.name.encode('UTF-8', 'cp866'))
74
+ FileUtils.rm_r(dest_file) if File.exist?(dest_file)
75
+ entry.extract(dest_file)
76
+ end
77
+ end
78
+ dest_dir
79
+ end
80
+
81
+ def download_distrib(tmp_f, user, password)
82
+ tmp_f.write(ass_updater.http.get(file,
83
+ user,
84
+ password
85
+ )
86
+ )
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,99 @@
1
+ #-- incoding utf-8
2
+
3
+ class AssUpdater
4
+ #
5
+ # Handle fo updtade history from v8upd11.xml
6
+ # @note (see AssUpdater::UpdateInfoService)
7
+ #
8
+ class UpdateHistory < AssUpdater::UpdateInfoService
9
+ # Returm min distrib version from update history
10
+ # @return [AssUpdater::AssVersion]
11
+ def min_version
12
+ all_versions.min
13
+ end
14
+
15
+ # Return max version from update histry
16
+ # @return [AssUpdater::AssVersion]
17
+ def max_version
18
+ all_versions.max
19
+ end
20
+
21
+ # Return all versions found in histry
22
+ # @return [Array<AssUpdater::AssVersion>]
23
+ def all_versions
24
+ r = []
25
+ raw['update'].each do |h|
26
+ r << h['version']
27
+ end
28
+ AssUpdater::AssVersion.convert_array r
29
+ end
30
+
31
+ # Return info about version <version>
32
+ # @param version [String,AssUpdater::AssVersion]
33
+ # @return [Hash]
34
+ # @raise [AssUpdater::Error] if info for version not found
35
+ def [](version)
36
+ return [min_version] if version.to_s == '0.0.0.0'
37
+ raw['update'].each do |h|
38
+ next if h['version'] != version.to_s
39
+ h['target'] = [] << h['target'] if h['target'].is_a? String
40
+ return h
41
+ end
42
+ fail AssUpdater::Error, "Unkown version number `#{version}'"
43
+ end
44
+
45
+ # Return array of target versions for update to version <version>
46
+ # @param version [String,AssUpdater::AssVersion]
47
+ # @return [Array<AssUpdater::AssVersion>]
48
+ # @note (see #ex
49
+ def target(version)
50
+ exclude_unknown_version(
51
+ AssUpdater::AssVersion.convert_array self[version]['target']
52
+ )
53
+ end
54
+
55
+ private
56
+
57
+ # @note Often ['target'] containe incorrect version number
58
+ # not fonded in {#all_versions}.
59
+ #
60
+ def exclude_unknown_version(a)
61
+ a.map do |i|
62
+ i if all_versions.index(i)
63
+ end.compact
64
+ end
65
+
66
+ def parse
67
+ r = Nori.new(parser: :rexml,
68
+ strip_namespaces: true).parse(get)['updateList']
69
+ r['update'] = [] << r['update'] if r['update'].is_a? Hash
70
+ r
71
+ end
72
+
73
+ def get
74
+ zip_f = Tempfile.new('upd11_zip')
75
+ begin
76
+ zip_f.write(ass_updater.http.get("#{updateinfo_path}/#{UPD11_ZIP}"))
77
+ zip_f.rewind
78
+ xml = unzip(zip_f)
79
+ ensure
80
+ zip_f.close
81
+ zip_f.unlink
82
+ end
83
+ xml.force_encoding 'UTF-8'
84
+ end
85
+
86
+ def unzip(zip_f)
87
+ xml = ''
88
+ Zip::File.open(zip_f.path) do |zf|
89
+ upd11_zip = zf.glob('v8cscdsc.xml').first
90
+ unless upd11_zip
91
+ fail AssUpdater::Error,
92
+ "File `v8cscdsc.xml' not fount in zip `#{UPD11_ZIP}'"
93
+ end
94
+ xml = upd11_zip.get_input_stream.read
95
+ end
96
+ xml
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,39 @@
1
+ #-- encoding utf-8
2
+
3
+ class AssUpdater
4
+ #
5
+ # Handle for UpdInfo.txt
6
+ #
7
+ class UpdateInfo < AssUpdater::UpdateInfoService
8
+ UPDINFO_TXT = 'UpdInfo.txt'
9
+
10
+ # Return last configuration release version from file UpdInfo.txt.
11
+ # @return [AssUpdater::AssVersion]
12
+ def version
13
+ AssUpdater::AssVersion.new(self[:version])
14
+ end
15
+
16
+ # Return value for key from UpdInfo.txt
17
+ # @param key [Symbol] :version, :from_versions, :update_date
18
+ def [](key)
19
+ raw[key]
20
+ end
21
+
22
+ private
23
+
24
+ def parse
25
+ get =~ /Version=([\d\.]*)(\s*)FromVersions=\
26
+ [;]?([\d\.\;]*)(\s*)UpdateDate=([\d\.]*)/im
27
+ r = { version: Regexp.last_match(1),
28
+ from_versions: [],
29
+ update_date: Regexp.last_match(5)
30
+ }
31
+ r[:from_versions] = Regexp.last_match(3).split(';') if Regexp.last_match 3
32
+ r
33
+ end
34
+
35
+ def get
36
+ ass_updater.http.get("#{updateinfo_path}/#{UPDINFO_TXT}")
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,38 @@
1
+ #-- encoding utf-8
2
+
3
+ class AssUpdater
4
+ # @abstract
5
+ # @note Service http://downloads.1c.ru often unavailable and initialize fail
6
+ # on timeout. Don't worry and try again.
7
+ class UpdateInfoService
8
+ attr_reader :ass_updater
9
+
10
+ # @param ass_updater [AssUpdater] owner objec
11
+ def initialize(ass_updater)
12
+ @ass_updater = ass_updater
13
+ raw
14
+ end
15
+
16
+ private
17
+
18
+ # Return raw data
19
+ # @return [Hash]
20
+ def raw
21
+ @raw ||= parse
22
+ end
23
+
24
+ def updateinfo_base
25
+ AssUpdater::UPDATEINFO_BASE
26
+ end
27
+
28
+ def updateinfo_path
29
+ "#{updateinfo_base}/#{ass_updater.conf_code_name}/"\
30
+ "#{ass_updater.conf_redaction.sub('.', '')}/"\
31
+ "#{ass_updater.platform_version.sub('.', '')}/"
32
+ end
33
+
34
+ def parse
35
+ fail 'Abstract method called'
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,4 @@
1
+ #--
2
+ class AssUpdater
3
+ VERSION = '0.1.1'
4
+ end
metadata ADDED
@@ -0,0 +1,159 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ass_updater
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Leonid Vlasov
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-10-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rubyzip
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: nori
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '2.6'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '2.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.10'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.10'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: simplecov
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: Wrapper for 1C configuration updates service
112
+ email:
113
+ - leoniv.vlasov@gmail.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - .gitignore
119
+ - .rubocop.yml
120
+ - .travis.yml
121
+ - Gemfile
122
+ - README.md
123
+ - Rakefile
124
+ - ass_updater.gemspec
125
+ - bin/console
126
+ - bin/setup
127
+ - lib/ass_updater.rb
128
+ - lib/ass_updater/ass_version.rb
129
+ - lib/ass_updater/http.rb
130
+ - lib/ass_updater/update_distrib.rb
131
+ - lib/ass_updater/update_history.rb
132
+ - lib/ass_updater/update_info.rb
133
+ - lib/ass_updater/update_info_service.rb
134
+ - lib/ass_updater/version.rb
135
+ homepage: https://github.com/leoniv/ass_updater
136
+ licenses:
137
+ - MIT
138
+ metadata: {}
139
+ post_install_message:
140
+ rdoc_options: []
141
+ require_paths:
142
+ - lib
143
+ required_ruby_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - '>='
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ required_rubygems_version: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - '>='
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ requirements: []
154
+ rubyforge_project:
155
+ rubygems_version: 2.0.14
156
+ signing_key:
157
+ specification_version: 4
158
+ summary: Wrapper for 1C configuration updates service
159
+ test_files: []