rivendell-import 0.0.5 → 0.6

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -3,6 +3,9 @@ source "https://rubygems.org"
3
3
  gemspec
4
4
 
5
5
  # gem "rivendell-db", :path => "~/Projects/RivendellDb"
6
+ # gem "rivendell-api", :path => "~/Projects/RivendellApi"
7
+
8
+ gem 'capistrano'
6
9
 
7
10
  if RUBY_PLATFORM =~ /linux/
8
11
  gem 'libnotify'
data/Gemfile.lock CHANGED
@@ -1,15 +1,16 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rivendell-import (0.0.5)
4
+ rivendell-import (0.6)
5
5
  SyslogLogger (~> 2.0)
6
6
  activerecord (~> 3.2.8)
7
7
  activesupport (~> 3.2.8)
8
8
  daemons
9
9
  httmultiparty
10
+ httparty (= 0.11.0)
10
11
  listen (~> 1.2.1)
11
12
  mail
12
- rivendell-api (~> 0.0.4)
13
+ rivendell-api (~> 0.0.5)
13
14
  rivendell-db
14
15
  sinatra
15
16
  sqlite3
@@ -20,21 +21,27 @@ GEM
20
21
  remote: https://rubygems.org/
21
22
  specs:
22
23
  SyslogLogger (2.0)
23
- activemodel (3.2.13)
24
- activesupport (= 3.2.13)
24
+ activemodel (3.2.14)
25
+ activesupport (= 3.2.14)
25
26
  builder (~> 3.0.0)
26
- activerecord (3.2.13)
27
- activemodel (= 3.2.13)
28
- activesupport (= 3.2.13)
27
+ activerecord (3.2.14)
28
+ activemodel (= 3.2.14)
29
+ activesupport (= 3.2.14)
29
30
  arel (~> 3.0.2)
30
31
  tzinfo (~> 0.3.29)
31
- activesupport (3.2.13)
32
- i18n (= 0.6.1)
32
+ activesupport (3.2.14)
33
+ i18n (~> 0.6, >= 0.6.4)
33
34
  multi_json (~> 1.0)
34
35
  addressable (2.3.5)
35
36
  arel (3.0.2)
36
37
  bcrypt-ruby (3.0.1)
37
38
  builder (3.0.3)
39
+ capistrano (2.14.2)
40
+ highline
41
+ net-scp (>= 1.0.0)
42
+ net-sftp (>= 2.0.0)
43
+ net-ssh (>= 2.0.14)
44
+ net-ssh-gateway (>= 1.1.0)
38
45
  cucumber (1.2.1)
39
46
  builder (>= 2.1.2)
40
47
  diff-lcs (>= 1.1.3)
@@ -84,13 +91,14 @@ GEM
84
91
  guard-rspec (2.0.0)
85
92
  guard (>= 1.1)
86
93
  rspec (~> 2.11)
94
+ highline (1.6.16)
87
95
  httmultiparty (0.3.10)
88
96
  httparty (>= 0.7.3)
89
97
  multipart-post
90
98
  httparty (0.11.0)
91
99
  multi_json (~> 1.0)
92
100
  multi_xml (>= 0.5.2)
93
- i18n (0.6.1)
101
+ i18n (0.6.5)
94
102
  json (1.7.5)
95
103
  json_pure (1.8.0)
96
104
  libnotify (0.8.0)
@@ -102,10 +110,17 @@ GEM
102
110
  mail (2.5.4)
103
111
  mime-types (~> 1.16)
104
112
  treetop (~> 1.4.8)
105
- mime-types (1.23)
106
- multi_json (1.4.0)
107
- multi_xml (0.5.4)
113
+ mime-types (1.25)
114
+ multi_json (1.7.7)
115
+ multi_xml (0.5.5)
108
116
  multipart-post (1.2.0)
117
+ net-scp (1.1.0)
118
+ net-ssh (>= 2.6.5)
119
+ net-sftp (2.1.1)
120
+ net-ssh (>= 2.6.5)
121
+ net-ssh (2.6.6)
122
+ net-ssh-gateway (1.2.0)
123
+ net-ssh (>= 2.6.5)
109
124
  null_logger (0.0.1)
110
125
  polyglot (0.3.3)
111
126
  rack (1.5.2)
@@ -117,7 +132,7 @@ GEM
117
132
  ffi (>= 0.5.0)
118
133
  rb-kqueue (0.2.0)
119
134
  ffi (>= 0.5.0)
120
- rivendell-api (0.0.4)
135
+ rivendell-api (0.0.5)
121
136
  activesupport
122
137
  httmultiparty
