docbook_files 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -3,14 +3,22 @@ source "http://rubygems.org"
3
3
  gem "libxml-ruby", :require => 'xml'
4
4
  gem "term-ansicolor"
5
5
  gem "wand"
6
- gem "json"
6
+ gem "zucker"
7
+ gem "json", :platforms => :ruby_18
8
+ gem "win32console", :platforms => :mingw
7
9
 
8
10
  group :development do
9
11
  gem "bones"
10
- gem 'turn'
11
12
  gem 'rspec'
12
13
  gem 'guard'
13
- gem 'rb-fsevent'
14
- gem 'growl_notify'
15
14
  gem 'guard-rspec'
16
15
  end
16
+ group :darwin do
17
+ gem 'rb-fsevent', :require => false
18
+ gem 'growl_notify', :require => false
19
+ end
20
+ group :linux do
21
+ gem 'rb-inotify', :require => false
22
+ gem 'libnotify', :require => false
23
+ end
24
+
data/Gemfile.lock CHANGED
@@ -1,12 +1,12 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- ansi (1.3.0)
5
4
  bones (3.7.1)
6
5
  little-plugger (>= 1.1.2)
7
6
  loquacious (>= 1.8.1)
8
7
  rake (>= 0.8.7)
9
8
  diff-lcs (1.1.3)
9
+ ffi (1.0.9)
10
10
  growl_notify (0.0.3)
11
11
  rb-appscript
12
12
  guard (0.8.4)
@@ -14,6 +14,7 @@ GEM
14
14
  guard-rspec (0.5.0)
15
15
  guard (>= 0.8.4)
16
16
  json (1.6.1)
17
+ libnotify (0.5.7)
17
18
  libxml-ruby (2.2.2)
18
19
  little-plugger (1.1.2)
19
20
  loquacious (1.9.0)
@@ -21,6 +22,8 @@ GEM
21
22
  rake (0.9.2)
22
23
  rb-appscript (0.6.1)
23
24
  rb-fsevent (0.4.3.1)
25
+ rb-inotify (0.8.8)
26
+ ffi (>= 0.5.0)
24
27
  rspec (2.6.0)
25
28
  rspec-core (~> 2.6.0)
26
29
  rspec-expectations (~> 2.6.0)
@@ -32,11 +35,10 @@ GEM
32
35
  safe_shell (1.0.1)
33
36
  term-ansicolor (1.0.7)
34
37
  thor (0.14.6)
35
- turn (0.8.3)
36
- ansi
37
38
  wand (0.4)
38
39
  mime-types
39
40
  safe_shell (~> 1.0.0)
41
+ zucker (11)
40
42
 
41
43
  PLATFORMS
42
44
  ruby
@@ -47,9 +49,12 @@ DEPENDENCIES
47
49
  guard
48
50
  guard-rspec
49
51
  json
52
+ libnotify
50
53
  libxml-ruby
51
54
  rb-fsevent
55
+ rb-inotify
52
56
  rspec
53
57
  term-ansicolor
54
- turn
55
58
  wand
59
+ win32console
60
+ zucker
data/History.txt CHANGED
@@ -1,3 +1,13 @@
1
+ == 0.5.0 / 2011-10-19
2
+
3
+ * A file can now manage multiple inclusions and/or references.
4
+ * The YAML and JSON output contains now two sections, hierarchy and details, just like the terminal output.
5
+ * The details contain new fields for multiple references: includes, included_by and references, referenced_by
6
+
7
+ * Minor changes
8
+ ** Removed JSON dependency. It is used when available.
9
+ ** Color support is now optional on Windows
10
+
1
11
  == 0.4.0 / 2011-10-14
2
12
 
3
13
  * Added JSON and YAML output formats
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2011 Rainer Volz
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ 'Software'), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -29,29 +29,41 @@ If you don't like the screen output or want to integrate docbook_file into a cer
29
29
 
30
30
  docbook_files --outputformat=yaml myproject.xml
31
31
 
