itunes_store_transporter 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,103 @@
1
+ require "optout"
2
+ require "itunes/store/transporter"
3
+ require "itunes/store/transporter/shell"
4
+ require "itunes/store/transporter/errors"
5
+ require "itunes/store/transporter/output_parser"
6
+ require "itunes/store/transporter/command/option"
7
+
8
+ module ITunes
9
+ module Store
10
+ class Transporter
11
+ module Command # :nodoc: all
12
+
13
+ class Base
14
+ include Option
15
+
16
+ def initialize(config, default_options = {})
17
+ @config = config
18
+ @shell = Shell.new(@config[:path])
19
+ @default_options = default_options
20
+ end
21
+
22
+ def run(options = {})
23
+ options = default_options.merge(options)
24
+ argv = create_transporter_options(options)
25
+ stdout_lines = []
26
+ stderr_lines = []
27
+
28
+ # TODO: hooks
29
+ exitcode = @shell.exec(argv) do |line, name|
30
+ if name == :stdout
31
+ stdout_lines << line
32
+ $stdout.puts line if config[:print_stdout]
33
+ else
34
+ stderr_lines << line
35
+ $stderr.puts line if config[:print_stderr]
36
+ end
37
+ end
38
+
39
+ if exitcode == 0
40
+ handle_success(stdout_lines, stderr_lines, options)
41
+ else
42
+ handle_error(stdout_lines, stderr_lines, options, exitcode)
43
+ end
44
+ end
45
+
46
+ protected
47
+ attr :config
48
+ attr :default_options
49
+
50
+ def options
51
+ @options ||= Optout.options do
52
+ # On Windows we must include this else the Transporter batch script will call `pause` after the Transporter exits
53
+ on :windows, "-WONoPause"
54
+ # Optout can't do this: [a, b, c] => -X a -X b -X c
55
+ on :jvm, "-X" #, :multiple => true
56
+ end
57
+ end
58
+
59
+ # TODO: conf[:warnings]
60
+ def handle_success(stdout_lines, stderr_lines, options)
61
+ stdout_lines.join
62
+ end
63
+
64
+ def handle_error(stdout_lines, stderr_lines, options, exitcode)
65
+ parser = Transporter::OutputParser.new(stderr_lines)
66
+ errors = parser.errors.any? ? parser.errors : [ TransporterMessage.new(stderr_lines.join) ]
67
+ raise ITunes::Store::Transporter::ExecutionError.new(errors, exitcode)
68
+ end
69
+
70
+ def create_transporter_options(optz)
71
+ optz[:windows] = "true" if Transporter::Shell.windows?
72
+ options.argv(optz)
73
+ rescue Optout::OptionError => e
74
+ raise ITunes::Store::Transporter::OptionError, e.message
75
+ end
76
+ end
77
+
78
+ class Mode < Base
79
+ def initialize(*config)
80
+ super
81
+ options.on :log, "-o", Optout::File
82
+ options.on :verbose, "-v", %w|informational critical detailed eXtreme| # Since log output is critical to determining what's going on we can't include "off"
83
+ options.on :username, "-u", :required => true
84
+ options.on :password, "-p", :required => true
85
+ options.on :summary, "-summaryFile", Optout::File
86
+ options.on :mode, "-m", /\w+/, :required => true
87
+ options.on *SHORTNAME
88
+ end
89
+
90
+ def create_transporter_options(optz)
91
+ optz[:mode] = mode
92
+ super
93
+ end
94
+
95
+ def mode
96
+ self.class.to_s.split("::")[-1].gsub(/([a-z])([A-Z])/, "\1_\2").downcase
97
+ end
98
+ end
99
+
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,55 @@
1
+ require "fileutils"
2
+ require "itunes/store/transporter/errors"
3
+ require "itunes/store/transporter/command"
4
+
5
+ module ITunes
6
+ module Store
7
+ class Transporter
8
+ module Command
9
+
10
+ ##
11
+ # Retrieve the metadata for a previously delivered package.
12
+ #
13
+ class Lookup < Mode
14
+ def initialize(*config)
15
+ super
16
+ # These 2 are mutually exclusive, and one is required.
17
+ # Optout has no way to denote this
18
+ options.on *VENDOR_ID
19
+ options.on *APPLE_ID
20
+ options.on *DESTINATION
21
+ end
22
+
23
+ def run(options = {})
24
+ options[:destination] = Dir.mktmpdir
25
+ super
26
+ ensure
27
+ FileUtils.rm_rf(options[:destination])
28
+ end
29
+
30
+ protected
31
+ def handle_success(stdout_lines, stderr_lines, options)
32
+ id = options[:apple_id] || options[:vendor_id]
33
+ path = File.join(options[:destination], "#{id}.itmsp", "metadata.xml")
34
+
35
+ if !File.exists?(path)
36
+ raise ITunes::Store::Transporter::TransporterError, "No metadata file exists at #{path}"
37
+ end
38
+
39
+ begin
40
+ metadata = File.read(path)
41
+ rescue StandardError => e
42
+ raise ITunes::Store::Transporter::TransporterError, "Failed to read metadata file #{path}: #{e}"
43
+ end
44
+
45
+ metadata
46
+ end
47
+
48
+ def mode
49
+ "lookupMetadata"
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,21 @@
1
+ require "optout"
2
+
3
+ module ITunes
4
+ module Store
5
+ class Transporter
6
+ module Command
7
+ module Option
8
+ # Common command options
9
+ VENDOR_ID = [ :vendor_id, "-vendor_id", /\w/ ]
10
+ APPLE_ID = [ :apple_id, "-apple_id", /\w/ ]
11
+ SHORTNAME = [ :shortname, "-s", /\w/ ]
12
+ TRANSPORT = [ :transport, "-t", %w|Aspera Signiant DAV| ]
13
+ SUCCESS = [ :success, "-success", Optout::Dir.exists ]
14
+ FAILURE = [ :failure, "-failure", Optout::Dir.exists ]
15
+ PACKAGE = [ :package, "-f", Optout::Dir.exists.named(/\.itmsp\z/), { :required => true } ]
16
+ DESTINATION = [ :destination, "-destination" ]
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,35 @@
1
+ require "itunes/store/transporter/command"
2
+
3
+ module ITunes
4
+ module Store
5
+ class Transporter
6
+ module Command
7
+
8
+ ##
9
+ # List of Providers for whom your account is authorzed to deliver for.
10
+ #
11
+ class Providers < Mode
12
+ protected
13
+ def mode
14
+ "provider"
15
+ end
16
+
17
+ def handle_success(stdout_lines, stderr_lines, options)
18
+ providers = []
19
+ stdout_lines.each do |line|
20
+ line.chomp!
21
+ if line =~ /\A\d+\s+(.+?)\s+(\w+)\Z/
22
+ provider = {}
23
+ provider[:longname] = $1
24
+ provider[:shortname] = $2
25
+ providers << provider
26
+ end
27
+ end
28
+
29
+ providers
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,28 @@
1
+ require "itunes/store/transporter/command"
2
+
3
+ module ITunes
4
+ module Store
5
+ class Transporter
6
+ module Command
7
+
8
+ ##
9
+ # Download a RelaxNG schema file for a particular metadata specification.
10
+ #
11
+
12
+ class Schema < Mode
13
+ def initialize(*config)
14
+ super
15
+ options.on *DESTINATION
16
+ options.on :type, "-schemaType", /\A(transitional|strict)\z/i, :required => true
17
+ options.on :version, "-schema", /\w+/i, :required => true
18
+ end
19
+
20
+ protected
21
+ def mode
22
+ "generateSchema"
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,34 @@
1
+ require "itunes/store/transporter/command"
2
+
3
+ module ITunes
4
+ module Store
5
+ class Transporter
6
+ module Command # :nodoc:
7
+
8
+ ##
9
+ # Retrieve the status of a previously uploaded package
10
+ #
11
+ class Status < Mode
12
+ def initialize(*config)
13
+ super
14
+ options.on *VENDOR_ID
15
+ end
16
+
17
+ protected
18
+ def handle_success(stdout_lines, stderr_lines, options)
19
+ status = {}
20
+ stdout_lines.each do |line|
21
+ next unless line =~ /\A\s*\w/
22
+ key, value = line.split(/:\s+/, 2).map(&:strip)
23
+ key.gsub!(/\s+/, "_")
24
+ key.downcase!
25
+ status[key.to_sym] = value
26
+ end
27
+ status
28
+ end
29
+ end
30
+
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,27 @@
1
+ require "optout"
2
+ require "itunes/store/transporter/command"
3
+
4
+ module ITunes
5
+ module Store
6
+ class Transporter
7
+ module Command # :nodoc: all
8
+
9
+ ##
10
+ # Upload a package to the iTunes Store
11
+ #
12
+ class Upload < Mode
13
+ def initialize(*config)
14
+ super
15
+ options.on *PACKAGE
16
+ options.on *TRANSPORT
17
+ options.on *SUCCESS
18
+ options.on *FAILURE
19
+ options.on :delete, "-delete", Optout::Boolean
20
+ options.on :rate, "-k", Integer # Required if TRANSPORT is Aspera or Signiant
21
+ options.on :log_history, "-loghistory", Optout::Dir.exists
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,37 @@
1
+ require "optout"
2
+ require "itunes/store/transporter/errors"
3
+ require "itunes/store/transporter/command"
4
+ require "itunes/store/transporter/output_parser"
5
+
6
+ module ITunes
7
+ module Store
8
+ class Transporter
9
+ module Command # :nodoc:
10
+
11
+ ##
12
+ # Validate the contents of a package's metadata and assets.
13
+ #
14
+
15
+ class Verify < Mode
16
+ def initialize(*config)
17
+ super
18
+ options.on *PACKAGE
19
+ options.on :verify_assets, "-disableAssetVerification", Optout::Boolean # If false verify MD only no assets
20
+ end
21
+
22
+ protected
23
+ # Verify mode returns 0 if there are no packages to verify but will emit an error message about the lack of packages
24
+ def handle_success(stdout_lines, stderr_lines, options)
25
+ parser = Transporter::OutputParser.new(stderr_lines)
26
+ if parser.errors.any?
27
+ raise ITunes::Store::Transporter::ExecutionError.new(parser.errors, 0)
28
+ else
29
+ true
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+
@@ -0,0 +1,30 @@
1
+ require "itunes/store/transporter/command"
2
+
3
+ module ITunes
4
+ module Store
5
+ class Transporter
6
+ module Command # :nodoc: all
7
+
8
+ ##
9
+ # Return the +iTMSTransporter+ version.
10
+ #
11
+ class Version < Base
12
+ def initialize(*config)
13
+ super
14
+ options.on :version, "-version"
15
+ end
16
+
17
+ protected
18
+ def create_transporter_options(optz)
19
+ optz[:version] = true
20
+ super
21
+ end
22
+
23
+ def handle_success(stdout_lines, stderr_lines, options)
24
+ super =~ /version\s+(\d+(?:\.\d+)*)\b/i ? $1 : "Unknown"
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,67 @@
1
+
2
+ module ITunes
3
+ module Store
4
+ class Transporter
5
+
6
+ class TransporterError < StandardError; end
7
+ class OptionError < TransporterError; end
8
+
9
+ class ExecutionError < TransporterError
10
+ attr :errors
11
+ attr :exitstatus
12
+
13
+ def initialize(errors, exitstatus = nil)
14
+ @errors = [ errors ].flatten
15
+ @exitstatus = exitstatus
16
+ super @errors.map { |e| e.to_s }.join ", "
17
+ end
18
+ end
19
+
20
+ class TransporterMessage
21
+ attr :code
22
+ attr :message
23
+
24
+ def initialize(message, code = nil)
25
+ @message = message
26
+ @code = code
27
+ end
28
+
29
+ # 1000...2000?
30
+
31
+ def bad_data?
32
+ (3000...4000).include?(code)
33
+ end
34
+
35
+ def invalid_data?
36
+ (4000...5000).include?(code)
37
+ end
38
+
39
+ def missing_data?
40
+ (5000...6000).include?(code)
41
+ end
42
+
43
+ def unsupported_feature?
44
+ (6000...7000).include?(code)
45
+ end
46
+
47
+ def schema_error?
48
+ (8000...9000).include?(code)
49
+ end
50
+
51
+ def asset_error?
52
+ (9000...10_000).include?(code)
53
+ end
54
+
55
+ def validation_error?
56
+ (3000...10_000).include?(code)
57
+ end
58
+
59
+ def to_s
60
+ s = message.dup
61
+ s << " (#{code})" if code
62
+ s
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end