123
138
  null_logger
@@ -143,11 +158,11 @@ GEM
143
158
  rack (~> 1.4)
144
159
  rack-protection (~> 1.4)
145
160
  tilt (~> 1.3, >= 1.3.4)
146
- sqlite3 (1.3.7)
161
+ sqlite3 (1.3.8)
147
162
  stringex (1.5.1)
148
163
  thor (0.16.0)
149
164
  tilt (1.4.1)
150
- treetop (1.4.14)
165
+ treetop (1.4.15)
151
166
  polyglot
152
167
  polyglot (>= 0.3.1)
153
168
  trollop (2.0)
@@ -159,6 +174,7 @@ PLATFORMS
159
174
  ruby
160
175
 
161
176
  DEPENDENCIES
177
+ capistrano
162
178
  cucumber
163
179
  database_cleaner
164
180
  guard
data/Guardfile CHANGED
@@ -1,7 +1,7 @@
1
1
  # A sample Guardfile
2
2
  # More info at https://github.com/guard/guard#readme
3
3
 
4
- guard 'rspec', :version => 2 do
4
+ guard 'rspec' do
5
5
  watch(%r{^spec/.+_spec\.rb$})
6
6
  watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
7
  watch('spec/spec_helper.rb') { "spec" }
data/examples/config.rb CHANGED
@@ -20,6 +20,8 @@ Rivendell::Import.config do |config|
20
20
  config.rivendell.password = ""
21
21
 
22
22
  config.to_prepare do |file|
23
+ cart.default_title = file.basename
24
+
23
25
  file.in("music") do
24
26
  cart.group = "MUSIC"
25
27
  end
@@ -2,43 +2,42 @@ Feature: Manage Cart attributes
2
2
  In order to organize dropboxes
3
3
  An user
4
4
  wants to filter files by name
5
-
5
+
6
6
  Scenario: Select a file by Ruby regexp
7
- Given a configuration with this prepare block
7
+ Given a configuration with this prepare block
8
8
  """
9
9
  if file.match /dummy/
10
10
  task.tags << 'matched'
11
11
  end
12
- """
13
- When a file "dummy.wav" is imported
12
+ """
13
+ When a file "dummy.wav" is imported
14
14
  Then the task should have tag "matched"
15
15
 
16
16
  Scenario: Select a file with helper 'with'
17
- Given a configuration with this prepare block
17
+ Given a configuration with this prepare block
18
18
  """
19
19
  with /dummy/ do
20
20
  task.tag 'matched'
21
21
  end
22
- """
23
- When a file "dummy.wav" is imported
22
+ """
23
+ When a file "dummy.wav" is imported
24
24
  Then the task should have tag "matched"
25
25
 
26
26
  Scenario: Select a cast by file name
27
27
  Given a cart "123" exists with title:"A long Title"
28
- And a configuration with this prepare block
28
+ And a configuration with this prepare block
29
29
  """
30
30
  cart.find_by_title file.basename
31
- """
32
- When a file "a-long-title.wav" is imported
31
+ """
32
+ When a file "a-long-title.wav" is imported
33
33
  Then the task should have destination "Cart 123"
34
34
 
35
35
  Scenario: Select a cast by file name
36
36
  Given a cart "123" exists with title:"A long Title", group:"PAD"
37
37
  And a cart "666" exists with title:"A long Title", group:"MUSIC"
38
- And a configuration with this prepare block
38
+ And a configuration with this prepare block
39
39
  """
40
40
  cart.find_by_title file.basename, :group => 'PAD'
41
- """
42
- When a file "a-long-title.wav" is imported
41
+ """
42
+ When a file "a-long-title.wav" is imported
43
43
  Then the task should have destination "Cart 123"
44
-
@@ -1,6 +1,6 @@
1
1
  def import
2
2
  @import ||= Rivendell::Import::Base.new.tap do |import|
3
-
3
+
4
4
  end
5
5
  end
6
6
 
@@ -16,7 +16,7 @@ Given /^a cart "(.*?)" exists with (.*)$/ do |number, fields|
16
16
  attributes = fields.scan(/\ *(([^:]+):"([^\"]+)",?)/).map do |part, name, value|
17
17
  [name, value]
18
18
  end.as_hash
19
-
19
+
20
20
  cart = Rivendell::API::Cart.new(attributes.merge(:number => number))
21
21
  Rivendell::Import::Task.mock_xport.carts << cart
22
22
  end
@@ -26,6 +26,7 @@ Given /^a configuration with this prepare block$/ do |code|
26
26
  end
27
27
 
