luigi 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 31f72e1bb7c69d75d612950916f95e58fa4400aa
4
+ data.tar.gz: 5ef3d3525cc4fed1a18e116f2a181b0404345824
5
+ SHA512:
6
+ metadata.gz: 36b695ae7932032f603148293248e81783306009f32fcf88aa9c0bc151987cb84cfb635114e8b5fb4129d55b920c3beb97543f5a14139770dc4803bbfea22073
7
+ data.tar.gz: 5a90dce275ef2342a929b19c05387d581f5b51e171e336efc2c9ff7e7c386bfbaed2106b3a6a4ef7602935d58924ae693035a4f0f87027335389e7da6ae5fb5f
@@ -0,0 +1,34 @@
1
+ require 'date'
2
+
3
+ #interface
4
+ class PlumberProject
5
+
6
+ def initialize path
7
+ open path
8
+ end
9
+
10
+ def open path
11
+ @path = path
12
+ end
13
+
14
+ def path
15
+ @path
16
+ end
17
+
18
+ def name
19
+ File.basename @path, ".yml"
20
+ end
21
+
22
+ def index
23
+ 123
24
+ end
25
+
26
+ def STATUS
27
+ :ok # at least :ok or anything else
28
+ end
29
+
30
+ def date
31
+ return Date.today
32
+
33
+ end
34
+ end
@@ -0,0 +1,396 @@
1
+ # encoding: utf-8
2
+ require 'fileutils'
3
+ require 'logger'
4
+
5
+ require File.join File.dirname(__FILE__), "luigi/gitplumber"
6
+ require File.join File.dirname(__FILE__), "luigi/ShellSanitizer"
7
+
8
+ ## requires a project_class
9
+ # project_class must implement: name, date
10
+ class Luigi
11
+
12
+ attr_reader :dirs,
13
+ :opened_projects,
14
+ :project_paths,
15
+ :opened_paths,
16
+ :opened_sort,
17
+ :opened_dir
18
+
19
+ attr_writer :project_class
20
+
21
+ include GitPlumber
22
+
23
+
24
+ def initialize(settings, project_class = nil)
25
+ @settings = settings
26
+ @opened_projects = []
27
+ @project_class = project_class
28
+ @file_extension = settings['project_file_extension']
29
+ @using_git = settings['use_git']
30
+
31
+ @logger = Logger.new(STDERR)
32
+ @logger.level = Logger::ERROR
33
+ @logger.error "need a project_class" if project_class.nil?
34
+ @logger.progname = "LUIGI"
35
+
36
+ @dirs = {}
37
+ # TODO allow for multiple templates
38
+ @dirs[:template] = File.expand_path File.join @settings['script_path'], @settings['templates']['project']
39
+ @dirs[:storage] = File.expand_path File.join @settings['path'], @settings['dirs']['storage']
40
+ @dirs[:working] = File.join @dirs[:storage], @settings['dirs']['working']
41
+ @dirs[:archive] = File.join @dirs[:storage], @settings['dirs']['archive']
42
+
43
+
44
+ end
45
+
46
+ ##
47
+ # Checks the existens of one of the three basic dirs.
48
+ # dir can be either :storage, :working or :archive
49
+ # and also :template
50
+ def check_dir(dir)
51
+ File.exists? "#{@dirs[dir]}"
52
+ end
53
+
54
+ ##
55
+ # Checks the existens of every thing required
56
+ def check_dirs
57
+ check_dir :storage and
58
+ check_dir :working and
59
+ check_dir :archive and
60
+ check_dir :template
61
+ end
62
+
63
+ ##
64
+ # create a dir
65
+ # dir can be either :storage, :working or :archive
66
+ def create_dir(dir)
67
+ unless check_dir(dir)
68
+ if dir == :storage or check_dir :storage
69
+ FileUtils.mkdir "#{@dirs[dir]}"
70
+ @logger.info "Created \"#{dir.to_s}\" Directory (#{@dirs[dir]})"
71
+ return true
72
+ end
73
+ @logger.error "no storage dir"
74
+ end
75
+ return false
76
+ end
77
+
78
+ ##
79
+ # creates new project_dir and project_file
80
+ def _new_project_folder(name)
81
+ unless check_dir(:working)
82
+ @logger.info(File.exists? @dirs[:working])
83
+ @logger.info "missing working directory!"
84
+ return false
85
+ end
86
+
87
+ # check of existing project with the same name
88
+ folder = get_project_folder(name, :working)
89
+ unless folder
90
+ FileUtils.mkdir File.join @dirs[:working], name
91
+ return get_project_folder(name, :working)
92
+ else
93
+ @logger.info "#{folder} already exists"
94
+ return false
95
+ end
96
+ end
97
+
98
+ ##
99
+ # creates new project_dir and project_file
100
+ # returns project object
101
+ def new_project(_name)
102
+ _name = ShellSanitizer.process _name
103
+ name = ShellSanitizer.clean_path _name
104
+
105
+ project_name = _name
106
+ settings = @settings
107
+ defaults = @settings['defaults']
108
+ defaults = {}
109
+
110
+ filename = @dirs[:template]
111
+
112
+ ## Approach A ( Thomas Kühn )
113
+ engine=ERB.new(File.read(filename),nil,'<>')
114
+ result = engine.result(binding)
115
+
116
+ # copy template_file to project_dir
117
+ folder = _new_project_folder(name)
118
+ if folder
119
+ target = File.join folder, name+@file_extension
120
+
121
+ #puts "writing into #{target}"
122
+ file = File.new target, "w"
123
+ result.lines.each do |line|
124
+ file.write line
125
+ end
126
+ file.close
127
+
128
+ @logger.info "#{folder} created"
129
+ return @project_class.new target
130
+ else
131
+ return false
132
+ end
133
+ end
134
+
135
+
136
+ ##
137
+ # produces an Array of @project_class objects
138
+ # sorted by date (projects must implement date())
139
+ # if sort is foobar, projects must implement foobar()
140
+ # output of (foobar must be comparable)
141
+ #
142
+ # untested
143
+ def open_projects(dir=:working, year=Date.today.year, sort = :date)
144
+ if dir==:all
145
+ @opened_paths = list_projects_all
146
+ else
147
+ @opened_paths = list_projects dir, year
148
+ end
149
+
150
+ @opened_dir = dir
151
+ @project_paths = {}
152
+ @opened_paths.each {|path|
153
+ project = @project_class.new path
154
+ if project.STATUS == :ok
155
+ @opened_projects = @opened_projects + [ project ]
156
+ end
157
+ @project_paths[project.name] = path
158
+ }
159
+ sort_projects(sort)
160
+ return true
161
+ end
162
+
163
+ def open_project project
164
+ if project.class == String
165
+ project = ShellSanitizer.process project
166
+ project = ShellSanitizer.clean_path project
167
+ open_projects()
168
+ project = lookup(project)
169
+ end
170
+ return project if project.class == @project_class
171
+ return false
172
+ end
173
+
174
+
175
+ ##
176
+ # produces an Array of @project_class objects
177
+ #
178
+ # untested
179
+ def open_projects_all(sort = :date)
180
+ @opened_paths = list_projects_all
181
+ open_projects :all, year=nil, sort
182
+ end
183
+
184
+ def [] name
185
+ lookup name
186
+ end
187
+
188
+ def lookup_path(name, sort = nil)
189
+ p = lookup(name)
190
+ return @project_paths[p.name] unless p.nil?
191
+ @logger.error "there is no project #{name}"
192
+ return false
193
+ end
194
+
195
+
196
+ def lookup(name, sort = nil)
197
+ sort_projects sort unless sort == nil or @opened_sort == sort
198
+ name = name.to_i - 1 if name =~ /^\d*$/
199
+ if name.class == String
200
+ name_map = {}
201
+ @opened_projects.each {|project| name_map[project.name] = project}
202
+ project = name_map[name]
203
+ @logger.error "there is no project \"#{name}\"" if project.nil?
204
+ elsif name.class == Fixnum
205
+ project = @opened_projects[name]
206
+ @logger.error "there is no project ##{name+1}" if project.nil?
207
+ end
208
+ return project
209
+ end
210
+
211
+
212
+ def sort_projects(sort = :date)
213
+ fail "sort must be a Symbol" unless sort.class == Symbol
214
+ if @project_class.method_defined? sort
215
+ @opened_projects.sort_by! {|project| project.method(sort).call}
216
+ else fail "#{@project_class} does not implement #{sort}()"
217
+ end
218
+ return true
219
+ end
220
+
221
+ ##
222
+ # path to project file
223
+ # there may only be one @file_extension file per project folder
224
+ #
225
+ # untested
226
+ def get_project_file_path(name, dir=:working, year=Date.today.year)
227
+ name = ShellSanitizer.process name
228
+ name = ShellSanitizer.clean_path name
229
+
230
+ folder = get_project_folder(name, dir, year)
231
+ if folder
232
+ files = Dir.glob File.join folder, "*#{@file_extension}"
233
+ warn "ambiguous amount of #{@file_extension} files in #{folder}" if files.length > 1
234
+ warn "no #{@file_extension} files in #{folder}" if files.length < 1
235
+ return files[0]
236
+ end
237
+ @logger.info "NO FOLDER get_project_folder(name = #{name}, dir = #{dir}, year = #{year})"
238
+ return false
239
+ end
240
+
241
+
242
+ ##
243
+ # Path to project folder
244
+ # If the folder exists
245
+ # dir can be :working or :archive
246
+ #
247
+ # TODO untested for archives
248
+ def get_project_folder( name, dir=:working, year=Date.today.year )
249
+ name = ShellSanitizer.process name
250
+ name = ShellSanitizer.clean_path name
251
+ year = year.to_s
252
+ target = File.join @dirs[dir], name if dir == :working
253
+ target = File.join @dirs[dir], year, name if dir == :archive
254
+ return target if File.exists? target
255
+ false
256
+ end
257
+
258
+ ##
259
+ # list projects
260
+ # lists project files
261
+ def list_project_names(dir = :working, year=Date.today.year)
262
+ return unless check_dir(dir)
263
+ if dir == :working
264
+ paths = Dir.glob File.join @dirs[dir], "/*"
265
+ names = paths.map {|path| File.basename path }
266
+ elsif dir == :archive
267
+ paths = Dir.glob File.join @dirs[dir], year.to_s, "/*"
268
+ names = paths.map {|path|
269
+ file_path = get_project_file_path (File.basename path), :archive, year
270
+ name = File.basename file_path, @file_extension
271
+ }
272
+ return names
273
+ else
274
+ @logger.error "unknown path #{dir}"
275
+ end
276
+ end
277
+
278
+ ##
279
+ # list projects
280
+ # lists project files
281
+ # (names actually contains paths)
282
+ def list_projects(dir = :working, year=Date.today.year)
283
+ return unless check_dir(dir)
284
+ if dir == :working
285
+ folders = Dir.glob File.join @dirs[dir], "/*"
286
+ paths = folders.map {|path| get_project_file_path File.basename path }
287
+ elsif dir == :archive
288
+ folders = Dir.glob File.join @dirs[dir], year.to_s, "/*"
289
+ paths = folders.map {|path| get_project_file_path (File.basename path), :archive, year }
290
+ else
291
+ @logger.error "unknown path #{dir}"
292
+ end
293
+
294
+ puts "WARNING! one folder is not correct" if paths.include? false
295
+ paths.keep_if{|v| v}
296
+ end
297
+
298
+ ##
299
+ # list projects
300
+ # lists project files
301
+ # (names actually contains paths)
302
+ def list_projects_all
303
+ names = []
304
+
305
+ #first all archived projects, ever :D
306
+ archives = Dir.glob File.join @dirs[:archive], "/*"
307
+ archives.sort!
308
+ archives.each do |a|
309
+ paths = Dir.glob File.join a, "/*"
310
+ year = File.basename a
311
+ names += paths.map { |path|
312
+ get_project_file_path (File.basename path), :archive, year
313
+ }
314
+ end
315
+
316
+ #then all working projects
317
+ names += list_projects :working
318
+
319
+ return names
320
+ end
321
+
322
+ def filter_by hash
323
+ filtered_projets = []
324
+ @opened_projects.each{|project|
325
+ hash.each{|key,value|
326
+ field = project.data(key)
327
+ if field and field.to_s.downcase.include? value
328
+ filtered_projets.push project
329
+ break
330
+ end
331
+ }
332
+ }
333
+ return filtered_projets
334
+ end
335
+
336
+ ##
337
+ # Move to archive directory
338
+ # @name
339
+ ## Luigi.archive_project should use ShellSanitizer
340
+ def archive_project(project, year = nil, prefix = '')
341
+ project = open_project project
342
+ return false unless project.class == @project_class
343
+
344
+ year ||= project.date.year
345
+ year_folder = File.join @dirs[:archive], year.to_s
346
+ FileUtils.mkdir year_folder unless File.exists? year_folder
347
+
348
+ project_folder = get_project_folder project.name, :working
349
+ if prefix and prefix.length > 0
350
+ archived_name = project.name.prepend(prefix + "_")
351
+ target = File.join year_folder, archived_name
352
+ else
353
+ target = File.join year_folder, project.name
354
+ end
355
+
356
+ return false unless project_folder
357
+ return false if list_project_names(:archive, year).include? project.name
358
+
359
+ @logger.info "moving: #{project_folder} to #{target}" if target and project_folder
360
+
361
+ FileUtils.mv project_folder, target
362
+ if open_git()
363
+ git_update_path project_folder
364
+ git_update_path target
365
+ end
366
+ return target
367
+ end
368
+
369
+ ##
370
+ # Move to archive directory
371
+ def unarchive_project(project, year = Date.today.year)
372
+ project = open_project project
373
+ return false unless project.class == @project_class
374
+
375
+ name = project.name
376
+ path = project.path
377
+ cleaned_name = File.basename(path,@file_extension)
378
+ source = get_project_folder name, :archive, year
379
+ target = File.join @dirs[:working], cleaned_name
380
+
381
+ @logger.info "moving #{source} to #{target}"
382
+ return false unless source
383
+
384
+ unless get_project_folder cleaned_name
385
+ FileUtils.mv source, target
386
+ if open_git()
387
+ git_update_path source
388
+ git_update_path target
389
+ end
390
+ return true
391
+ else
392
+ return false
393
+ end
394
+ end
395
+
396
+ end
@@ -0,0 +1,41 @@
1
+ # encoding: utf-8
2
+
3
+ class ShellSanitizer
4
+ REPLACE_HASH = {
5
+ ?“ => '"', ?” => '"', ?‘ => "'", ?’ => "'", ?„ => '"',
6
+
7
+ ?» => ">>", ?« => "<<",
8
+ ?ä => "ae", ?ö => "oe", ?ü => "ue",
9
+ ?Ä => "Ae", ?Ö => "Oe", ?Ü => "Ue",
10
+ ?ß => "ss", ?ï => "i", ?ë => "e",
11
+ ?æ => "ae", ?Æ => "AE", ?œ => "oe",
12
+ ?Œ => "OE",
13
+ ?€ => "EUR", ?¥ => "YEN",
14
+ ?½ => "1/2", ?¼ => "1/4", ?¾ => "3/4",
15
+ ?© => "(c)", ?™ => "(TM)", ?® => "(r)",
16
+ ?♥ => "<3", ?☺ => ":)"
17
+ }
18
+
19
+ def self.process(string)
20
+ string = deumlautify string
21
+ #string = Ascii.process string
22
+ return string
23
+ end
24
+
25
+ ## TODO somebody find my a gem that works and I'll replace this
26
+ def self.deumlautify(string)
27
+ REPLACE_HASH.each{|k,v| string = string.gsub k, v }
28
+ string.each_char.to_a.keep_if {|c| c.ascii_only?}
29
+ return string
30
+ end
31
+
32
+ def self.clean_path(path)
33
+ path = path.strip()
34
+ path = deumlautify path
35
+ path.sub!(/^\./,'') # removes hidden_file_dot '.' from the begging
36
+ path.gsub!(/\//,'_')
37
+ path.gsub!(/\//,'_')
38
+ return path
39
+ end
40
+
41
+ end
@@ -0,0 +1,151 @@
1
+ # encoding: utf-8
2
+
3
+ # # http://stackoverflow.com/questions/1891429/decorators-in-ruby-migrating-from-python
4
+ # module Documenter
5
+ # def document(func_name)
6
+ # old_method = instance_method(func_name)
7
+ #
8
+ # define_method(func_name) do |*args|
9
+ # puts "about to call #{func_name}(#{args.join(', ')})"
10
+ # old_method.bind(self).call(*args)
11
+ # end
12
+ # end
13
+ # end
14
+
15
+ require 'git'
16
+ require 'logger'
17
+ require 'textboxes'
18
+
19
+ module GitPlumber
20
+
21
+ def open_git
22
+ return false unless @using_git
23
+ logger = Logger.new STDOUT
24
+ begin
25
+ @git = Git.open @dirs[:storage]
26
+ return true
27
+ rescue => error
28
+ logger.error "#{@dirs[:storage]} does not seem to be a git repository"
29
+ return false
30
+ end
31
+ end
32
+
33
+ def git_log(count = 30)
34
+ table = Textboxes.new
35
+ table.style[:border] = false
36
+ @git.log(count = count).to_a.reverse.each do |commit|
37
+ table.add_row [
38
+ commit.author.name,
39
+ commit.message,
40
+ commit.date.strftime("%H:%M Uhr — %d.%m.%Y"),
41
+ ]
42
+ end
43
+ puts table
44
+ end
45
+
46
+ def git_push()
47
+ @git = Git.open @dirs[:storage], :log => Logger.new(STDOUT)
48
+ out = @git.push()
49
+ puts out if out
50
+ end
51
+
52
+ def git_pull()
53
+ @git = Git.open @dirs[:storage], :log => Logger.new(STDOUT)
54
+ out = @git.pull()
55
+ puts out if out
56
+ end
57
+
58
+ def git_commit(message)
59
+ @git.commit(message)
60
+ end
61
+
62
+ def git_update_path path = @git.dir
63
+ return unless @settings['use_git']
64
+ if File.exists? path
65
+ @git.add path
66
+ else
67
+ @git.remove path, {:recursive => true}
68
+ end
69
+
70
+ end
71
+
72
+ def git_save message
73
+ puts "GITSAVE\n"
74
+ git_add()
75
+ @git.commit_all "ruby git #commit_all \"#{message}\""
76
+ end
77
+
78
+ def git_status
79
+ renamed = git_renamed_files
80
+ exclude = renamed.flatten
81
+ if @git.status.added.length + @git.status.deleted.length + @git.status.untracked.length + @git.status.changed.length == 0
82
+ puts "Nothing Changed"
83
+ end
84
+
85
+ git_print_status :added, exclude
86
+ git_print_status :changed, exclude
87
+ git_print_status :deleted, exclude
88
+ git_print_status :untracked, exclude
89
+ git_print_renamed renamed
90
+ end
91
+
92
+ def git_print_status name, exclude
93
+ case name
94
+ when :added then status = @git.status.added
95
+ when :changed then status = @git.status.changed
96
+ when :deleted then status = @git.status.deleted
97
+ when :untracked then status = @git.status.untracked
98
+ end
99
+ status.reject! {|k,v| exclude.include? k }
100
+
101
+ puts "#{status.length} #{name.to_s.capitalize}:" if status.length > 0
102
+ status.each do |path, info|
103
+ case info.type
104
+ when "M" then color = :yellow
105
+ when "A" then color = :green
106
+ when "D" then color = :red
107
+ else color = :default
108
+ end
109
+ line = Paint[path, color]
110
+ state = " "
111
+ state = Paint[ "\e[32m✓\e[0m" , :green] if !info.sha_index.nil? and info.sha_index.to_i(16) > 0
112
+ puts "#{state} #{line}"
113
+ end
114
+ puts if status.length > 0
115
+ end
116
+
117
+ def git_renamed_files
118
+ repo_shas = {}
119
+ index_shas = {}
120
+ out = ""
121
+ files = []
122
+ @git.lib.diff_index('HEAD').each { |file, data|
123
+ sr = data[:sha_repo]
124
+ si = data[:sha_index]
125
+ repo_shas[sr] = file if sr.to_i(16) > 0
126
+ index_shas[si] = file if si.to_i(16) > 0
127
+ if index_shas.include? sr
128
+ files.push [ repo_shas[sr], index_shas[sr] ]
129
+ end
130
+ }
131
+ return files
132
+ end
133
+
134
+ def git_print_renamed files
135
+ puts "#{files.length} Renamed:" if files.length > 0
136
+ width = 0
137
+ files.map {|a,b| width = a.length if a.length > width}
138
+ out = ""
139
+ files.each {|a,b|
140
+ a = a.ljust(width)
141
+ out << Paint[ "\e[32m✓\e[0m" , :green] + " "
142
+ out << Paint[a, :red]
143
+ out << " -> "
144
+ out << Paint[b, :green]
145
+ out << "\n"
146
+ }
147
+ puts out if out.length > 0
148
+ end
149
+
150
+
151
+ end
@@ -0,0 +1,3 @@
1
+ module Luigi
2
+ VERSION = '1.0.0'
3
+ end
metadata ADDED
@@ -0,0 +1,124 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: luigi
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Hendrik Sollich
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-11-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec-core
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: git
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.2'
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: 1.2.8
65
+ type: :runtime
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - "~>"
70
+ - !ruby/object:Gem::Version
71
+ version: '1.2'
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: 1.2.8
75
+ - !ruby/object:Gem::Dependency
76
+ name: textboxes
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: 0.0.1
82
+ type: :runtime
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: 0.0.1
89
+ description: ''
90
+ email: hendrik@hoodie.de
91
+ executables: []
92
+ extensions: []
93
+ extra_rdoc_files: []
94
+ files:
95
+ - lib/PlumberProject.rb
96
+ - lib/luigi.rb
97
+ - lib/luigi/ShellSanitizer.rb
98
+ - lib/luigi/gitplumber.rb
99
+ - lib/luigi/version.rb
100
+ homepage: https://github.com/hoodie/luigi
101
+ licenses:
102
+ - GPL
103
+ metadata: {}
104
+ post_install_message:
105
+ rdoc_options: []
106
+ require_paths:
107
+ - lib
108
+ required_ruby_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '1.9'
113
+ required_rubygems_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ requirements: []
119
+ rubyforge_project:
120
+ rubygems_version: 2.2.2
121
+ signing_key:
122
+ specification_version: 4
123
+ summary: luigi - a plumber
124
+ test_files: []