luigi 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/PlumberProject.rb +34 -0
- data/lib/luigi.rb +396 -0
- data/lib/luigi/ShellSanitizer.rb +41 -0
- data/lib/luigi/gitplumber.rb +151 -0
- data/lib/luigi/version.rb +3 -0
- metadata +124 -0
checksums.yaml
ADDED
@@ -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
|
data/lib/luigi.rb
ADDED
@@ -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
|
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: []
|