luigi 1.0.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 +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: []
|