tracksperanto 3.3.0.pre → 3.3.6
Sign up to get free protection for your applications and to get access to all the features.
- data/DEVELOPER_DOCS.rdoc +23 -15
- data/Gemfile +8 -5
- data/History.txt +9 -0
- data/README.rdoc +52 -16
- data/bin/tracksperanto +4 -2
- data/lib/export/base.rb +5 -4
- data/lib/import/flame_stabilizer.rb +2 -0
- data/lib/import/nuke_script.rb +1 -0
- data/lib/import/shake_grammar/lexer.rb +4 -3
- data/lib/pipeline/base.rb +6 -2
- data/lib/tracksperanto.rb +2 -2
- data/test/export/test_flame_stabilizer_cornerpin_export.rb +4 -0
- data/test/helper.rb +26 -18
- data/test/test_cli.rb +53 -44
- data/test/test_pipeline.rb +106 -90
- data/tracksperanto.gemspec +15 -12
- metadata +33 -17
data/DEVELOPER_DOCS.rdoc
CHANGED
@@ -3,31 +3,37 @@
|
|
3
3
|
=== Tests
|
4
4
|
|
5
5
|
Tracksperanto is heavily tested. Please use the Github checkout to also receive some 17+ megabytes of test files that the test suite
|
6
|
-
can chew on.
|
7
|
-
here but we are sharing an essential pipeline tool that has to be robust day in day out, year to year. Mmmkay?
|
8
|
-
|
9
|
-
So please do not underestimate tests.
|
6
|
+
can chew on. Contributions or patches without tests will be rejected at sight.
|
10
7
|
|
11
8
|
=== Development environment
|
12
9
|
|
13
|
-
Tracksperanto is currently being developed on Ruby 1.9.3 but it should also work fine on 1.8.7.
|
14
|
-
|
10
|
+
Tracksperanto is currently being developed on Ruby 1.9.3 but it should also work fine on 1.8.7.
|
11
|
+
What you will need is everything mentioned in the Gemfile plus Bundler.
|
12
|
+
Development should be done agains the git checkout because the gem does not contain the test files
|
13
|
+
(various example files in different formats that are used for verifying all the import and export modules).
|
14
|
+
|
15
|
+
The test corpus on Tracksperanto is HUGE at the moment, and it makes no sense to ship it with the gem.
|
15
16
|
|
17
|
+
So, to get started:
|
18
|
+
|
19
|
+
* Make sure you have Ruby and Bundler (+sudo gem install bundler+ if unsure)
|
16
20
|
* Checkout the repo at http://github.com/guerilla-di/tracksperanto
|
17
|
-
* Run
|
18
|
-
*
|
19
|
-
* File a pull request or send a patch to
|
21
|
+
* Run +bundle install+ and +bundle exec rake+ to run the tests
|
22
|
+
* Do your thing, in a separate branch
|
23
|
+
* File a pull request or send a patch to +me at julik dot nl+
|
20
24
|
|
21
25
|
=== Internal tracker representation
|
22
26
|
|
23
27
|
The trackers are represented by Tracker objects, which work like addressable hashes per frame number. The Tracker objects
|
24
28
|
contain Keyframe objects, and those in turn contain coordinates. The coordinates are stored in absolute pixels, relative to
|
25
|
-
the zero coordinate in the lower left corner.
|
26
|
-
|
29
|
+
the zero coordinate in the lower left corner.
|
30
|
+
|
31
|
+
Note on subpixel precision: the absolute left/bottom of the image has coordinates 0,0
|
32
|
+
(at the lower left corner of the leftmost bottommost pixel) and 0.5x0.5 in the middle of that pixel.
|
27
33
|
|
28
34
|
=== Importing your own formats
|
29
35
|
|
30
|
-
|
36
|
+
To write an import module refer to Tracksperanto::Import::Base
|
31
37
|
docs. Your importer will be configured with width and height of the comp that it is importing, and will get an IO
|
32
38
|
object with the file that you are processing. You should then yield parsed trackers within the each method (tracker objects should
|
33
39
|
be Tracksperanto::Tracker objects or compatibles)
|
@@ -44,7 +50,7 @@ You probably want to write a Tool (consult the Tracksperanto::Tool::Base docs) i
|
|
44
50
|
or their data. A Tool is just like an export module, except that instead it sits between the exporter and the exporting routine. Tools wrap export
|
45
51
|
modules or each other, so you can stack different tool modules together (like "scale first, then move").
|
46
52
|
|
47
|
-
=== Writing your own processing
|
53
|
+
=== Writing your own processing pipelines from start to finish
|
48
54
|
|
49
55
|
You probably want to write a descendant of Tracksperanto::Pipeline::Base. This is a class that manages a conversion from start to finish, including detecting the
|
50
56
|
input format, allocating output files and building a chain of Tools to process the export. If you want to make a GUI for Tracksperanto you will likely need
|
@@ -70,7 +76,7 @@ the software user-friendly. A well-behaved Tracksperanto module should manage it
|
|
70
76
|
# This importer needs to know width and height
|
71
77
|
some_importer.width = 1024
|
72
78
|
some_importer.height = 576
|
73
|
-
some_importer.io = File.open("source_file.
|
79
|
+
some_importer.io = File.open("source_file.shk")
|
74
80
|
|
75
81
|
# The importer responds to each() so if your file is not too big you can just load all the trackers
|
76
82
|
# as an array. If you expect to have alot of trackers investigate a way to buffer them on disk
|
@@ -89,6 +95,8 @@ the software user-friendly. A well-behaved Tracksperanto module should manage it
|
|
89
95
|
|
90
96
|
# Now when we send export commands to the Slipper it will play them through
|
91
97
|
# to the Scaler and the Scaler in turn will send commands to the exporter.
|
98
|
+
# As you can see when you run export commands you do not have to use the Tracker
|
99
|
+
# objects, you just have to stream the right arguments in the right sequence
|
92
100
|
slipper.start_export(1024, 576)
|
93
101
|
trackers.each do | t |
|
94
102
|
slipper.start_tracker_segment(t.name)
|
@@ -99,4 +107,4 @@ the software user-friendly. A well-behaved Tracksperanto module should manage it
|
|
99
107
|
end
|
100
108
|
slipper.end_export
|
101
109
|
|
102
|
-
# And we are done!
|
110
|
+
# And we are done!
|
data/Gemfile
CHANGED
@@ -1,24 +1,27 @@
|
|
1
1
|
# -*- ruby -*-
|
2
2
|
source :rubygems
|
3
3
|
|
4
|
+
gem "bundler"
|
5
|
+
|
4
6
|
gem "obuf", "~> 1.1"
|
5
|
-
gem "tickly", "~> 2.
|
6
|
-
gem "bychar"
|
7
|
+
gem "tickly", "~> 2.1"
|
8
|
+
gem "bychar", "~> 2"
|
7
9
|
gem "progressive_io", "~> 1.0"
|
8
10
|
gem "flame_channel_parser", "~> 4.0"
|
11
|
+
|
9
12
|
gem "progressbar", "0.10.0"
|
10
13
|
gem "update_hints", "~> 1.0"
|
11
14
|
|
12
|
-
|
13
15
|
group :development do
|
14
16
|
gem "approximately"
|
15
17
|
gem "jeweler"
|
16
18
|
gem "rake"
|
19
|
+
gem "linebyline"
|
17
20
|
|
18
21
|
if RUBY_VERSION > "1.8"
|
19
|
-
gem "flexmock", "~> 1.3"
|
22
|
+
gem "flexmock", "~> 1.3", :require => %w( flexmock flexmock/test_unit )
|
20
23
|
else
|
21
|
-
gem "flexmock", "~> 0.8"
|
24
|
+
gem "flexmock", "~> 0.8", :require => %w( flexmock flexmock/test_unit )
|
22
25
|
end
|
23
26
|
|
24
27
|
gem "cli_test", "~>1.0"
|
data/History.txt
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
=== 3.3.6
|
2
|
+
|
3
|
+
* Shake out the latest Bundler integration issues
|
4
|
+
|
5
|
+
=== 3.3.0
|
6
|
+
|
7
|
+
* Require dependencies using Bundler
|
8
|
+
* Update to newer Tickly that has a faster parser
|
9
|
+
|
1
10
|
=== 3.2.2
|
2
11
|
|
3
12
|
* Bump a whole array of dependencies to speed up and simplify Nuke and Shake parsers
|
data/README.rdoc
CHANGED
@@ -9,6 +9,8 @@ Unfortunately, the UIs of these are all different and not very user-friendly. It
|
|
9
9
|
that an app cannot solve a shot that another one will, but you usually have to redo your 2D
|
10
10
|
tracks in each one of them.
|
11
11
|
|
12
|
+
=== Efficiency when doing tracks
|
13
|
+
|
12
14
|
Another problem with today's matchmoving apps is that they are vastly inefficient when
|
13
15
|
doing 2D tracks. Almost all of them use OpenGL and want to load the whole frame into memory
|
14
16
|
at once. When doing tracks of long shots at high resolutions (like 2K and HD), especially
|
@@ -27,31 +29,65 @@ which is not adequate for all of the features being tracked.
|
|
27
29
|
|
28
30
|
So it's very natural to track in a modern compositing app that has selective image
|
29
31
|
loading, and then export one single group of tracks into all of the matchmoving
|
30
|
-
applications at once.
|
31
|
-
|
32
|
+
applications at once.
|
33
|
+
|
34
|
+
=== Evaluating different camera solvers
|
35
|
+
|
36
|
+
Since your 2D tracking data is now freely interchangeable you can load the same tracks
|
37
|
+
into multiple 3D tracking applications and see which one gives you a better solve.
|
38
|
+
Should all the 3D camera trackers fail, you can still take your tracks into the 2D
|
39
|
+
compositing world to do the job.
|
40
|
+
|
41
|
+
=== Processing 2D tracking data
|
42
|
+
|
43
|
+
Sometimes you need to offset your tracks in time, or resize them to a different pixel format.
|
44
|
+
Very few apps allow you to convert your tracks in one step from format to format - like doing
|
45
|
+
an unproportional scale on the tracks, or moving them a few pixels left and right. This comes
|
46
|
+
at a high cost if the footage you are tracking came cropped or in a wrong aspect - the only
|
47
|
+
way to solve the shot will be to retrack it from scratch.
|
48
|
+
|
49
|
+
To circumvent this, Tracksperanto allows you to apply transformations to the tracking data
|
50
|
+
that you export - and you can apply multiple transformations if desired.
|
51
|
+
|
52
|
+
== Using Tracksperanto from the command line
|
32
53
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
by applying simple transformations to the tracks.
|
54
|
+
To run on your own computer, make sure you have Ruby installed. Versions from 1.8.7
|
55
|
+
and up are supported.
|
56
|
+
|
57
|
+
$ ruby -v
|
58
|
+
ruby 1.9.3p286 (2012-10-12 revision 37165) [x86_64-darwin12.2.0]
|
39
59
|
|
40
|
-
|
60
|
+
Then install tracksperanto. It will be downloaded and unpacked automatically for you by the
|
61
|
+
RubyGems system:
|
41
62
|
|
42
|
-
|
63
|
+
$ sudo gem install tracksperanto
|
43
64
|
|
44
|
-
tracksperanto
|
65
|
+
Then you will have a "tracksperanto" binary in your $PATH, which you can use like this:
|
45
66
|
|
46
|
-
-w
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
67
|
+
$ tracksperanto -w 1920 -h 1080 /Films/Blockbuster/Shots/001/script.shk
|
68
|
+
|
69
|
+
To see the supported options, run
|
70
|
+
|
71
|
+
$ tracksperanto --help | more
|
51
72
|
|
52
73
|
The converted files will be saved in the same directory as the source, if resulting
|
53
74
|
converted files already exist <b>they will be overwritten without warning</b>.
|
54
75
|
|
76
|
+
== Using Tracksperanto through the web
|
77
|
+
|
78
|
+
For situations where you cannot install anything on your machine, or you run a shitty OS that cannot
|
79
|
+
run Ruby decently, or you are in a locked-down environment, we offer a web-enabled version of
|
80
|
+
Tracksperanto at the following URL:
|
81
|
+
|
82
|
+
http://tracksperanto.guerilla-di.org/
|
83
|
+
|
84
|
+
This is a web-app which is always in lock-step with the main Tracksperanto in terms of versions,
|
85
|
+
features and bug fixes. As a matter of principle, we reserve the right to use anything you upload
|
86
|
+
to the web version for fixing bugs in Tracksperanto. Note that we usually scrub all the studio-specific
|
87
|
+
data (like script and footage paths) from the files before adding them to the repo.
|
88
|
+
|
89
|
+
If you want your own copy of the web application at your facility we can discuss that, but it's not free.
|
90
|
+
|
55
91
|
== Format support
|
56
92
|
|
57
93
|
---
|
data/bin/tracksperanto
CHANGED
@@ -10,11 +10,11 @@
|
|
10
10
|
# == Author
|
11
11
|
# Julik <me@julik.nl>
|
12
12
|
|
13
|
+
# Require the xperanto lib, which in turn requires Bundler and pulls in all the gems
|
13
14
|
require File.dirname(__FILE__) + '/../lib/tracksperanto' unless defined?(Tracksperanto)
|
15
|
+
require 'update_hints'
|
14
16
|
require 'optparse'
|
15
|
-
require 'rubygems'
|
16
17
|
require 'progressbar'
|
17
|
-
require "update_hints"
|
18
18
|
|
19
19
|
def disclaimer
|
20
20
|
"Please consider a small donation to keep Tracksperanto going: http://guerilla-di.org/source-and-license/\n"+
|
@@ -100,6 +100,8 @@ op.on(" -crop", "--crop CROP_VALUES_COMMA_SEPARATED", String, toold("Crop")) do
|
|
100
100
|
end
|
101
101
|
|
102
102
|
op.on(" -ys", "--yscale Y_SCALING_FACTOR", Float, toold("Scaler"), &tool("Scaler", :y_factor))
|
103
|
+
op.on(" -xs", "--xscale X_SCALING_FACTOR", Float, toold("Scaler"), &tool("Scaler", :x_factor))
|
104
|
+
|
103
105
|
op.on(" -t", "--trim", Float, toold("StartTrim"), &tool("StartTrim")) # Before slip!
|
104
106
|
op.on(" -s", "--slip FRAMES", Integer, toold("Slipper"), &tool("Slipper", :slip))
|
105
107
|
op.on(" -g", "--golden", toold("Golden"), &tool("Golden"))
|
data/lib/export/base.rb
CHANGED
@@ -64,13 +64,14 @@ class Tracksperanto::Export::Base
|
|
64
64
|
# Called on tracker start, once for each tracker. Receives the name of the tracker.
|
65
65
|
def start_tracker_segment(tracker_name)
|
66
66
|
end
|
67
|
+
|
68
|
+
# Called for each tracker keyframe, with the Tracksperanto internal coordinates and frame numbers.
|
69
|
+
# The calls come after start_tracker_segment and before end_tracker_segment
|
70
|
+
def export_point(at_frame_i, abs_float_x, abs_float_y, float_residual)
|
71
|
+
end
|
67
72
|
|
68
73
|
# Called on tracker end, once for each tracker
|
69
74
|
def end_tracker_segment
|
70
75
|
end
|
71
76
|
|
72
|
-
# Called for each tracker keyframe, with the Tracksperanto internal coordinates and frame numbers.
|
73
|
-
# The calls come after start_tracker_segment and before end_tracker_segment
|
74
|
-
def export_point(at_frame_i, abs_float_x, abs_float_y, float_residual)
|
75
|
-
end
|
76
77
|
end
|
data/lib/import/nuke_script.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
|
+
|
2
3
|
require 'bychar'
|
3
4
|
|
4
5
|
module Tracksperanto::ShakeGrammar
|
@@ -27,13 +28,13 @@ module Tracksperanto::ShakeGrammar
|
|
27
28
|
# that will cache in chunks, and then read from there byte by byte. This yields a substantial speedup (4.9 seconds for the test
|
28
29
|
# as opposed to 7.9 without this). We do check for the proper class only once so that when we use nested lexers
|
29
30
|
# we only wrap the passed IO once, and only if necessary.
|
30
|
-
with_io = Bychar
|
31
|
+
with_io = Bychar.wrap(with_io) unless with_io.respond_to?(:read_one_char!)
|
31
32
|
@io, @stack, @buf, @sentinel, @limit_to_one_stmt, @stack_depth = with_io, [], '', sentinel, limit_to_one_stmt, stack_depth
|
32
33
|
|
33
34
|
catch(STOP_TOKEN) do
|
34
35
|
begin
|
35
36
|
loop { parse }
|
36
|
-
rescue Bychar::
|
37
|
+
rescue Bychar::EOF
|
37
38
|
end
|
38
39
|
end
|
39
40
|
|
@@ -53,7 +54,7 @@ module Tracksperanto::ShakeGrammar
|
|
53
54
|
|
54
55
|
def parse
|
55
56
|
|
56
|
-
c = @io.
|
57
|
+
c = @io.read_one_char!
|
57
58
|
|
58
59
|
if @buf.length > MAX_BUFFER_SIZE # Wrong format and the buffer is filled up, bail
|
59
60
|
raise WrongInputError, "Atom buffer overflow at #{MAX_BUFFER_SIZE} bytes, this is definitely not a Shake script"
|
data/lib/pipeline/base.rb
CHANGED
@@ -1,4 +1,8 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
|
+
|
3
|
+
require 'progressive_io'
|
4
|
+
require 'obuf'
|
5
|
+
|
2
6
|
module Tracksperanto::Pipeline
|
3
7
|
|
4
8
|
class EmptySourceFileError < RuntimeError
|
@@ -213,9 +217,9 @@ module Tracksperanto::Pipeline
|
|
213
217
|
# Setup output files and return a single output
|
214
218
|
# that replays to all of them
|
215
219
|
def setup_outputs_for(input_file_path)
|
216
|
-
|
220
|
+
file_name_without_extension = File.basename(input_file_path, '.*')
|
217
221
|
outputs = (exporters || Tracksperanto.exporters).map do | exporter_class |
|
218
|
-
export_name = [
|
222
|
+
export_name = [file_name_without_extension, exporter_class.desc_and_extension].join("_")
|
219
223
|
export_path = File.join(File.dirname(input_file_path), export_name)
|
220
224
|
exporter_class.new(open_owned_export_file(export_path))
|
221
225
|
end
|
data/lib/tracksperanto.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
|
-
%w( stringio delegate tempfile
|
2
|
+
%w( stringio delegate tempfile ).map(&method(:require))
|
3
3
|
|
4
4
|
module Tracksperanto
|
5
5
|
PATH = File.expand_path(File.dirname(__FILE__))
|
6
|
-
VERSION = '3.
|
6
|
+
VERSION = '3.3.6'
|
7
7
|
|
8
8
|
module Import; end
|
9
9
|
module Export; end
|
@@ -47,6 +47,8 @@ class FlameStabilizerCornerpinExportTest < Test::Unit::TestCase
|
|
47
47
|
x = Tracksperanto::Export::FlameStabilizerCornerpin.new(s)
|
48
48
|
x.just_export(trackers, 1920, 1080)
|
49
49
|
|
50
|
+
s.rewind
|
51
|
+
|
50
52
|
assert_same_buffer(File.open(P2), s)
|
51
53
|
end
|
52
54
|
|
@@ -63,6 +65,8 @@ class FlameStabilizerCornerpinExportTest < Test::Unit::TestCase
|
|
63
65
|
x = Tracksperanto::Export::FlameStabilizerCornerpin.new(s)
|
64
66
|
x.just_export(trackers, 1920, 1080)
|
65
67
|
|
68
|
+
s.rewind
|
69
|
+
|
66
70
|
assert_same_buffer(File.open(P3), s)
|
67
71
|
end
|
68
72
|
end
|
data/test/helper.rb
CHANGED
@@ -2,17 +2,18 @@
|
|
2
2
|
require "rubygems"
|
3
3
|
require File.dirname(__FILE__) + '/../lib/tracksperanto' unless defined?(Tracksperanto)
|
4
4
|
require 'test/unit'
|
5
|
-
require 'flexmock'
|
6
|
-
require 'flexmock/test_unit'
|
7
|
-
require 'approximately'
|
8
5
|
require 'fileutils'
|
9
6
|
|
7
|
+
require 'bundler'
|
8
|
+
Bundler.require :development
|
9
|
+
|
10
10
|
unless File.exist?(File.dirname(__FILE__) + "/import/samples")
|
11
11
|
puts "Please run tests on a git checkout from http://github.com/guerilla-di/tracksperanto"
|
12
12
|
puts "so that you also have the 17-something megs of the test corpus to test against. Aborting."
|
13
13
|
exit 1
|
14
14
|
end
|
15
15
|
|
16
|
+
# We are limited to flexmock 0.8 on Ruby 1.8
|
16
17
|
# http://redmine.ruby-lang.org/issues/4882
|
17
18
|
# https://github.com/jimweirich/flexmock/issues/4
|
18
19
|
# https://github.com/julik/flexmock/commit/4acea00677e7b558bd564ec7c7630f0b27d368ca
|
@@ -22,6 +23,22 @@ class FlexMock::PartialMockProxy
|
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
26
|
+
class Test::Unit::TestCase
|
27
|
+
# Runs the block with a temporary directory. The directory will be removed
|
28
|
+
# when the block completes. The path to the directory will be yielded to the block
|
29
|
+
def in_temp_dir
|
30
|
+
old_dir = Dir.pwd
|
31
|
+
begin
|
32
|
+
Dir.mktmpdir do | where |
|
33
|
+
Dir.chdir(where)
|
34
|
+
yield(where)
|
35
|
+
end
|
36
|
+
ensure
|
37
|
+
Dir.chdir(old_dir)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
25
42
|
# This module creates ideal parabolic tracks for testing exporters. The two trackers
|
26
43
|
# will start at opposite corners of the image and traverse two parabolic curves, touching
|
27
44
|
# the bounds of the image at the and and in the middle. On the middle frame they will vertically
|
@@ -94,21 +111,9 @@ module ParabolicTracks
|
|
94
111
|
flunk "The test output was overwritten, so this test is meaningless"
|
95
112
|
end
|
96
113
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
# There are subtle differences in how IO is handled on dfferent platforms (Darwin)
|
101
|
-
lineno = 0
|
102
|
-
begin
|
103
|
-
loop do
|
104
|
-
return if ref_buffer.eof? && actual_buffer.eof?
|
105
|
-
lineno += 1
|
106
|
-
ref_line, actual_line = ref_buffer.readline, actual_buffer.readline
|
107
|
-
assert_equal ref_line, actual_line, "Mismatch on line #{lineno}:"
|
108
|
-
end
|
109
|
-
rescue EOFError
|
110
|
-
flunk "One of the buffers was too short at #{lineno}"
|
111
|
-
end
|
114
|
+
# for assert_same_buffer
|
115
|
+
def self.included(into)
|
116
|
+
into.send(:include, LineByLine::Assertions)
|
112
117
|
end
|
113
118
|
|
114
119
|
def ensure_same_output(exporter_klass, reference_path, message = "The line should be identical")
|
@@ -118,6 +123,7 @@ module ParabolicTracks
|
|
118
123
|
create_reference_output(exporter_klass, reference_path) do | x |
|
119
124
|
yield(x) if block_given?
|
120
125
|
end
|
126
|
+
flunk
|
121
127
|
return
|
122
128
|
end
|
123
129
|
|
@@ -126,6 +132,8 @@ module ParabolicTracks
|
|
126
132
|
yield(x) if block_given?
|
127
133
|
export_parabolics_with(x)
|
128
134
|
|
135
|
+
io.rewind
|
136
|
+
|
129
137
|
assert_same_buffer(File.open(reference_path, "r"), io, message)
|
130
138
|
end
|
131
139
|
|
data/test/test_cli.rb
CHANGED
@@ -4,16 +4,15 @@ require "set"
|
|
4
4
|
require "cli_test"
|
5
5
|
|
6
6
|
class TestCli < Test::Unit::TestCase
|
7
|
-
TEMP_DIR = File.expand_path(File.dirname(__FILE__) + "/tmp")
|
8
7
|
BIN_P = File.expand_path(File.dirname(__FILE__) + "/../bin/tracksperanto")
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
9
|
+
# Wraps in_temp_dir but sneaks a prefab file into it
|
10
|
+
def with_stabilizer_in_temp_dir
|
11
|
+
test_f = File.expand_path(File.dirname(__FILE__)) + "/import/samples/flame_stabilizer/fromCombustion_fromMidClip_wSnap.stabilizer"
|
12
|
+
in_temp_dir do | where |
|
13
|
+
FileUtils.cp(test_f, where + "/flm.stabilizer")
|
14
|
+
yield(where)
|
15
|
+
end
|
17
16
|
end
|
18
17
|
|
19
18
|
# Run the tracksperanto binary with passed options, and return [exit_code, stdout_content, stderr_content]
|
@@ -28,43 +27,52 @@ class TestCli < Test::Unit::TestCase
|
|
28
27
|
end
|
29
28
|
|
30
29
|
def test_cli_with_nonexisting_file
|
31
|
-
|
32
|
-
|
33
|
-
|
30
|
+
with_stabilizer_in_temp_dir do
|
31
|
+
status, o, e = cli("nonexisting.file")
|
32
|
+
assert_equal 1, status
|
33
|
+
assert_match /file does not exist/, e
|
34
|
+
end
|
34
35
|
end
|
35
36
|
|
36
37
|
def test_basic_cli
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
38
|
+
with_stabilizer_in_temp_dir do | d |
|
39
|
+
status, o, e = cli("flm.stabilizer")
|
40
|
+
assert_equal 0, status, "Should exit with a normal status (error was #{e})"
|
41
|
+
fs = %w(. ..
|
42
|
+
flm.stabilizer flm_3de_v3.txt flm_3de_v4.txt flm_boujou_text.txt flm_flame.stabilizer
|
43
|
+
flm_matchmover.rz2 flm_mayalive.txt flm_nuke.nk flm_pftrack_2011_pfmatchit.txt flm_pftrack_v4.2dt
|
44
|
+
flm_pftrack_v5.2dt flm_shake_trackers.txt flm_syntheyes_2dt.txt flm_flame_cornerpin.stabilizer
|
45
|
+
flm_tracksperanto_ruby.rb flm_mayaLocators.ma flm_createNulls.jsx flm_xsi_nulls.py flm_nuke_cam_trk_autotracks.txt flm_3dsmax_nulls.ms
|
46
|
+
)
|
47
|
+
assert_match /Found and converted 1 trackers with 232 keyframes\./, o, "Should have output coversion statistics"
|
48
|
+
assert_same_set fs, Dir.entries(d)
|
49
|
+
end
|
47
50
|
end
|
48
51
|
|
49
52
|
def test_cli_with_nonexisting_only_exporter_prints_proper_error_message
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
53
|
+
with_stabilizer_in_temp_dir do
|
54
|
+
status, o, e = cli("--only microsoftfuckingword flm.stabilizer")
|
55
|
+
assert_not_equal 0, status, "Should exit with abnormal state"
|
56
|
+
assert e.include?("Unknown exporter \"microsoftfuckingword\"")
|
57
|
+
assert e.include?("The following export modules are available")
|
58
|
+
end
|
54
59
|
end
|
55
60
|
|
56
61
|
def test_cli_with_nonexisting_importer_prints_proper_error_message
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
62
|
+
with_stabilizer_in_temp_dir do
|
63
|
+
status, o, e = cli("--from microsoftfuckingword flm.stabilizer")
|
64
|
+
assert_not_equal 0, status, "Should exit with abnormal state"
|
65
|
+
assert e.include?("Unknown importer \"microsoftfuckingword\"")
|
66
|
+
assert e.include?("The following import modules are available")
|
67
|
+
end
|
61
68
|
end
|
62
69
|
|
63
70
|
def test_cli_with_only_option
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
71
|
+
with_stabilizer_in_temp_dir do | d |
|
72
|
+
cli("#{BIN_P} --only syntheyes flm.stabilizer")
|
73
|
+
fs = %w(. .. flm.stabilizer flm_syntheyes_2dt.txt )
|
74
|
+
assert_same_set fs, Dir.entries(d)
|
75
|
+
end
|
68
76
|
end
|
69
77
|
|
70
78
|
# TODO: This currently hangs in testing
|
@@ -74,20 +82,21 @@ class TestCli < Test::Unit::TestCase
|
|
74
82
|
# end
|
75
83
|
|
76
84
|
def test_cli_reformat
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
85
|
+
with_stabilizer_in_temp_dir do | d |
|
86
|
+
cli("--reformat-x 1204 --reformat-y 340 --only flamestabilizer flm.stabilizer")
|
87
|
+
p = Tracksperanto::Import::FlameStabilizer.new(:io => File.open(d + "/flm_flame.stabilizer"))
|
88
|
+
items = p.to_a
|
89
|
+
assert_equal 1204, p.width, "The width of the converted setup should be that"
|
90
|
+
assert_equal 340, p.height, "The height of the converted setup should be that"
|
91
|
+
end
|
84
92
|
end
|
85
93
|
|
86
94
|
def test_cli_trim
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
95
|
+
with_stabilizer_in_temp_dir do | d |
|
96
|
+
results = cli("--slip -8000 --trim --only flamestabilizer flm.stabilizer")
|
97
|
+
assert_not_equal 0, results[0] # status
|
98
|
+
assert_match /There were no trackers exported/, results[-1] # STDERR
|
99
|
+
end
|
91
100
|
end
|
92
101
|
|
93
102
|
# We use this instead of assert_equals for arrays of file names since different filesystems
|
data/test/test_pipeline.rb
CHANGED
@@ -3,14 +3,8 @@ require File.expand_path(File.dirname(__FILE__)) + '/helper'
|
|
3
3
|
|
4
4
|
class TestPipeline < Test::Unit::TestCase
|
5
5
|
|
6
|
-
def setup
|
7
|
-
@old_dir = Dir.pwd
|
8
|
-
Dir.chdir(File.dirname(__FILE__))
|
9
|
-
super
|
10
|
-
end
|
11
|
-
|
12
6
|
def create_stabilizer_file
|
13
|
-
@stabilizer = "
|
7
|
+
@stabilizer = "input.stabilizer"
|
14
8
|
trackers = %w( Foo Bar Baz).map do | name |
|
15
9
|
t = Tracksperanto::Tracker.new(:name => name)
|
16
10
|
t.keyframe!(:frame => 3, :abs_x => 100, :abs_y => 200)
|
@@ -25,144 +19,166 @@ class TestPipeline < Test::Unit::TestCase
|
|
25
19
|
end
|
26
20
|
end
|
27
21
|
|
28
|
-
def teardown
|
29
|
-
Dir.glob("./input*.*").each(&File.method(:unlink))
|
30
|
-
Dir.chdir(@old_dir)
|
31
|
-
super
|
32
|
-
end
|
33
|
-
|
34
22
|
def test_supports_block_init
|
35
23
|
pipeline = Tracksperanto::Pipeline::Base.new(:tool_tuples => [:a, :b])
|
36
24
|
assert_equal [:a, :b], pipeline.tool_tuples
|
37
25
|
end
|
38
26
|
|
39
27
|
def test_run_with_autodetected_importer_and_size_without_progress_block
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
28
|
+
in_temp_dir do
|
29
|
+
create_stabilizer_file
|
30
|
+
pipeline = Tracksperanto::Pipeline::Base.new
|
31
|
+
assert_nothing_raised { pipeline.run(@stabilizer) }
|
32
|
+
assert_equal 3, pipeline.converted_points
|
33
|
+
assert_equal 9, pipeline.converted_keyframes, "Should report conversion of 9 keyframes"
|
34
|
+
end
|
45
35
|
end
|
46
36
|
|
47
37
|
def test_run_with_error_picks_up_known_snags_from_importer
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
38
|
+
in_temp_dir do
|
39
|
+
create_stabilizer_file
|
40
|
+
pipeline = Tracksperanto::Pipeline::Base.new
|
41
|
+
flexmock(Tracksperanto::Import::ShakeScript).should_receive(:known_snags).times(1)
|
42
|
+
assert_raise(Tracksperanto::Pipeline::NoTrackersRecoveredError) do
|
43
|
+
pipeline.run(@stabilizer, :importer => "ShakeScript", :width => 2910, :height => 1080)
|
44
|
+
end
|
53
45
|
end
|
54
46
|
end
|
55
47
|
|
56
48
|
def test_run_with_autodetected_importer_and_size_with_progress_block
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
49
|
+
in_temp_dir do
|
50
|
+
create_stabilizer_file
|
51
|
+
processing_log = ""
|
52
|
+
accum = lambda do | percent, message |
|
53
|
+
processing_log << ("%d -> %s\n" % [percent, message])
|
54
|
+
end
|
62
55
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
56
|
+
pipeline = Tracksperanto::Pipeline::Base.new(:progress_block => accum)
|
57
|
+
assert_nothing_raised { pipeline.run(@stabilizer) }
|
58
|
+
assert processing_log.include?("Parsing the file")
|
59
|
+
assert processing_log.include?("Parsing channel \"tracker1/ref/y\"")
|
60
|
+
end
|
67
61
|
end
|
68
62
|
|
69
63
|
def test_run_returns_the_number_of_trackers_and_keyframes_processed
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
64
|
+
in_temp_dir do
|
65
|
+
create_stabilizer_file
|
66
|
+
pipeline = Tracksperanto::Pipeline::Base.new
|
67
|
+
result = pipeline.run(@stabilizer)
|
68
|
+
assert_equal [3, 9], result
|
69
|
+
end
|
74
70
|
end
|
75
71
|
|
76
72
|
def test_run_crashes_with_empty_file
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
73
|
+
in_temp_dir do
|
74
|
+
empty_file_path = "input_empty.stabilizer"
|
75
|
+
f = File.open(empty_file_path, "w"){|f| f.write('') }
|
76
|
+
pipeline = Tracksperanto::Pipeline::Base.new
|
77
|
+
assert_raise(Tracksperanto::Pipeline::EmptySourceFileError) { pipeline.run(empty_file_path) }
|
78
|
+
end
|
81
79
|
end
|
82
80
|
|
83
81
|
def test_run_crashes_with_no_trackers
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
82
|
+
in_temp_dir do
|
83
|
+
empty_file_path = "input_empty.stabilizer"
|
84
|
+
f = File.open(empty_file_path, "w"){|f| f.write('xx') }
|
85
|
+
pipeline = Tracksperanto::Pipeline::Base.new
|
86
|
+
assert_raise(Tracksperanto::Pipeline::NoTrackersRecoveredError) { pipeline.run(empty_file_path) }
|
87
|
+
end
|
88
88
|
end
|
89
89
|
|
90
90
|
def test_tool_initialization_from_tuples
|
91
|
-
|
91
|
+
in_temp_dir do
|
92
|
+
create_stabilizer_file
|
92
93
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
94
|
+
pipeline = Tracksperanto::Pipeline::Base.new
|
95
|
+
pipeline.tool_tuples = [
|
96
|
+
["Bla", {:foo=> 234}]
|
97
|
+
]
|
97
98
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
99
|
+
mock_mux = flexmock("MUX")
|
100
|
+
mock_lint = flexmock("LINT")
|
101
|
+
flexmock(Tracksperanto::Export::Mux).should_receive(:new).and_return(mock_mux)
|
102
|
+
flexmock(Tracksperanto::Tool::Lint).should_receive(:new).with(mock_mux).and_return(mock_lint)
|
102
103
|
|
103
|
-
|
104
|
-
|
104
|
+
m = flexmock("tool object")
|
105
|
+
mock_tool_class = flexmock("tool class")
|
105
106
|
|
106
|
-
|
107
|
-
|
107
|
+
flexmock(Tracksperanto).should_receive(:get_tool).with("Bla").once.and_return(mock_tool_class)
|
108
|
+
mock_tool_class.should_receive(:new).with(mock_lint, {:foo => 234}).once
|
108
109
|
|
109
|
-
|
110
|
+
assert_raise(NoMethodError) { pipeline.run(@stabilizer) }
|
111
|
+
end
|
110
112
|
end
|
111
113
|
|
112
114
|
def test_run_with_autodetected_importer_that_requires_size
|
113
|
-
|
114
|
-
|
115
|
-
|
115
|
+
in_temp_dir do
|
116
|
+
FileUtils.cp( File.dirname(__FILE__) + "/import/samples/shake_script/four_tracks_in_one_stabilizer.shk", "input.shk")
|
117
|
+
pipeline = Tracksperanto::Pipeline::Base.new
|
118
|
+
assert_raise(Tracksperanto::Pipeline::DimensionsRequiredError) { pipeline.run("input.shk") }
|
119
|
+
end
|
116
120
|
end
|
117
121
|
|
118
122
|
def test_run_with_autodetected_importer_that_requires_size_when_size_supplied
|
119
|
-
|
120
|
-
|
121
|
-
|
123
|
+
in_temp_dir do
|
124
|
+
FileUtils.cp( File.dirname(__FILE__) + "/import/samples/shake_script/four_tracks_in_one_stabilizer.shk", "input.shk")
|
125
|
+
pipeline = Tracksperanto::Pipeline::Base.new
|
126
|
+
assert_nothing_raised { pipeline.run("input.shk", :width => 720, :height => 576) }
|
127
|
+
end
|
122
128
|
end
|
123
129
|
|
124
130
|
def test_run_with_overridden_importer_and_no_size
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
131
|
+
in_temp_dir do
|
132
|
+
FileUtils.cp( File.dirname(__FILE__) + "/import/samples/shake_script/four_tracks_in_one_stabilizer.shk", "input.shk")
|
133
|
+
pipeline = Tracksperanto::Pipeline::Base.new
|
134
|
+
num_exporters = Tracksperanto.exporters.length
|
135
|
+
assert_nothing_raised { pipeline.run("input.shk", :importer => "ShakeScript", :width => 720, :height => 576) }
|
136
|
+
assert_equal num_exporters, Dir.glob("input_*").length, "#{num_exporters} files should be present for the input and outputs"
|
137
|
+
end
|
130
138
|
end
|
131
139
|
|
132
140
|
def test_run_with_overridden_importer_and_size_for_file_that_would_be_recognized_differently
|
133
|
-
|
134
|
-
|
135
|
-
|
141
|
+
in_temp_dir do
|
142
|
+
FileUtils.cp( File.dirname(__FILE__) + "/import/samples/shake_script/four_tracks_in_one_stabilizer.shk", "input.stabilizer")
|
143
|
+
pipeline = Tracksperanto::Pipeline::Base.new
|
144
|
+
assert_nothing_raised { pipeline.run("input.stabilizer", :importer => "ShakeScript", :width => 720, :height => 576) }
|
145
|
+
end
|
136
146
|
end
|
137
147
|
|
138
148
|
def test_run_with_unknown_format_raises
|
139
|
-
|
149
|
+
in_temp_dir do
|
150
|
+
File.open("input.txt", "w"){|f| f.write("foo") }
|
140
151
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
152
|
+
pipeline = Tracksperanto::Pipeline::Base.new
|
153
|
+
assert_raise(Tracksperanto::Pipeline::UnknownFormatError) { pipeline.run("input.txt") }
|
154
|
+
assert_raise(Tracksperanto::Pipeline::UnknownFormatError) { pipeline.run("input.txt", :width => 100, :height => 100) }
|
155
|
+
assert_raise(Tracksperanto::Pipeline::DimensionsRequiredError) { pipeline.run("input.txt", :importer => "Syntheyes") }
|
156
|
+
end
|
145
157
|
end
|
146
158
|
|
147
159
|
def test_importing_file_with_trackers_of_zero_length_does_not_accumulate_any_trackers
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
160
|
+
in_temp_dir do
|
161
|
+
pft_with_empty_trackers = File.dirname(__FILE__) + "/import/samples/pftrack5/empty_trackers.2dt"
|
162
|
+
i = Tracksperanto::Import::PFTrack.new(:io => File.open(pft_with_empty_trackers), :width => 1920, :height => 1080)
|
163
|
+
tks = i.to_a
|
164
|
+
assert_equal 3, tks.length
|
165
|
+
assert_equal 0, tks[0].length, "The tracker should have 0 keyframes for this test to make sense"
|
153
166
|
|
154
|
-
|
167
|
+
FileUtils.cp(pft_with_empty_trackers, "input_empty.2dt")
|
155
168
|
|
156
|
-
|
157
|
-
|
158
|
-
|
169
|
+
pipeline = Tracksperanto::Pipeline::Base.new
|
170
|
+
num_t, num_k = pipeline.run("input_empty.2dt", :width => 1920, :height => 1080)
|
171
|
+
assert_equal 1, num_t, "Only one tracker should have been sent through the export"
|
172
|
+
end
|
159
173
|
end
|
160
174
|
|
161
175
|
def test_run_with_overridden_importer_and_size
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
176
|
+
in_temp_dir do
|
177
|
+
FileUtils.cp( File.dirname(__FILE__) + "/import/samples/3de_v4/3de_export_cube.txt", "input.txt")
|
178
|
+
pipeline = Tracksperanto::Pipeline::Base.new
|
179
|
+
assert_raise(Tracksperanto::Pipeline::DimensionsRequiredError) { pipeline.run("input.txt", :importer => "Equalizer4") }
|
180
|
+
assert_nothing_raised { pipeline.run("input.txt", :importer => "Equalizer4", :width => 720, :height => 576) }
|
181
|
+
end
|
166
182
|
end
|
167
183
|
|
168
184
|
end
|
data/tracksperanto.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "tracksperanto"
|
8
|
-
s.version = "3.3.
|
8
|
+
s.version = "3.3.6"
|
9
9
|
|
10
|
-
s.required_rubygems_version = Gem::Requirement.new("
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Julik Tarkhanov"]
|
12
|
-
s.date = "2013-
|
12
|
+
s.date = "2013-04-04"
|
13
13
|
s.description = "Converts 2D track exports between different apps like Flame, MatchMover, PFTrack..."
|
14
14
|
s.email = "me@julik.nl"
|
15
15
|
s.executables = ["tracksperanto"]
|
@@ -209,50 +209,53 @@ Gem::Specification.new do |s|
|
|
209
209
|
s.specification_version = 3
|
210
210
|
|
211
211
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
212
|
+
s.add_runtime_dependency(%q<bundler>, [">= 0"])
|
212
213
|
s.add_runtime_dependency(%q<obuf>, ["~> 1.1"])
|
213
|
-
s.add_runtime_dependency(%q<tickly>, ["~> 2.
|
214
|
-
s.add_runtime_dependency(%q<bychar>, ["
|
214
|
+
s.add_runtime_dependency(%q<tickly>, ["~> 2.1"])
|
215
|
+
s.add_runtime_dependency(%q<bychar>, ["~> 2"])
|
215
216
|
s.add_runtime_dependency(%q<progressive_io>, ["~> 1.0"])
|
216
217
|
s.add_runtime_dependency(%q<flame_channel_parser>, ["~> 4.0"])
|
217
218
|
s.add_runtime_dependency(%q<progressbar>, ["= 0.10.0"])
|
218
219
|
s.add_runtime_dependency(%q<update_hints>, ["~> 1.0"])
|
219
|
-
s.add_runtime_dependency(%q<bundler>, [">= 0"])
|
220
220
|
s.add_development_dependency(%q<approximately>, [">= 0"])
|
221
221
|
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
222
222
|
s.add_development_dependency(%q<rake>, [">= 0"])
|
223
|
+
s.add_development_dependency(%q<linebyline>, [">= 0"])
|
223
224
|
s.add_development_dependency(%q<flexmock>, ["~> 1.3"])
|
224
225
|
s.add_development_dependency(%q<cli_test>, ["~> 1.0"])
|
225
226
|
s.add_development_dependency(%q<rake-hooks>, [">= 0"])
|
226
227
|
s.add_development_dependency(%q<ruby-prof>, [">= 0"])
|
227
228
|
else
|
229
|
+
s.add_dependency(%q<bundler>, [">= 0"])
|
228
230
|
s.add_dependency(%q<obuf>, ["~> 1.1"])
|
229
|
-
s.add_dependency(%q<tickly>, ["~> 2.
|
230
|
-
s.add_dependency(%q<bychar>, ["
|
231
|
+
s.add_dependency(%q<tickly>, ["~> 2.1"])
|
232
|
+
s.add_dependency(%q<bychar>, ["~> 2"])
|
231
233
|
s.add_dependency(%q<progressive_io>, ["~> 1.0"])
|
232
234
|
s.add_dependency(%q<flame_channel_parser>, ["~> 4.0"])
|
233
235
|
s.add_dependency(%q<progressbar>, ["= 0.10.0"])
|
234
236
|
s.add_dependency(%q<update_hints>, ["~> 1.0"])
|
235
|
-
s.add_dependency(%q<bundler>, [">= 0"])
|
236
237
|
s.add_dependency(%q<approximately>, [">= 0"])
|
237
238
|
s.add_dependency(%q<jeweler>, [">= 0"])
|
238
239
|
s.add_dependency(%q<rake>, [">= 0"])
|
240
|
+
s.add_dependency(%q<linebyline>, [">= 0"])
|
239
241
|
s.add_dependency(%q<flexmock>, ["~> 1.3"])
|
240
242
|
s.add_dependency(%q<cli_test>, ["~> 1.0"])
|
241
243
|
s.add_dependency(%q<rake-hooks>, [">= 0"])
|
242
244
|
s.add_dependency(%q<ruby-prof>, [">= 0"])
|
243
245
|
end
|
244
246
|
else
|
247
|
+
s.add_dependency(%q<bundler>, [">= 0"])
|
245
248
|
s.add_dependency(%q<obuf>, ["~> 1.1"])
|
246
|
-
s.add_dependency(%q<tickly>, ["~> 2.
|
247
|
-
s.add_dependency(%q<bychar>, ["
|
249
|
+
s.add_dependency(%q<tickly>, ["~> 2.1"])
|
250
|
+
s.add_dependency(%q<bychar>, ["~> 2"])
|
248
251
|
s.add_dependency(%q<progressive_io>, ["~> 1.0"])
|
249
252
|
s.add_dependency(%q<flame_channel_parser>, ["~> 4.0"])
|
250
253
|
s.add_dependency(%q<progressbar>, ["= 0.10.0"])
|
251
254
|
s.add_dependency(%q<update_hints>, ["~> 1.0"])
|
252
|
-
s.add_dependency(%q<bundler>, [">= 0"])
|
253
255
|
s.add_dependency(%q<approximately>, [">= 0"])
|
254
256
|
s.add_dependency(%q<jeweler>, [">= 0"])
|
255
257
|
s.add_dependency(%q<rake>, [">= 0"])
|
258
|
+
s.add_dependency(%q<linebyline>, [">= 0"])
|
256
259
|
s.add_dependency(%q<flexmock>, ["~> 1.3"])
|
257
260
|
s.add_dependency(%q<cli_test>, ["~> 1.0"])
|
258
261
|
s.add_dependency(%q<rake-hooks>, [">= 0"])
|
metadata
CHANGED
@@ -1,16 +1,32 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tracksperanto
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.3.
|
5
|
-
prerelease:
|
4
|
+
version: 3.3.6
|
5
|
+
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Julik Tarkhanov
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-04-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
14
30
|
- !ruby/object:Gem::Dependency
|
15
31
|
name: obuf
|
16
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -34,7 +50,7 @@ dependencies:
|
|
34
50
|
requirements:
|
35
51
|
- - ~>
|
36
52
|
- !ruby/object:Gem::Version
|
37
|
-
version: '2.
|
53
|
+
version: '2.1'
|
38
54
|
type: :runtime
|
39
55
|
prerelease: false
|
40
56
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -42,23 +58,23 @@ dependencies:
|
|
42
58
|
requirements:
|
43
59
|
- - ~>
|
44
60
|
- !ruby/object:Gem::Version
|
45
|
-
version: '2.
|
61
|
+
version: '2.1'
|
46
62
|
- !ruby/object:Gem::Dependency
|
47
63
|
name: bychar
|
48
64
|
requirement: !ruby/object:Gem::Requirement
|
49
65
|
none: false
|
50
66
|
requirements:
|
51
|
-
- -
|
67
|
+
- - ~>
|
52
68
|
- !ruby/object:Gem::Version
|
53
|
-
version: '
|
69
|
+
version: '2'
|
54
70
|
type: :runtime
|
55
71
|
prerelease: false
|
56
72
|
version_requirements: !ruby/object:Gem::Requirement
|
57
73
|
none: false
|
58
74
|
requirements:
|
59
|
-
- -
|
75
|
+
- - ~>
|
60
76
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
77
|
+
version: '2'
|
62
78
|
- !ruby/object:Gem::Dependency
|
63
79
|
name: progressive_io
|
64
80
|
requirement: !ruby/object:Gem::Requirement
|
@@ -124,14 +140,14 @@ dependencies:
|
|
124
140
|
- !ruby/object:Gem::Version
|
125
141
|
version: '1.0'
|
126
142
|
- !ruby/object:Gem::Dependency
|
127
|
-
name:
|
143
|
+
name: approximately
|
128
144
|
requirement: !ruby/object:Gem::Requirement
|
129
145
|
none: false
|
130
146
|
requirements:
|
131
147
|
- - ! '>='
|
132
148
|
- !ruby/object:Gem::Version
|
133
149
|
version: '0'
|
134
|
-
type: :
|
150
|
+
type: :development
|
135
151
|
prerelease: false
|
136
152
|
version_requirements: !ruby/object:Gem::Requirement
|
137
153
|
none: false
|
@@ -140,7 +156,7 @@ dependencies:
|
|
140
156
|
- !ruby/object:Gem::Version
|
141
157
|
version: '0'
|
142
158
|
- !ruby/object:Gem::Dependency
|
143
|
-
name:
|
159
|
+
name: jeweler
|
144
160
|
requirement: !ruby/object:Gem::Requirement
|
145
161
|
none: false
|
146
162
|
requirements:
|
@@ -156,7 +172,7 @@ dependencies:
|
|
156
172
|
- !ruby/object:Gem::Version
|
157
173
|
version: '0'
|
158
174
|
- !ruby/object:Gem::Dependency
|
159
|
-
name:
|
175
|
+
name: rake
|
160
176
|
requirement: !ruby/object:Gem::Requirement
|
161
177
|
none: false
|
162
178
|
requirements:
|
@@ -172,7 +188,7 @@ dependencies:
|
|
172
188
|
- !ruby/object:Gem::Version
|
173
189
|
version: '0'
|
174
190
|
- !ruby/object:Gem::Dependency
|
175
|
-
name:
|
191
|
+
name: linebyline
|
176
192
|
requirement: !ruby/object:Gem::Requirement
|
177
193
|
none: false
|
178
194
|
requirements:
|
@@ -456,13 +472,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
456
472
|
version: '0'
|
457
473
|
segments:
|
458
474
|
- 0
|
459
|
-
hash:
|
475
|
+
hash: -4545677537433489103
|
460
476
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
461
477
|
none: false
|
462
478
|
requirements:
|
463
|
-
- - ! '
|
479
|
+
- - ! '>='
|
464
480
|
- !ruby/object:Gem::Version
|
465
|
-
version:
|
481
|
+
version: '0'
|
466
482
|
requirements: []
|
467
483
|
rubyforge_project:
|
468
484
|
rubygems_version: 1.8.24
|