tracksperanto 3.3.0.pre → 3.3.6
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.
- 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
|