ass_updater 0.1.1

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 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: []