32
- The result is printed to STDOUT. The structure returned is equivalent to the normal terminal output, except that you always get the details. The structure returned is an array, where each entry contains the following key-value pairs:
33
-
34
- * type - file type (main, inc-luded, or ref-erenced)
35
- * name - file name
36
- * full_name - path relative to the main file
37
- * level - the level in the file hierarchy, starting with 0
38
- * parent - parent file that included or referenced this file
39
- * status - error status: 0 = ok, 1 = file not found, 2 = processing error (see error_string)
40
- * error_string - contains an error message, if status > 0
41
- * namespace - XML namespace, if applicable
42
- * version - XML version attribute, of applicable
43
- * docbook - true for DocBook 5 files, else false
44
- * tag - start tag for XML files (chapter, book, article ...)
45
- * ts - file modification time
46
- * size - fiel size in byte
47
- * checksum - SHA1 checksum
48
- * mime - MIME type
49
-
32
+ The result is printed to STDOUT. The structure returned is equivalent to the normal terminal output, except that you always get the details.
33
+
34
+ * hierarchy - an array of entries for each step in the file hierarchy
35
+ ** type - file type (main, inc-luded, or ref-erenced)
36
+ ** name - file name
37
+ ** path - path relative to the main file
38
+ ** status - error status: 0 = ok, 1 = file not found, 2 = processing error (see error_string)
39
+ ** size - file size in bytes
40
+ ** level - the level in the file hierarchy, starting with 0
41
+
42
+ * details - an array of entries for each file used in the hierarchy
43
+ ** name - file name
44
+ ** path - path relative to the main file
45
+ ** status - error status: 0 = ok, 1 = file not found, 2 = processing error (see error_string)
46
+ ** error_string - contains an error message, if status > 0
47
+ ** namespace - XML namespace, if applicable
48
+ ** version - XML version attribute, if applicable
49
+ ** docbook - true for DocBook 5 files, else false
50
+ ** tag - start tag for XML files (chapter, book, article ...)
51
+ ** ts - file modification time
52
+ ** size - file size in byte
53
+ ** checksum - SHA1 checksum
54
+ ** mime - MIME type
55
+ ** includes - files that are included by this file, an array of file names
56
+ ** included_by - files that include this file, an array of file names
57
+ ** references - files that are referenced by this file, an array of file names
58
+ ** referenced_by - files that reference this file, an array of file names
59
+
50
60
 
51
61
  Requirements
52
62
  ------------
53
63
 
54
64
  * libxml2
65
+ * json (optional, if you want JSON output on Ruby 1.8)
66
+ * win32console (optional, if you want color support on MS Windows)
55
67
 
56
68
  Install
57
69
  -------
data/Rakefile CHANGED
@@ -21,5 +21,19 @@ Bones {
21
21
  depend_on 'libxml-ruby'
22
22
  depend_on 'term-ansicolor'
23
23
  depend_on 'wand'
24
- depend_on 'json'
24
+ depend_on 'zucker'
25
+ depend_on 'rspec', :development => true
26
+ gem.extras[:license] = 'MIT'
27
+ gem.extras[:post_install_message] = <<-POST_INSTALL_MSG
28
+
29
+ Please note:
30
+
31
+ - docbook_files uses color to mark problematic files.
32
+ On Windows, you should additionally install the gem 'win32console'
33
+ to enable color output in the terminal.
34
+
35
+ - JSON output is optional for Ruby 1.8. Please install the gem 'json'
36
+ if you are running Ruby 1.8 and want JSON output.
37
+
38
+ POST_INSTALL_MSG
25
39
  }
@@ -2,21 +2,48 @@
2
2
 
3
3
  require 'optparse'
4
4
  require 'yaml'
5
- require 'json'
6
- require 'term/ansicolor'
5
+ require 'zucker/env'
7
6
 
8
- class String
9
- include Term::ANSIColor
7
+ # Windows (RubyInstaller) needs the additional gem.
8
+ # If not present create dummies for the color routines.
9
+ if OS.windows?
10
+ begin
11
+ require 'win32console'
12
+ require 'term/ansicolor'
13
+ class String
14
+ include Term::ANSIColor
15
+ end
16
+ rescue LoadError
17
+ class String
18
+ def red; self; end
19
+ def green; self; end
20
+ def magenta; self; end
21
+ def bold; self; end
22
+ end
23
+ end
24
+ else
25
+ require 'term/ansicolor'
26
+ class String
27
+ include Term::ANSIColor
28
+ end
10
29
  end