28
28
  When /^a file "([^"]*)" is imported$/ do |file|
29
+ FileUtils.touch file, :mtime => Time.now - 15
29
30
  import.file file
30
31
  end
31
32
 
@@ -8,13 +8,16 @@ module Rivendell::Import
8
8
 
9
9
  set :public_folder, ::File.expand_path('static', ::File.dirname(__FILE__))
10
10
  # set :static_cache_control, [:public, :max_age => 3600]
11
+ set :bind, '0.0.0.0'
11
12
 
12
13
  get '/' do
13
14
  redirect "/tasks", 302
14
15
  end
15
16
 
16
17
  get '/tasks' do
17
- erb :index, :locals => { :tasks => tasks.paginate(:page => params[:page], :per_page => 15) }
18
+ tasks = self.tasks.paginate(:page => params[:page], :per_page => (params[:per_page] or 15))
19
+ tasks = tasks.search(params[:search]) if params[:search]
20
+ erb :index, :locals => { :tasks => tasks }
18
21
  end
19
22
 
20
23
  get '/tasks.json' do
@@ -50,4 +53,3 @@ module Rivendell::Import
50
53
 
51
54
  end
52
55
  end
53
-
@@ -24,9 +24,15 @@ module Rivendell::Import
24
24
  Rivendell::Import.logger.info "Listen files in #{directory}"
25
25
 
26
26
  callback = Proc.new do |modified, added, removed|
27
- added.each do |file|
28
- Rivendell::Import.logger.debug "Detected file '#{file}'"
29
- file(file, directory)
27
+ # Rivendell::Import.logger.debug [modified, added, removed].inspect
28
+ begin
29
+ added.each do |file|
30
+ Rivendell::Import.logger.debug "Detected file '#{file}'"
31
+ file(file, directory)
32
+ end
33
+ rescue Exception => e
34
+ Rivendell::Import.logger.error "Task creation failed : #{e}"
35
+ Rivendell::Import.logger.debug e.backtrace.join("\n")
30
36
  end
31
37
  end
32
38
 
@@ -41,6 +47,7 @@ module Rivendell::Import
41
47
  end
42
48
 
43
49
  def file(path, base_directory = nil)
50
+ path = ::File.expand_path(path, base_directory)
44
51
  file = Rivendell::Import::File.new path, :base_directory => base_directory
45
52
  create_task file
46
53
  end
@@ -5,7 +5,7 @@ module Rivendell::Import
5
5
  include ActiveModel::Serializers::JSON
6
6
 
7
7
  def attributes
8
- %w{number group clear_cuts?}.inject({}) do |map, attribute|
8
+ %w{number group clear_cuts? title default_title}.inject({}) do |map, attribute|
9
9
  value = send attribute
10
10
  map[attribute] = value if value
11
11
  map
@@ -18,7 +18,7 @@ module Rivendell::Import
18
18
 
19
19
  delegate :blank?, :to => :attributes
20
20
 
21
- attr_accessor :number, :group
21
+ attr_accessor :number, :group, :title, :default_title
22
22
  attr_reader :task
23
23
 
24
24
  def initialize(task = nil)
@@ -37,9 +37,18 @@ module Rivendell::Import
37
37
  end
38
38
 
39
39
  def update
40
- # xport.edit_cart # to define title, etc ...
40
+ update_attributes = attributes.dup
41
+
42
+ if default_title
43
+ current_cart = xport.list_cart(number)
44
+ unless current_cart.has_title?
45
+ update_attributes[:title] = default_title
46
+ end
47
+ end
48
+
49
+ xport.edit_cart number, update_attributes
41
50
  end
42
-
51
+
43
52
  def cut
44
53
  @cut ||= Cut.new(self)
45
54
  end
@@ -70,9 +79,9 @@ module Rivendell::Import
70
79
  cattr_accessor :db_url
71
80
 
72
81
  def cart_finder
73
- @cart_finder ||=
82
+ @cart_finder ||=
74
83
  begin
75
- unless db_url
84
+ unless db_url
76
85
  Rivendell::Import::CartFinder::ByApi.new xport
77
86
  else
78
87
  Rivendell::DB.establish_connection(db_url)
@@ -80,7 +89,6 @@ module Rivendell::Import
80
89
  end
81
90
  end
82
91
  end
83
-
92
+
84
93
  end
85
94
  end
86
-
@@ -46,7 +46,7 @@ module Rivendell::Import
46
46
 
47
47
  def parser
48
48
  @parser ||= Trollop::Parser.new do
