luigi 1.0.0 → 1.1.0
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.
- checksums.yaml +4 -4
- data/lib/luigi.rb +95 -205
- data/lib/luigi/ShellSanitizer.rb +1 -1
- data/lib/luigi/version.rb +1 -1
- data/lib/luigi_internal.rb +184 -0
- data/lib/luigi_project.rb +90 -0
- data/lib/luigi_projects_list.rb +36 -0
- metadata +34 -4
- data/lib/PlumberProject.rb +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 361fa53ceb381c724adade28d8810a8395751c24
|
4
|
+
data.tar.gz: 10505b06c45cf12b465e8d75af6e013ebebafb7b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dcdfd3563d55f51a638abcf1b1c0afdd9ff7865356f6f990aa1c9ab8ecd02c0a3a10d6534fe2dd5f4addf8b9b0ad81991af3e4fff8dfe39344e02c8056c7438c
|
7
|
+
data.tar.gz: b90f219db6687ca7919d5c5a9f128f99efe1820f53f282b1889d7c42e71766b285d91dcf626e01456ac79e5dd8ed309365edf9c5e7c7e216c8936388d4b61f32
|
data/lib/luigi.rb
CHANGED
@@ -1,63 +1,39 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require 'fileutils'
|
3
3
|
require 'logger'
|
4
|
+
require 'hashr'
|
4
5
|
|
6
|
+
require File.join File.dirname(__FILE__), "luigi_internal"
|
7
|
+
require File.join File.dirname(__FILE__), "luigi_project"
|
8
|
+
require File.join File.dirname(__FILE__), "luigi_projects_list"
|
5
9
|
require File.join File.dirname(__FILE__), "luigi/gitplumber"
|
6
10
|
require File.join File.dirname(__FILE__), "luigi/ShellSanitizer"
|
7
11
|
|
8
12
|
## requires a project_class
|
9
13
|
# project_class must implement: name, date
|
10
|
-
|
14
|
+
# TODO
|
15
|
+
class Luigi < LuigiInternal
|
11
16
|
|
12
17
|
attr_reader :dirs,
|
13
|
-
:opened_projects,
|
14
18
|
:project_paths,
|
15
|
-
:opened_paths,
|
16
19
|
:opened_sort,
|
17
|
-
:
|
20
|
+
:templates,
|
21
|
+
:settings
|
18
22
|
|
19
|
-
attr_writer :project_class
|
23
|
+
#attr_writer :project_class
|
20
24
|
|
21
25
|
include GitPlumber
|
22
26
|
|
23
|
-
|
24
27
|
def initialize(settings, project_class = nil)
|
25
|
-
@settings = settings
|
26
|
-
@opened_projects = []
|
28
|
+
@settings = Hashr.new settings
|
27
29
|
@project_class = project_class
|
28
30
|
@file_extension = settings['project_file_extension']
|
31
|
+
@file_extension ||= ".yml"
|
29
32
|
@using_git = settings['use_git']
|
30
33
|
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
34
|
+
init_logger()
|
35
|
+
init_dirs()
|
36
|
+
load_templates()
|
61
37
|
end
|
62
38
|
|
63
39
|
##
|
@@ -66,67 +42,43 @@ class Luigi
|
|
66
42
|
def create_dir(dir)
|
67
43
|
unless check_dir(dir)
|
68
44
|
if dir == :storage or check_dir :storage
|
69
|
-
FileUtils.mkdir
|
45
|
+
FileUtils.mkdir @dirs[dir]
|
70
46
|
@logger.info "Created \"#{dir.to_s}\" Directory (#{@dirs[dir]})"
|
71
47
|
return true
|
72
48
|
end
|
73
|
-
@logger.error "
|
49
|
+
@logger.error "No storage dir."
|
74
50
|
end
|
75
51
|
return false
|
76
52
|
end
|
77
53
|
|
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
54
|
|
98
55
|
##
|
99
56
|
# creates new project_dir and project_file
|
100
57
|
# returns project object
|
101
|
-
def new_project(_name)
|
58
|
+
def new_project(_name, template = :default, data = {})
|
102
59
|
_name = ShellSanitizer.process _name
|
103
60
|
name = ShellSanitizer.clean_path _name
|
104
61
|
|
105
|
-
|
106
|
-
settings = @settings
|
107
|
-
defaults = @settings['defaults']
|
108
|
-
defaults = {}
|
109
|
-
|
110
|
-
filename = @dirs[:template]
|
62
|
+
load_templates()
|
111
63
|
|
112
|
-
|
113
|
-
|
114
|
-
|
64
|
+
template_path = @templates[template]
|
65
|
+
raise "No such template." unless @templates.keys.include? template
|
66
|
+
raise "Template file does not exists." unless File.exists? template_path
|
67
|
+
data[:project_name] = name
|
115
68
|
|
116
|
-
#
|
69
|
+
# create project folder
|
117
70
|
folder = _new_project_folder(name)
|
71
|
+
|
118
72
|
if folder
|
119
73
|
target = File.join folder, name+@file_extension
|
74
|
+
# project will load template and
|
75
|
+
project = @project_class.new({
|
76
|
+
:path => target,
|
77
|
+
:settings => @settings,
|
78
|
+
:template_path => template_path,
|
79
|
+
:data => data }
|
80
|
+
)
|
120
81
|
|
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
82
|
else
|
131
83
|
return false
|
132
84
|
end
|
@@ -140,105 +92,81 @@ class Luigi
|
|
140
92
|
# output of (foobar must be comparable)
|
141
93
|
#
|
142
94
|
# untested
|
143
|
-
def
|
95
|
+
def _open_projects(dir=:working, sort = :date, year=Date.today.year)
|
96
|
+
#TODO perhaps cache projects
|
144
97
|
if dir==:all
|
145
|
-
|
98
|
+
opened_paths = list_project_files_all
|
146
99
|
else
|
147
|
-
|
100
|
+
opened_paths = list_project_files dir, year
|
148
101
|
end
|
149
102
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
project
|
154
|
-
if project.STATUS == :ok
|
155
|
-
@opened_projects = @opened_projects + [ project ]
|
156
|
-
end
|
157
|
-
@project_paths[project.name] = path
|
103
|
+
projects = []
|
104
|
+
opened_paths.each {|path|
|
105
|
+
project = open_project_from_path(path)
|
106
|
+
projects << project if project.status == :ok
|
158
107
|
}
|
159
|
-
sort_projects(sort)
|
160
|
-
return
|
108
|
+
projects = LuigiProjectsList.new sort_projects(projects, sort)
|
109
|
+
return projects
|
161
110
|
end
|
162
111
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
112
|
+
# sorts array of project_class
|
113
|
+
def sort_projects(projects, sort = :date)
|
114
|
+
raise "sort must be a Symbol, not a #{sort.class} (#{sort})" unless sort.class == Symbol
|
115
|
+
if @project_class.method_defined? sort
|
116
|
+
projects.sort_by! {|project| project.method(sort).call}
|
117
|
+
return projects
|
118
|
+
else raise "#{@project_class} does not implement #{sort}()"
|
119
|
+
end
|
120
|
+
return false
|
172
121
|
end
|
173
122
|
|
174
123
|
|
175
|
-
##
|
176
|
-
# produces an Array of @project_class objects
|
177
|
-
#
|
178
|
-
# untested
|
179
124
|
def open_projects_all(sort = :date)
|
180
|
-
|
181
|
-
open_projects :all, year=nil, sort
|
125
|
+
_open_projects :all , sort, Date.today.year
|
182
126
|
end
|
183
127
|
|
184
|
-
def
|
185
|
-
|
128
|
+
def open_projects_working(sort = :date)
|
129
|
+
_open_projects :working, sort, Date.today.year
|
186
130
|
end
|
187
131
|
|
188
|
-
def
|
189
|
-
|
190
|
-
return @project_paths[p.name] unless p.nil?
|
191
|
-
@logger.error "there is no project #{name}"
|
192
|
-
return false
|
132
|
+
def open_projects_archive(year,sort = :date)
|
133
|
+
_open_projects :archive, sort, year
|
193
134
|
end
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
135
|
+
|
136
|
+
|
137
|
+
# returns project path
|
138
|
+
def lookup_path_by_name(name, dir = :working, year = Date.today.year)
|
139
|
+
projects = map_project_files(dir, year)
|
140
|
+
matches = projects.keys.select{|k| k.downcase.include? name.downcase}
|
141
|
+
return matches.each{|match|
|
142
|
+
projects[match]
|
143
|
+
}
|
144
|
+
end
|
145
|
+
|
146
|
+
# returns opened project
|
147
|
+
# needs to open projects in order to sort
|
148
|
+
def lookup_by_num(num, dir= :working, sort=:date, year= Date.today.year)
|
149
|
+
projects = _open_projects(dir, sort, year)
|
150
|
+
projects.each{|p| puts "#{p.date}: #{p.name}" }
|
151
|
+
#num = num.to_i - 1 if num.class == String and num =~ /^\d*$/
|
152
|
+
num = num.to_i - 1
|
153
|
+
project = projects[num]
|
154
|
+
@logger.error "there is no project ##{num+1}" if project.nil?
|
208
155
|
return project
|
209
156
|
end
|
210
157
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
158
|
+
# opens a project from name
|
159
|
+
# TODO implement archive lookup
|
160
|
+
def open_project_from_name project_name
|
161
|
+
return false unless project_name.class == String
|
162
|
+
project_name = ShellSanitizer.process project_name
|
163
|
+
project_name = ShellSanitizer.clean_path project_name
|
164
|
+
path = get_project_file_path project_name
|
165
|
+
return open_project_from_path path if path
|
166
|
+
@logger.error "Patherror: #{project_name}"
|
219
167
|
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
168
|
|
169
|
+
|
242
170
|
##
|
243
171
|
# Path to project folder
|
244
172
|
# If the folder exists
|
@@ -261,67 +189,32 @@ class Luigi
|
|
261
189
|
def list_project_names(dir = :working, year=Date.today.year)
|
262
190
|
return unless check_dir(dir)
|
263
191
|
if dir == :working
|
264
|
-
|
265
|
-
names = paths.map {|path| File.basename path }
|
192
|
+
return map_project_files_working().keys()
|
266
193
|
elsif dir == :archive
|
267
|
-
|
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
|
194
|
+
return map_project_files_archive(year).keys()
|
273
195
|
else
|
274
196
|
@logger.error "unknown path #{dir}"
|
275
197
|
end
|
276
198
|
end
|
277
199
|
|
278
200
|
##
|
279
|
-
# list projects
|
280
201
|
# lists project files
|
281
|
-
|
282
|
-
def list_projects(dir = :working, year=Date.today.year)
|
202
|
+
def list_project_files(dir = :working, year=Date.today.year)
|
283
203
|
return unless check_dir(dir)
|
284
204
|
if dir == :working
|
285
|
-
|
286
|
-
paths = folders.map {|path| get_project_file_path File.basename path }
|
205
|
+
return list_project_files_working()
|
287
206
|
elsif dir == :archive
|
288
|
-
|
289
|
-
paths = folders.map {|path| get_project_file_path (File.basename path), :archive, year }
|
207
|
+
return list_project_files_archive(year)
|
290
208
|
else
|
291
209
|
@logger.error "unknown path #{dir}"
|
210
|
+
return []
|
292
211
|
end
|
293
|
-
|
294
|
-
puts "WARNING! one folder is not correct" if paths.include? false
|
295
|
-
paths.keep_if{|v| v}
|
296
212
|
end
|
297
213
|
|
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
214
|
|
319
|
-
|
320
|
-
end
|
321
|
-
|
322
|
-
def filter_by hash
|
215
|
+
def filter_by projects, hash
|
323
216
|
filtered_projets = []
|
324
|
-
|
217
|
+
projects.each{|project|
|
325
218
|
hash.each{|key,value|
|
326
219
|
field = project.data(key)
|
327
220
|
if field and field.to_s.downcase.include? value
|
@@ -338,7 +231,6 @@ class Luigi
|
|
338
231
|
# @name
|
339
232
|
## Luigi.archive_project should use ShellSanitizer
|
340
233
|
def archive_project(project, year = nil, prefix = '')
|
341
|
-
project = open_project project
|
342
234
|
return false unless project.class == @project_class
|
343
235
|
|
344
236
|
year ||= project.date.year
|
@@ -369,17 +261,15 @@ class Luigi
|
|
369
261
|
##
|
370
262
|
# Move to archive directory
|
371
263
|
def unarchive_project(project, year = Date.today.year)
|
372
|
-
project = open_project project
|
373
264
|
return false unless project.class == @project_class
|
374
265
|
|
375
|
-
name = project.name
|
376
266
|
path = project.path
|
377
267
|
cleaned_name = File.basename(path,@file_extension)
|
378
|
-
source = get_project_folder name, :archive, year
|
268
|
+
source = get_project_folder project.name, :archive, year
|
379
269
|
target = File.join @dirs[:working], cleaned_name
|
270
|
+
return false unless source
|
380
271
|
|
381
272
|
@logger.info "moving #{source} to #{target}"
|
382
|
-
return false unless source
|
383
273
|
|
384
274
|
unless get_project_folder cleaned_name
|
385
275
|
FileUtils.mv source, target
|
data/lib/luigi/ShellSanitizer.rb
CHANGED
@@ -22,7 +22,7 @@ class ShellSanitizer
|
|
22
22
|
return string
|
23
23
|
end
|
24
24
|
|
25
|
-
## TODO somebody find
|
25
|
+
## TODO somebody find me a gem that works and I'll replace this
|
26
26
|
def self.deumlautify(string)
|
27
27
|
REPLACE_HASH.each{|k,v| string = string.gsub k, v }
|
28
28
|
string.each_char.to_a.keep_if {|c| c.ascii_only?}
|
data/lib/luigi/version.rb
CHANGED
@@ -0,0 +1,184 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'fileutils'
|
3
|
+
require 'logger'
|
4
|
+
require 'hashr'
|
5
|
+
|
6
|
+
require File.join File.dirname(__FILE__), "luigi/gitplumber"
|
7
|
+
require File.join File.dirname(__FILE__), "luigi/ShellSanitizer"
|
8
|
+
|
9
|
+
## requires a project_class
|
10
|
+
# project_class must implement: name, date, index
|
11
|
+
|
12
|
+
# implements everything not exposed to the outside
|
13
|
+
# TODO: make this all private
|
14
|
+
class LuigiInternal
|
15
|
+
def init_logger
|
16
|
+
@logger = Logger.new(STDERR)
|
17
|
+
@logger.level = Logger::ERROR
|
18
|
+
@logger.error "need a project_class" if @project_class.nil?
|
19
|
+
@logger.progname = "LUIGI"
|
20
|
+
end
|
21
|
+
|
22
|
+
def init_dirs
|
23
|
+
@dirs = {}
|
24
|
+
@dirs[:storage] = File.expand_path(File.join(@settings['path'], @settings['dirs']['storage']))
|
25
|
+
@dirs[:working] = File.join @dirs[:storage], @settings['dirs']['working']
|
26
|
+
@dirs[:archive] = File.join @dirs[:storage], @settings['dirs']['archive']
|
27
|
+
@dirs[:templates] = File.join @dirs[:storage], @settings['dirs']['templates']
|
28
|
+
end
|
29
|
+
|
30
|
+
##
|
31
|
+
# Checks the existens of one of the three basic dirs.
|
32
|
+
# dir can be either :storage, :working or :archive
|
33
|
+
# and also :templates
|
34
|
+
def check_dir(dir)
|
35
|
+
File.exists? @dirs[dir]
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
# Checks the existens of every thing required
|
40
|
+
def check_dirs
|
41
|
+
check_dir :storage and
|
42
|
+
check_dir :working and
|
43
|
+
check_dir :archive and
|
44
|
+
check_dir :templates
|
45
|
+
end
|
46
|
+
|
47
|
+
# read the templates directory and cache paths
|
48
|
+
def load_templates
|
49
|
+
return false unless check_dir :templates
|
50
|
+
#files = Dir.glob File.join @dirs[:templates] , ?*
|
51
|
+
files = Dir.glob File.join(@dirs[:templates], "*{#{@file_extension}.erb,#{@file_extension}}")
|
52
|
+
@templates = {}
|
53
|
+
files.each{|file|
|
54
|
+
name = File.basename file.split(?.)[0]
|
55
|
+
@templates[name.to_sym] = file
|
56
|
+
}
|
57
|
+
return true
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# creates new project_dir and project_file
|
62
|
+
def _new_project_folder(name)
|
63
|
+
unless check_dir(:working)
|
64
|
+
@logger.info(File.exists? @dirs[:working])
|
65
|
+
@logger.info "missing working directory!"
|
66
|
+
return false
|
67
|
+
end
|
68
|
+
|
69
|
+
# check of existing project with the same name
|
70
|
+
folder = get_project_folder(name, :working)
|
71
|
+
unless folder
|
72
|
+
FileUtils.mkdir File.join @dirs[:working], name
|
73
|
+
return get_project_folder(name, :working)
|
74
|
+
else
|
75
|
+
@logger.info "#{folder} already exists"
|
76
|
+
return false
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# derives path to project file from name
|
82
|
+
# there may only be one @file_extension file per project folder
|
83
|
+
#
|
84
|
+
# untested
|
85
|
+
def get_project_file_path(name, dir=:working, year=Date.today.year)
|
86
|
+
name = ShellSanitizer.process name
|
87
|
+
name = ShellSanitizer.clean_path name
|
88
|
+
|
89
|
+
folder = get_project_folder(name, dir, year)
|
90
|
+
if folder
|
91
|
+
files = Dir.glob File.join folder, "*#{@file_extension}"
|
92
|
+
warn "ambiguous amount of #{@file_extension} files in #{folder}" if files.length > 1
|
93
|
+
warn "no #{@file_extension} files in #{folder}" if files.length < 1
|
94
|
+
return files[0]
|
95
|
+
end
|
96
|
+
@logger.info "NO FOLDER get_project_folder(name = #{name}, dir = #{dir}, year = #{year})"
|
97
|
+
return false
|
98
|
+
end
|
99
|
+
|
100
|
+
# opens a project from path
|
101
|
+
def open_project_from_path path
|
102
|
+
project = @project_class.new({
|
103
|
+
:path => path,
|
104
|
+
:settings => @settings})
|
105
|
+
return project if project.class == @project_class
|
106
|
+
return false
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
|
111
|
+
|
112
|
+
##
|
113
|
+
# maps project names to files from working dir
|
114
|
+
def map_project_files_working()
|
115
|
+
map = {}
|
116
|
+
folders = Dir.glob File.join @dirs[:working], "/*"
|
117
|
+
paths = folders.map {|path| get_project_file_path File.basename path }
|
118
|
+
paths.select!{|path| path} # removing faulty paths
|
119
|
+
paths.each {|path| map[File.basename path, @file_extension] = path }
|
120
|
+
return map
|
121
|
+
end
|
122
|
+
|
123
|
+
##
|
124
|
+
# maps project names to files from working dir
|
125
|
+
def map_project_files_archive(year = Date.today.year)
|
126
|
+
map={}
|
127
|
+
paths = Dir.glob File.join @dirs[:archive], year.to_s, "/*"
|
128
|
+
names = paths.map {|path|
|
129
|
+
file_path = get_project_file_path (File.basename path), :archive, year
|
130
|
+
name = File.basename file_path, @file_extension
|
131
|
+
map[name] = file_path
|
132
|
+
}
|
133
|
+
return map
|
134
|
+
end
|
135
|
+
|
136
|
+
##
|
137
|
+
# maps project names to files
|
138
|
+
def map_project_files(dir = :working, year=Date.today.year)
|
139
|
+
return unless check_dir(dir)
|
140
|
+
if dir == :working
|
141
|
+
return map_project_files_working()
|
142
|
+
elsif dir == :archive
|
143
|
+
return map_project_files_archive year
|
144
|
+
else
|
145
|
+
@logger.error "unknown path #{dir}"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
##
|
150
|
+
# returns map of years to archive folders
|
151
|
+
def map_archive_years
|
152
|
+
map = {}
|
153
|
+
Dir.glob(File.join @dirs[:archive], "/*").each{|path|
|
154
|
+
map[File.basename path] = path
|
155
|
+
}
|
156
|
+
return map
|
157
|
+
end
|
158
|
+
|
159
|
+
|
160
|
+
|
161
|
+
|
162
|
+
##
|
163
|
+
# lists project files from working directory
|
164
|
+
def list_project_files_working()
|
165
|
+
map_project_files_working.values
|
166
|
+
end
|
167
|
+
|
168
|
+
# lists project files from archive directory
|
169
|
+
def list_project_files_archive(year = Date.today.year)
|
170
|
+
map_project_files_archive(year).values
|
171
|
+
end
|
172
|
+
|
173
|
+
##
|
174
|
+
# list projects
|
175
|
+
# lists project files
|
176
|
+
def list_project_files_all
|
177
|
+
working = list_project_files_working
|
178
|
+
archive = []
|
179
|
+
map_archive_years.keys.each{|year|
|
180
|
+
archive += list_project_files_archive(year)
|
181
|
+
}
|
182
|
+
return ( archive + working )
|
183
|
+
end
|
184
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
|
5
|
+
class LuigiProject
|
6
|
+
|
7
|
+
attr_reader :status, :using_erb
|
8
|
+
|
9
|
+
# initializes the project
|
10
|
+
# opens project from :path.
|
11
|
+
# if :template_path is given it will create a fresh project from template first
|
12
|
+
# and store it in path
|
13
|
+
def initialize hash
|
14
|
+
@path = hash[:path]
|
15
|
+
@settings = hash[:settings]
|
16
|
+
@template_path = hash[:template_path]
|
17
|
+
@data = hash[:data]
|
18
|
+
@data ||= {}
|
19
|
+
|
20
|
+
@logger = Logger.new STDOUT
|
21
|
+
@logger.progname = "LuigiProject"
|
22
|
+
|
23
|
+
unless @template_path.nil?
|
24
|
+
create @template_path
|
25
|
+
end
|
26
|
+
|
27
|
+
open @path
|
28
|
+
end
|
29
|
+
|
30
|
+
# attempting to fill erb if template ends in .erb
|
31
|
+
# filling with @settings[:defaults]
|
32
|
+
def create(template_path)
|
33
|
+
@using_erb = File.extname(@template_path) == ".erb"
|
34
|
+
|
35
|
+
template_basename = File.basename @template_path
|
36
|
+
template_basename = File.basename @template_path, ".erb" if using_erb
|
37
|
+
|
38
|
+
raise "Project file extension error!" unless File.extname(@path) == @settings['project_file_extension']
|
39
|
+
raise "Template file extension error!" unless File.extname(template_basename) == @settings['project_file_extension']
|
40
|
+
raise "Template does not exist!" unless File.exists? @template_path
|
41
|
+
raise "Project file already exists! (#{@path})" if File.exists? @path
|
42
|
+
|
43
|
+
if @using_erb
|
44
|
+
create_with_erb(template_path)
|
45
|
+
else
|
46
|
+
FileUtils.cp @template_path, @path
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def fill_template
|
51
|
+
return binding
|
52
|
+
end
|
53
|
+
|
54
|
+
def create_with_erb template_path
|
55
|
+
engine=ERB.new(File.read(template_path),nil,'<>')
|
56
|
+
b = fill_template()
|
57
|
+
result = engine.result(b)
|
58
|
+
|
59
|
+
file = File.new @path, "w"
|
60
|
+
result.lines.each do |line|
|
61
|
+
file.write line
|
62
|
+
end
|
63
|
+
file.close
|
64
|
+
end
|
65
|
+
|
66
|
+
# opens project form path
|
67
|
+
def open path
|
68
|
+
@path = path
|
69
|
+
end
|
70
|
+
|
71
|
+
# returns path
|
72
|
+
def path
|
73
|
+
@path
|
74
|
+
end
|
75
|
+
|
76
|
+
# returns name
|
77
|
+
def name
|
78
|
+
File.basename @path, ".yml"
|
79
|
+
end
|
80
|
+
|
81
|
+
# returns index
|
82
|
+
def index
|
83
|
+
123
|
84
|
+
end
|
85
|
+
|
86
|
+
def date
|
87
|
+
return Date.today
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'fileutils'
|
3
|
+
require 'logger'
|
4
|
+
require 'hashr'
|
5
|
+
|
6
|
+
require File.join File.dirname(__FILE__), "luigi"
|
7
|
+
require File.join File.dirname(__FILE__), "luigi_project"
|
8
|
+
|
9
|
+
class LuigiProjectsList < Array
|
10
|
+
|
11
|
+
|
12
|
+
def lookup_by_anything thing, value
|
13
|
+
project_class = self[0].class
|
14
|
+
raise "#{project_class} does not implement #{thing.to_s}()" unless project_class.instance_methods.include? thing
|
15
|
+
raise "#{thing}" unless [:name, :date, :index].include? thing
|
16
|
+
|
17
|
+
selection = self.map{|project|
|
18
|
+
project if project.method(thing).call.to_s.downcase.include? value.to_s.downcase
|
19
|
+
}
|
20
|
+
selection.select{|p|p}
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
def lookup_by_index index
|
25
|
+
self.lookup_by_anything :index, index
|
26
|
+
end
|
27
|
+
|
28
|
+
def lookup_by_date date
|
29
|
+
self.lookup_by_anything :date, date
|
30
|
+
end
|
31
|
+
|
32
|
+
def lookup_by_name name
|
33
|
+
self.lookup_by_anything :name, name
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: luigi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hendrik Sollich
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-11-
|
11
|
+
date: 2014-11-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -77,6 +77,9 @@ dependencies:
|
|
77
77
|
requirement: !ruby/object:Gem::Requirement
|
78
78
|
requirements:
|
79
79
|
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0.0'
|
82
|
+
- - ">="
|
80
83
|
- !ruby/object:Gem::Version
|
81
84
|
version: 0.0.1
|
82
85
|
type: :runtime
|
@@ -84,19 +87,46 @@ dependencies:
|
|
84
87
|
version_requirements: !ruby/object:Gem::Requirement
|
85
88
|
requirements:
|
86
89
|
- - "~>"
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0.0'
|
92
|
+
- - ">="
|
87
93
|
- !ruby/object:Gem::Version
|
88
94
|
version: 0.0.1
|
89
|
-
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: hashr
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - "~>"
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0.0'
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: 0.0.22
|
105
|
+
type: :runtime
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - "~>"
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0.0'
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: 0.0.22
|
115
|
+
description: |-
|
116
|
+
A project manager that keeps track of a working directory, archive and template files.
|
117
|
+
Used in commandline tools like ascii-invoicer.
|
90
118
|
email: hendrik@hoodie.de
|
91
119
|
executables: []
|
92
120
|
extensions: []
|
93
121
|
extra_rdoc_files: []
|
94
122
|
files:
|
95
|
-
- lib/PlumberProject.rb
|
96
123
|
- lib/luigi.rb
|
97
124
|
- lib/luigi/ShellSanitizer.rb
|
98
125
|
- lib/luigi/gitplumber.rb
|
99
126
|
- lib/luigi/version.rb
|
127
|
+
- lib/luigi_internal.rb
|
128
|
+
- lib/luigi_project.rb
|
129
|
+
- lib/luigi_projects_list.rb
|
100
130
|
homepage: https://github.com/hoodie/luigi
|
101
131
|
licenses:
|
102
132
|
- GPL
|
data/lib/PlumberProject.rb
DELETED
@@ -1,34 +0,0 @@
|
|
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
|