11
30
 
12
31
  module DocbookFiles
13
32
 
14
33
  # Create a new instance of App, and run the +docbook_files+ application given
15
- # the command line _args_.
34
+ # the command line _args_. Check also for JSON availability.
16
35
  #
17
36
  def self.run( args = nil )
18
37
  args ||= ARGV.dup.map! { |v| v.dup }
19
- ::DocbookFiles::App.new.run args
38
+ opts = {}
39
+ # For Windows and/or Ruby 1.8
40
+ begin
41
+ require 'json'
42
+ opts[:json_available] = true
43
+ rescue LoadError
44
+ opts[:json_available] = false
45
+ end
46
+ ::DocbookFiles::App.new(opts).run args
20
47
  end
21
48
 
22
49
  ##
@@ -28,6 +55,14 @@ module DocbookFiles
28
55
  # * 2 - processing error
29
56
  #
30
57
  class App
58
+
59
+ # Replacement for empty values
60
+ EMPTYVAL = '-'
61
+
62
+ # Replacement for monstrously large files sizes
63
+ XXL_SIZE = "XXL"
64
+
65
+ # Help banner
31
66
  @@banner = <<EOB
32
67
  docbook_files, Version #{DocbookFiles::VERSION}
33
68
 
@@ -37,6 +72,7 @@ Files with problems (not found, invalid ...) are marked red.
37
72
  Usage: docbook_files [options] <DOCBOOK-FILE>
38
73
  EOB
39
74
 
75
+ # Initialize options and reset the FileData storage
40
76
  def initialize(opts = {})
41
77
  opts[:stdout] ||= $stdout
42
78
  opts[:stderr] ||= $stderr
@@ -45,22 +81,28 @@ EOB
45
81
  @stderr = opts[:stderr]
46
82
  @opts[:output_format] ||= :screen
47
83
  @opts[:details] ||= false
48
- @props = [:name, :full_name, :namespace, :docbook,
49
- :version, :tag, :parent, :status, :ts, :size, :checksum, :mime, :error_string]
84
+ @opts[:json_available] ||= opts[:json_available]
85
+ @props = [:name, :path, :status, :size]
86
+ FileData.reset()
50
87
  end
51
88
 
52
89
  def run(args)
53
90
  opts = OptionParser.new
54
91
  opts.on('--details','List file details') {|val| @opts[:details] = true}
