rivendell-import 0.0.5 → 0.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/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