49
- opt :config, "Configuration file", :type => String, :required => true
49
+ opt :config, "Configuration file", :type => String #, :required => true
50
50
  opt :listen, "Wait for files in given directory"
51
51
  opt :dry_run, "Just create tasks without executing them"
52
52
  opt :debug, "Enable debug messages (in stderr)"
@@ -17,6 +17,7 @@ module Rivendell::Import
17
17
  return unless auto_reload?
18
18
 
19
19
  callback = Proc.new do |modified, added, removed|
20
+ Rivendell::Import.logger.debug "Configuration changed ? #{[modified, added, removed].inspect}"
20
21
  if modified.include? absolute_path
21
22
  Rivendell::Import.logger.info "Configuration changed, reload it"
22
23
  load
@@ -43,9 +43,21 @@ module Rivendell::Import
43
43
  end
44
44
  end
45
45
 
46
+ def ready?
47
+ if age = modification_age
48
+ age > 10
49
+ else
50
+ false
51
+ end
52
+ end
53
+
54
+ def modification_age
55
+ Time.now - ::File.mtime(path) if exists?
56
+ end
57
+
46
58
  def in(directory, &block)
47
59
  if match %r{^#{directory}/}
48
- yield
60
+ yield
49
61
  end
50
62
  end
51
63
 
@@ -135,3 +135,9 @@ em { font-style: italic; }
135
135
  #content table tr.odd {
136
136
  background-color: #EAEAEA;
137
137
  }
138
+ #content .pagination {
139
+ float: right;
140
+ }
141
+ #content form {
142
+ margin-bottom: 10px;
143
+ }
@@ -11,15 +11,23 @@ module Rivendell::Import
11
11
  include Rivendell::Import::Tasking::Cart
12
12
  include Rivendell::Import::Tasking::Status
13
13
  include Rivendell::Import::Tasking::Destination
14
-
14
+
15
15
  def self.pending
16
16
  where :status => "pending"
17
17
  end
18
18
 
19
+ def self.ready
20
+ self.pending.select(&:ready?)
21
+ end
22
+
19
23
  def self.ran
20
24
  where :status => %w{completed failed}
21
25
  end
22
26
 
27
+ def self.search(text)
28
+ where [ "lower(file_name) like ?", "%#{text.downcase}%" ]
29
+ end
30
+
23
31
  def ran?
24
32
  status.completed? or status.failed?
25
33
  end
@@ -71,6 +79,22 @@ module Rivendell::Import
71
79
  end
72
80
  after_status_changed :notify!, :on => [:completed, :failed]
73
81
 
82
+ def ready?
83
+ status.pending? and file_ready?
84
+ end
85
+
86
+ def detailed_status
87
+ if status.pending? and not ready?
88
+ "waiting"
89
+ else
90
+ status
91
+ end
92
+ end
93
+
94
+ def file_ready?
95
+ file.ready?
96
+ end
97
+
74
98
  def destroy_file!
75
99
  file.destroy! if delete_file?
76
100
  end
@@ -94,7 +118,7 @@ module Rivendell::Import
94
118
  logger.debug e.backtrace.join("\n")
95
119
  ensure
96
120
  unless status.completed?
97
- change_status! :failed
121
+ change_status! :failed
98
122
  end
99
123
  save!
100
124
  end
@@ -2,11 +2,15 @@ module Rivendell::Import
2
2
  class Tasks
3
3
 
4
4
  def pop
5
- Task.pending.first
5
+ ready_tasks.first
6
6
  end
7
7
 
8
8
  def run
9
- Task.pending.find_each(&:run)
9
+ ready_tasks.each(&:run)
10
+ end
11
+
12
+ def ready_tasks
13
+ Task.ready
10
14
  end
11
15
 
12
16
  def create(file, &block)
@@ -1,5 +1,5 @@
1
1
  module Rivendell
2
2
  module Import
3
- VERSION = "0.0.5"
3
+ VERSION = "0.6"
4
4
  end
5
5
  end
@@ -24,6 +24,11 @@
24
24
  <div id="content">
25
25
  <%= will_paginate tasks %>
26
26
 
27
+ <form action=""/>
28
+ <input type="text" name="search" value="<%= params[:search] %>"/>
29
+ <input type="submit" value="Search"/>
30
+ </form>
31
+
27
32
  <table>
28
33
  <tr>
29
34
  <th>#</th>
@@ -36,7 +41,7 @@
36
41
  <% tasks.each_with_index do |task, index| %>
37
42
  <tr class="<%= 'odd' if index.odd? %>">
38
43
  <td><%= task.id %></td>