55
- opts.on('--outputformat=yaml|json',['json','yaml'],
92
+ opts.on('--outputformat=yaml|json',['yaml','json'],
56
93
  'Return the result in YAML or JSON format') {|format|
57
94
  case
58
95
  when format == 'yaml'
59
96
  @opts[:output_format] = :yaml
60
97
  when format == 'json'
61
- @opts[:output_format] = :json
98
+ if @opts[:json_available]
99
+ @opts[:output_format] = :json
100
+ else
101
+ @stderr.puts "Error: JSON not available. Please install the json gem first."
102
+ exit 1
103
+ end
62
104
  else
63
- @stderr.puts "Warning: Unknown output format #{format}. Using screen output.".orange
105
+ @stderr.puts "Error: Unknown output format #{format}."
64
106
  end
65
107
  }
66
108
  opts.banner = @@banner
@@ -83,6 +125,7 @@ EOB
83
125
  begin
84
126
  dbf = DocbookFiles::Docbook.new(rest[0])
85
127
  table = dbf.list_as_table(@props)
128
+ files = FileData.files
86
129
  rescue => exc
87
130
  @stderr.puts "Something unexpected happend while docbook_files was running ..."
88
131
  @stderr.puts exc.inspect.red
@@ -91,27 +134,29 @@ EOB
91
134
  unless table.nil?
92
135
  case @opts[:output_format]
93
136
  when :json
94
- mpath = table[0][:full_name]
95
- ntable = table.map{|t|
96
- t[:full_name] = relative2main(t[:full_name], mpath)
97
- t
98
- }
99
- @stdout.puts ntable.to_json
137
+ out = {:hierarchy => table, :details => files2table(files)}
138
+ @stdout.puts out.to_json
100
139
  when :yaml
101
- mpath = table[0][:full_name]
102
- ntable = table.map{|t|
103
- t[:full_name] = relative2main(t[:full_name], mpath)
104
- t
105
- }
106
- YAML.dump(ntable,@stdout)
140
+ out = {:hierarchy => table, :details => files2table(files)}
141
+ YAML.dump(out,@stdout)
107
142
  else
108
- output(table)
143
+ output_hierarchy(table)
144
+ output_details(files) if @opts[:details]
109
145
  end
110
146
  end
111
147
  end
112
148
 
113
- # Terminal output to @stdout
114
- def output(table)
149
+ # Transform the files into something YAML/JSON can handle
150
+ def files2table(files)
151
+ files.map { |f|
152
+ f.to_hash([:name, :path, :status, :error_string, :namespace,
153
+ :version, :docbook, :tag, :ts, :size, :checksum,
154
+ :mime, :includes, :included_by, :references, :referenced_by])
155
+ }
156
+ end
157
+
158
+ # Terminal output for file hierarchy
159
+ def output_hierarchy(table)
115
160
  output_string = "%3d %-60s %4s %10s"
116
161
  @stdout.puts
117
162
  @stdout.puts 'File Hierarchy'.bold
@@ -122,7 +167,7 @@ EOB
122
167
  sum_xml_err = 0
123
168
  table.each do |t|
124
169
  output = output_string % [t[:level],
125
- format_name(t[:level],t[:full_name],table[0][:full_name]),
170
+ format_name(t[:level],t[:path]),
126
171
  t[:type].to_s,
127
172
  format_size(t[:size])]
128
173
  sum_size += t[:size]
@@ -145,36 +190,44 @@ EOB
145
190
  summary += " #{sum_xml_err} file(s) with errors.".red
146
191
  end
147
192
  @stdout.puts summary
148
- if @opts[:details]
149
- @stdout.puts
150
- @stdout.puts "Details".bold
151
- table.each do |t|
152
- fname = format_name(0,t[:full_name],table[0][:full_name])
153
- @stdout.puts "File: %s" % [((t[:status] == FileData::STATUS_OK) ? fname : fname.red)]
154
- if (t[:type] == FileData::TYPE_MAIN)
155
- @stdout.puts "Main file"
156
- elsif (t[:type] == FileData::TYPE_INCLUDE)
157
- @stdout.puts "Included by: %s" % [t[:parent]]
193
+ end
194
+
195
+ # Print the FileData representation to the terminal
196
+ def output_details(files)
197
+ @stdout.puts
198
+ @stdout.puts "Details".bold
199
+ files.each do |t|
200
+ fname = t.path
201
+ @stdout.puts "File: %s" % [((t.status == FileData::STATUS_OK) ? fname : fname.red)]
202
+ @stdout.puts "Includes: %s" % [format_fds(t.includes)] unless t.includes.empty?
203
+ @stdout.puts "Included by: %s" % [format_fds(t.included_by)] unless t.included_by.empty?
204
+ @stdout.puts "References: %s" % [format_fds(t.references)] unless t.references.empty?
205
+ @stdout.puts "Referenced by: %s" % [format_fds(t.referenced_by)] unless t.referenced_by.empty?
206
+ unless t.status == FileData::STATUS_NOT_FOUND
207
+ # show that part only if file exists
208
+ @stdout.puts "Size: %s (%d)" % [format_size(t.size),t.size]
209
+ if (t.docbook)
210
+ @stdout.puts "Type: DocBook, Version #{t.version}, Tag: #{t.tag}"
158
211
  else
159
- @stdout.puts "Referenced by: %s" % [t[:parent]]
160
- end
161
- unless t[:status] == FileData::STATUS_NOT_FOUND
162
- # show that part only if file exists
163
- @stdout.puts "Size: %s (%d)" % [format_size(t[:size]),t[:size]]
164
- if (t[:docbook])
165
- @stdout.puts "Type: DocBook, Version #{t[:version]}, Tag: #{t[:tag]}"
166
- else
167
- @stdout.puts "MIME: #{val_s(t[:mime])}"
168
- end
169
- @stdout.puts "Timestamp: %s" % [t[:ts]]
170
- @stdout.puts "Checksum: %s" % [t[:checksum]]
212
+ @stdout.puts "MIME: #{val_s(t.mime)}"
171
213
  end
172
- @stdout.puts "Error: %s" % [t[:error_string].to_s.red] unless (t[:error_string].nil?)
173
- @stdout.puts
214
+ @stdout.puts "Timestamp: %s" % [t.ts]
215
+ @stdout.puts "SHA1: %s" % [t.checksum]
174
216
  end
217
+ @stdout.puts "Error: %s" % [t.error_string.to_s.red] unless (t.error_string.nil?)
218
+ @stdout.puts
175
219
  end
176
220
  end
177
221
 
222
+
223
+ # Format a list of FileDatas
224
+ def format_fds(fds)
225
+ if (fds.nil? || fds.empty?)
226
+ EMPTYVAL
227
+ else
228
+ fds.map {|p| p.path}.join ','
229
+ end
230
+ end
178
231
 
179
232
  # Format the filename to indicate the level in the hierarchy.
180
233
  # Indentation = two spaces per level.
@@ -183,9 +236,8 @@ EOB
183
236
  # relative part of the path is shown, else the full path.
184
237
  # If the resulting string is too long for display it is shortened.
185
238
  #
186
- def format_name(level, full_name, main_name)
187
- nname = relative2main(full_name, main_name)
188
- lnname = ' '*level+nname
239
+ def format_name(level, full_name)
240
+ lnname = ' '*level+full_name
189
241
  if (lnname.length > 60)
190
242
  lnname[0..3]+'...'+lnname[-54,lnname.length-1]
191
243
  else
@@ -193,18 +245,6 @@ EOB
193
245
  end
194
246
  end
195
247
 
196
- # Try to find the path of _file_name_ that is relative to the _main file_.
197
- # If there is no common part return the _file_name_.
198
- def relative2main(file_name,main_name)
199
- main_dir = File.dirname(main_name)
200
- md = file_name.match("^#{main_dir}/")
201
- if md.nil?
202
- file_name
203
- else
204
- md.post_match
205
- end
206
- end
207
-
208
248
  # :stopdoc:
209
249
  KB = 1024
210
250
  MB = 1048576
@@ -217,7 +257,7 @@ EOB
217
257
  # Sizes >= 1PB will return 'XXL'
218
258
  def format_size(sz)
219
259
  if (emptyval?(sz))
220
- '-'
260
+ EMPTYVAL
221
261
  else
222
262
  case
223
263
  when sz < KB then "#{sz}B"
@@ -226,18 +266,14 @@ EOB
226
266
  when sz >= GB && sz < TB then "#{sz/GB}GB"
227
267
  when sz >= TB && sz < PB then "#{sz/TB}TB"
228
268
  else
229
- "XXL"
269
+ XXL_SIZE
230
270
  end
231
271
  end
232
272
  end
233
273
 
234
- # Return a string for the value, '<>' if there is none.
274
+ # Return a string for the value, '-' if there is none.
235
275
  def val_s(val)
236
- if emptyval?(val)
237
- '-'
238
- else
239
- val.to_s
240
- end
276
+ emptyval?(val) ? EMPTYVAL : val.to_s
241
277
  end
242
278
 
243
279
  # Check whether the value is nil or empty.
@@ -245,12 +281,9 @@ EOB
245
281
  if val.nil?
246
282
  true
247
283
  else
248
- if (val.class == String)
249
- val.empty?
250
- else
251
- false
252
- end
284
+ (val.class == String) ? val.empty? : false
253
285
  end
254
286
  end
287
+
255
288
  end
256
289
  end