39
- <td><%= task.status %></td>
44
+ <td><%= task.detailed_status %></td>
40
45
  <td><%= distance_of_time_in_words_from_now(task.updated_at) %></td>
41
46
  <td><%= truncate_filename(task.file, 60) %></td>
42
47
  <td><%= task.destination %></td>
@@ -17,7 +17,9 @@ Gem::Specification.new do |gem|
17
17
 
18
18
  gem.add_runtime_dependency 'listen', '~> 1.2.1'
19
19
  gem.add_runtime_dependency 'httmultiparty'
20
- gem.add_runtime_dependency 'rivendell-api', '~> 0.0.4'
20
+ # 0.12.0 requires ruby 1.9.3
21
+ gem.add_runtime_dependency 'httparty', '0.11.0'
22
+ gem.add_runtime_dependency 'rivendell-api', '~> 0.0.5'
21
23
  gem.add_runtime_dependency 'trollop'
22
24
  gem.add_runtime_dependency 'activerecord', '~> 3.2.8'
23
25
  gem.add_runtime_dependency 'activesupport', '~> 3.2.8'
@@ -5,7 +5,7 @@ describe Rivendell::Import::Base do
5
5
  describe "#prepare_task" do
6
6
 
7
7
  let(:task) { mock }
8
-
8
+
9
9
  it "should prepare task with to_prepare block" do
10
10
  subject.to_prepare = Proc.new {}
11
11
  task.should_receive :prepare
@@ -22,13 +22,13 @@ describe Rivendell::Import::Base do
22
22
  subject.stub :default_to_prepare => block
23
23
  subject.to_prepare.should == block
24
24
  end
25
-
25
+
26
26
  end
27
27
 
28
28
  describe "#create_task" do
29
29
 
30
30
  let(:file) { Rivendell::Import::File.new "dummy.wav" }
31
-
31
+
32
32
  it "should create a task with given file" do
33
33
  Rivendell::Import::Task.should_receive(:create).with({:file => file}, {})
34
34
  subject.create_task file
@@ -44,9 +44,9 @@ describe Rivendell::Import::Base do
44
44
  describe "#file" do
45
45
 
46
46
  let(:file) { Rivendell::Import::File.new("dummy.wav") }
47
-
47
+
48
48
  it "should create a File with given path and base_directory" do
49
- Rivendell::Import::File.should_receive(:new).with("path", :base_directory => "base_directory")
49
+ Rivendell::Import::File.should_receive(:new).with(File.expand_path("path", "base_directory"), :base_directory => "base_directory")
50
50
  subject.file "path", "base_directory"
51
51
  end
52
52
 
@@ -59,11 +59,11 @@ describe Rivendell::Import::Base do
59
59
  end
60
60
 
61
61
  describe "#directory" do
62
-
62
+
63
63
  it "should look for files in given directory" do
64
- Dir.mktmpdir do |directory|
64
+ Dir.mktmpdir do |directory|
65
65
  FileUtils.mkdir "#{directory}/subdirectory"
66
-
66
+
67
67
  file = "#{directory}/subdirectory/dummy.wav"
68
68
  FileUtils.touch file
69
69
 
@@ -73,9 +73,9 @@ describe Rivendell::Import::Base do
73
73
  end
74
74
 
75
75
  end
76
-
76
+
77
77
  describe "#process" do
78
-
78
+
79
79
  it "should use file method when path isn't a directory" do
80
80
  File.stub :directory? => false
81
81
  subject.should_receive(:file).with("dummy")
@@ -93,7 +93,7 @@ describe Rivendell::Import::Base do
93
93
  describe "#listen" do
94
94
 
95
95
  before(:each) do
96
- Listen.stub :to => true
96
+ Listen.stub :to => mock(:change => mock(:start! => true))
97
97
  end
98
98
 
99
99
  let(:directory) { "directory" }
@@ -103,7 +103,7 @@ describe Rivendell::Import::Base do
103
103
  worker.stub :start => worker
104
104
  Rivendell::Import::Worker.stub :new => worker
105
105
  end
106
-
106
+
107
107
  it "should create a Worker" do
108
108
  Rivendell::Import::Worker.should_receive(:new).with(subject).and_return(worker)
109
109
  subject.listen directory
@@ -125,12 +125,6 @@ describe Rivendell::Import::Base do
125
125
  subject.listen directory
126
126
  end
127
127
 
128
- it "should invoke file with added files" do
129
- Listen.stub(:to).and_yield(nil,%w{file},nil)
130
- subject.should_receive(:file).with("file", directory)
131
- subject.listen directory
132
- end
133
-
134
128
  end
135
129
 
136
130
  end