docurium 0.0.5 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/bin/cm CHANGED
@@ -6,7 +6,7 @@ require 'gli'
6
6
  require 'docurium'
7
7
  require 'docurium/cli'
8
8
 
9
- include GLI
9
+ include GLI::App
10
10
 
11
11
  version Docurium::Version
12
12
 
@@ -38,4 +38,4 @@ on_error do |exception|
38
38
  puts exception.backtrace
39
39
  end
40
40
 
41
- exit GLI.run(ARGV)
41
+ exit run(ARGV)
data/docurium.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  $:.push File.expand_path("../lib", __FILE__)
3
- require 'docurium'
3
+ require 'docurium/version'
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "docurium"
@@ -17,6 +17,9 @@ Gem::Specification.new do |s|
17
17
  s.add_dependency "version_sorter", "~>1.1.0"
18
18
  s.add_dependency "mustache", ">= 0.99.4"
19
19
  s.add_dependency "rocco", "= 0.7.0"
20
+ s.add_dependency "gli", "~>2.5"
21
+ s.add_dependency "rugged", "~>0.18.b1"
22
+ s.add_dependency "redcarpet", "~>2.2.2"
20
23
  s.add_development_dependency "bundler", "~>1.0"
21
24
 
22
25
  s.files = `git ls-files`.split("\n")
data/lib/docurium.rb CHANGED
@@ -2,12 +2,14 @@ require 'json'
2
2
  require 'tempfile'
3
3
  require 'version_sorter'
4
4
  require 'rocco'
5
+ require 'docurium/version'
5
6
  require 'docurium/layout'
7
+ require 'docurium/cparser'
6
8
  require 'pp'
9
+ require 'rugged'
10
+ require 'redcarpet'
7
11
 
8
12
  class Docurium
9
- Version = VERSION = '0.0.5'
10
-
11
13
  attr_accessor :branch, :output_dir, :data
12
14
 
13
15
  def initialize(config_file)
@@ -15,6 +17,8 @@ class Docurium
15
17
  raise "You need to specify a valid config file" if !valid_config(config_file)
16
18
  @sigs = {}
17
19
  @groups = {}
20
+ repo_path = Rugged::Repository.discover('.')
21
+ @repo = Rugged::Repository.new(repo_path)
18
22
  clear_data
19
23
  end
20
24
 
@@ -38,73 +42,68 @@ class Docurium
38
42
 
39
43
  def generate_docs
40
44
  out "* generating docs"
41
- outdir = mkdir_temp
42
- copy_site(outdir)
45
+ output_index = Rugged::Index.new
46
+ write_site(output_index)
43
47
  versions = get_versions
44
48
  versions << 'HEAD'
45
49
  versions.each do |version|
46
50
  out " - processing version #{version}"
47
- workdir = mkdir_temp
48
- Dir.chdir(workdir) do
49
- clear_data(version)
50
- checkout(version, workdir)
51
- parse_headers
52
- tally_sigs(version)
53
- end
51
+ index = @repo.index
52
+ index.clear
53
+ clear_data(version)
54
+ read_subtree(index, version, @data[:prefix])
55
+ parse_headers(index)
56
+ tally_sigs(version)
54
57
 
55
58
  tf = File.expand_path(File.join(File.dirname(__FILE__), 'docurium', 'layout.mustache'))
56
59
  if ex = option_version(version, 'examples')
57
- workdir = mkdir_temp
58
- Dir.chdir(workdir) do
59
- with_git_env(workdir) do
60
- `git rev-parse #{version}:#{ex} 2>&1` # check that it exists
61
- if $?.exitstatus == 0
62
- out " - processing examples for #{version}"
63
- `git read-tree #{version}:#{ex}`
64
- `git checkout-index -a`
65
-
66
- files = []
67
- Dir.glob("**/*.c") do |file|
68
- next if !File.file?(file)
69
- files << file
70
- end
71
- files.each do |file|
72
- out " # #{file}"
73
-
74
- # highlight, roccoize and link
75
- rocco = Rocco.new(file, files, {:language => 'c'})
76
- rocco_layout = Rocco::Layout.new(rocco, tf)
77
- rocco_layout.version = version
78
- rf = rocco_layout.render
79
-
80
- rf_path = File.basename(file).split('.')[0..-2].join('.') + '.html'
81
- rel_path = "ex/#{version}/#{rf_path}"
82
- rf_path = File.join(outdir, rel_path)
83
-
84
- # look for function names in the examples and link
85
- id_num = 0
86
- @data[:functions].each do |f, fdata|
87
- rf.gsub!(/#{f}([^\w])/) do |fmatch|
88
- extra = $1
89
- id_num += 1
90
- name = f + '-' + id_num.to_s
91
- # save data for cross-link
92
- @data[:functions][f][:examples] ||= {}
93
- @data[:functions][f][:examples][file] ||= []
94
- @data[:functions][f][:examples][file] << rel_path + '#' + name
95
- "<a name=\"#{name}\" href=\"../../##{version}/group/#{fdata[:group]}/#{f}\">#{f}</a>#{extra}"
96
- end
97
- end
98
-
99
- # write example to docs directory
100
- FileUtils.mkdir_p(File.dirname(rf_path))
101
- File.open(rf_path, 'w+') do |f|
102
- @data[:examples] ||= []
103
- @data[:examples] << [file, rel_path]
104
- f.write(rf)
105
- end
60
+ if subtree = find_subtree(version, ex) # check that it exists
61
+ index.read_tree(subtree)
62
+ out " - processing examples for #{version}"
63
+
64
+ files = []
65
+ index.each do |entry|
66
+ next unless entry[:path].match(/\.c$/)
67
+ files << entry[:path]
68
+ end
69
+
70
+ files.each do |file|
71
+ out " # #{file}"
72
+
73
+ # highlight, roccoize and link
74
+ rocco = Rocco.new(file, files, {:language => 'c'}) do
75
+ ientry = index[file]
76
+ blob = @repo.lookup(ientry[:oid])
77
+ blob.content
78
+ end
79
+ rocco_layout = Rocco::Layout.new(rocco, tf)
80
+ rocco_layout.version = version
81
+ rf = rocco_layout.render
82
+
83
+ rf_path = File.basename(file).split('.')[0..-2].join('.') + '.html'
84
+ rel_path = "ex/#{version}/#{rf_path}"
85
+
86
+ # look for function names in the examples and link
87
+ id_num = 0
88
+ @data[:functions].each do |f, fdata|
89
+ rf.gsub!(/#{f}([^\w])/) do |fmatch|
90
+ extra = $1
91
+ id_num += 1
92
+ name = f + '-' + id_num.to_s
93
+ # save data for cross-link
94
+ @data[:functions][f][:examples] ||= {}
95
+ @data[:functions][f][:examples][file] ||= []
96
+ @data[:functions][f][:examples][file] << rel_path + '#' + name
97
+ "<a name=\"#{name}\" class=\"fnlink\" href=\"../../##{version}/group/#{fdata[:group]}/#{f}\">#{f}</a>#{extra}"
106
98
  end
107
99
  end
100
+
101
+ # write example to the repo
102
+ sha = @repo.write(rf, :blob)
103
+ output_index.add(:path => rel_path, :oid => sha, :mode => 0100644)
104
+
105
+ @data[:examples] ||= []
106
+ @data[:examples] << [file, rel_path]
108
107
  end
109
108
  end
110
109
 
@@ -113,49 +112,37 @@ class Docurium
113
112
  end
114
113
  end
115
114
 
116
- File.open(File.join(outdir, "#{version}.json"), 'w+') do |f|
117
- f.write(@data.to_json)
118
- end
119
- end
120
-
121
- Dir.chdir(outdir) do
122
- project = {
123
- :versions => versions.reverse,
124
- :github => @options['github'],
125
- :name => @options['name'],
126
- :signatures => @sigs,
127
- :groups => @groups
128
- }
129
- File.open("project.json", 'w+') do |f|
130
- f.write(project.to_json)
131
- end
115
+ sha = @repo.write(@data.to_json, :blob)
116
+ output_index.add(:path => "#{version}.json", :oid => sha, :mode => 0100644)
132
117
  end
133
118
 
134
- if br = @options['branch']
135
- out "* writing to branch #{br}"
136
- ref = "refs/heads/#{br}"
137
- with_git_env(outdir) do
138
- psha = `git rev-parse #{ref}`.chomp
139
- `git add -A`
140
- tsha = `git write-tree`.chomp
141
- puts "\twrote tree #{tsha}"
142
- if(psha == ref)
143
- csha = `echo 'generated docs' | git commit-tree #{tsha}`.chomp
144
- else
145
- csha = `echo 'generated docs' | git commit-tree #{tsha} -p #{psha}`.chomp
146
- end
147
- puts "\twrote commit #{csha}"
148
- `git update-ref -m 'generated docs' #{ref} #{csha}`
149
- puts "\tupdated #{br}"
150
- end
151
- else
152
- final_dir = File.join(@project_dir, @options['output'] || 'docs')
153
- out "* output html in #{final_dir}"
154
- FileUtils.mkdir_p(final_dir)
155
- Dir.chdir(final_dir) do
156
- FileUtils.cp_r(File.join(outdir, '.'), '.')
157
- end
158
- end
119
+ project = {
120
+ :versions => versions.reverse,
121
+ :github => @options['github'],
122
+ :name => @options['name'],
123
+ :signatures => @sigs,
124
+ :groups => @groups
125
+ }
126
+ sha = @repo.write(project.to_json, :blob)
127
+ output_index.add(:path => "project.json", :oid => sha, :mode => 0100644)
128
+
129
+ br = @options['branch']
130
+ out "* writing to branch #{br}"
131
+ refname = "refs/heads/#{br}"
132
+ tsha = output_index.write_tree(@repo)
133
+ puts "\twrote tree #{tsha}"
134
+ ref = Rugged::Reference.lookup(@repo, refname)
135
+ user = { :name => @repo.config['user.name'], :email => @repo.config['user.email'], :time => Time.now }
136
+ options = {}
137
+ options[:tree] = tsha
138
+ options[:author] = user
139
+ options[:committer] = user
140
+ options[:message] = 'generated docs'
141
+ options[:parents] = ref ? [ref.target] : []
142
+ options[:update_ref] = refname
143
+ csha = Rugged::Commit.create(@repo, options)
144
+ puts "\twrote commit #{csha}"
145
+ puts "\tupdated #{br}"
159
146
  end
160
147
 
161
148
  def show_warnings
@@ -185,13 +172,17 @@ class Docurium
185
172
  end
186
173
 
187
174
  def get_versions
188
- VersionSorter.sort(git('tag').split("\n"))
175
+ tags = []
176
+ @repo.tags.each { |tag| tags << tag.gsub(%r(^refs/tags/), '') }
177
+ VersionSorter.sort(tags)
189
178
  end
190
179
 
191
- def parse_headers
192
- headers.each do |header|
193
- parse_header(header)
180
+ def parse_headers(index)
181
+ headers(index).each do |header|
182
+ records = parse_header(index, header)
183
+ update_globals(records)
194
184
  end
185
+
195
186
  @data[:groups] = group_functions
196
187
  @data[:types] = @data[:types].sort # make it an assoc array
197
188
  find_type_usage
@@ -214,29 +205,30 @@ class Docurium
214
205
  end
215
206
  end
216
207
 
217
- def git(command)
218
- out = ''
219
- Dir.chdir(@project_dir) do
220
- out = `git #{command}`
208
+ def find_subtree(version, path)
209
+ tree = nil
210
+ if version == 'HEAD'
211
+ tree = @repo.lookup(@repo.head.target).tree
212
+ else
213
+ trg = @repo.lookup(Rugged::Reference.lookup(@repo, "refs/tags/#{version}").target)
214
+ if(trg.class == Rugged::Tag)
215
+ trg = trg.target
216
+ end
217
+
218
+ tree = trg.tree
221
219
  end
222
- out.strip
223
- end
224
220
 
225
- def checkout(version, workdir)
226
- with_git_env(workdir) do
227
- `git read-tree #{version}:#{@data[:prefix]}`
228
- `git checkout-index -a`
221
+ begin
222
+ tree_entry = tree.path(path)
223
+ @repo.lookup(tree_entry[:oid])
224
+ rescue Rugged::TreeError
225
+ nil
229
226
  end
230
227
  end
231
228
 
232
- def with_git_env(workdir)
233
- ENV['GIT_INDEX_FILE'] = mkfile_temp
234
- ENV['GIT_WORK_TREE'] = workdir
235
- ENV['GIT_DIR'] = File.join(@project_dir, '.git')
236
- yield
237
- ENV.delete('GIT_INDEX_FILE')
238
- ENV.delete('GIT_WORK_TREE')
239
- ENV.delete('GIT_DIR')
229
+ def read_subtree(index, version, path)
230
+ tree = find_subtree(version, path)
231
+ index.read_tree(tree)
240
232
  end
241
233
 
242
234
  def valid_config(file)
@@ -245,7 +237,7 @@ class Docurium
245
237
  @project_dir = File.dirname(fpath)
246
238
  @config_file = File.basename(fpath)
247
239
  @options = JSON.parse(File.read(fpath))
248
- true
240
+ !!@options['branch']
249
241
  end
250
242
 
251
243
  def group_functions
@@ -271,11 +263,11 @@ class Docurium
271
263
  func.to_a.sort
272
264
  end
273
265
 
274
- def headers
266
+ def headers(index = nil)
275
267
  h = []
276
- Dir.glob(File.join('**/*.h')).each do |header|
277
- next if !File.file?(header)
278
- h << header
268
+ index.each do |entry|
269
+ next unless entry[:path].match(/\.h$/)
270
+ h << entry[:path]
279
271
  end
280
272
  h
281
273
  end
@@ -299,248 +291,123 @@ class Docurium
299
291
  end
300
292
  end
301
293
 
302
- def header_content(header_path)
303
- File.readlines(header_path)
294
+ def parse_header(index, path)
295
+ id = index[path][:oid]
296
+ blob = @repo.lookup(id)
297
+ parser = Docurium::CParser.new
298
+ parser.parse_text(path, blob.content)
304
299
  end
305
300
 
306
- def parse_header(filepath)
307
- lineno = 0
308
- content = header_content(filepath)
309
-
310
- # look for structs and enums
311
- in_block = false
312
- block = ''
313
- linestart = 0
314
- tdef, type, name = nil
315
- content.each do |line|
316
- lineno += 1
317
- line = line.strip
318
-
319
- if line[0, 1] == '#' #preprocessor
320
- if m = /\#define (.*?) (.*)/.match(line)
321
- @data[:globals][m[1]] = {:value => m[2].strip, :file => filepath, :line => lineno}
322
- else
323
- next
324
- end
325
- end
301
+ def update_globals(recs)
302
+ wanted = {
303
+ :functions => %W/type value file line lineto args argline sig return group description comments/.map(&:to_sym),
304
+ :types => %W/type value file line lineto block tdef comments/.map(&:to_sym),
305
+ :globals => %W/value file line comments/.map(&:to_sym),
306
+ :meta => %W/brief defgroup ingroup comments/.map(&:to_sym),
307
+ }
326
308
 
327
- if m = /^(typedef )*(struct|enum) (.*?)(\{|(\w*?);)/.match(line)
328
- tdef = m[1] # typdef or nil
329
- type = m[2] # struct or enum
330
- name = m[3] # name or nil
331
- linestart = lineno
332
- name.strip! if name
333
- tdef.strip! if tdef
334
- if m[4] == '{'
335
- # struct or enum
336
- in_block = true
337
- else
338
- # single line, probably typedef
339
- val = m[4].gsub(';', '').strip
340
- if !name.empty?
341
- name = name.gsub('*', '').strip
342
- @data[:types][name] = {:tdef => tdef, :type => type, :value => val, :file => filepath, :line => lineno}
343
- end
344
- end
345
- elsif m = /\}(.*?);/.match(line)
346
- if !m[1].strip.empty?
347
- name = m[1].strip
348
- end
349
- name = name.gsub('*', '').strip
350
- @data[:types][name] = {:block => block, :tdef => tdef, :type => type, :value => val, :file => filepath, :line => linestart, :lineto => lineno}
351
- in_block = false
352
- block = ''
353
- elsif in_block
354
- block += line + "\n"
355
- end
356
- end
357
-
358
- in_comment = false
359
- in_block = false
360
- current = -1
361
- data = []
362
- lineno = 0
363
- # look for functions
364
- content.each do |line|
365
- lineno += 1
366
- line = line.strip
367
- next if line.size == 0
368
- next if line[0, 1] == '#'
369
- in_block = true if line =~ /\{/
370
- if m = /(.*?)\/\*(.*?)\*\//.match(line)
371
- code = m[1]
372
- comment = m[2]
373
- current += 1
374
- data[current] ||= {:comments => clean_comment(comment), :code => [code], :line => lineno}
375
- elsif m = /(.*?)\/\/(.*?)/.match(line)
376
- code = m[1]
377
- comment = m[2]
378
- current += 1
379
- data[current] ||= {:comments => clean_comment(comment), :code => [code], :line => lineno}
380
- else
381
- if line =~ /\/\*/
382
- in_comment = true
383
- current += 1
384
- elsif current == -1
385
- current += 1
386
- end
387
- data[current] ||= {:comments => '', :code => [], :line => lineno}
388
- data[current][:lineto] = lineno
389
- if in_comment
390
- data[current][:comments] += clean_comment(line) + "\n"
391
- else
392
- data[current][:code] << line
393
- end
394
- if (m = /(.*?);$/.match(line)) && (data[current][:code].size > 0) && !in_block
395
- current += 1
396
- end
397
- in_comment = false if line =~ /\*\//
398
- in_block = false if line =~ /\}/
399
- end
400
- end
401
- data.compact!
402
- meta = extract_meta(data)
403
- funcs = extract_functions(filepath, data)
404
- @data[:files] << {:file => filepath, :meta => meta, :functions => funcs, :lines => lineno}
405
- end
309
+ file_map = {}
406
310
 
407
- def clean_comment(comment)
408
- comment = comment.gsub(/^\/\//, '')
409
- comment = comment.gsub(/^\/\**/, '')
410
- comment = comment.gsub(/^\**/, '')
411
- comment = comment.gsub(/^[\w\*]*\//, '')
412
- comment
413
- end
311
+ md = Redcarpet::Markdown.new Redcarpet::Render::HTML, :no_intra_emphasis => true
312
+ recs.each do |r|
414
313
 
415
- # go through all the comment blocks and extract:
416
- # @file, @brief, @defgroup and @ingroup
417
- def extract_meta(data)
418
- file, brief, defgroup, ingroup = nil
419
- data.each do |block|
420
- block[:comments].each do |comment|
421
- m = []
422
- file = m[1] if m = /@file (.*?)$/.match(comment)
423
- brief = m[1] if m = /@brief (.*?)$/.match(comment)
424
- defgroup = m[1] if m = /@defgroup (.*?)$/.match(comment)
425
- ingroup = m[1] if m = /@ingroup (.*?)$/.match(comment)
314
+ # initialize filemap for this file
315
+ file_map[r[:file]] ||= {
316
+ :file => r[:file], :functions => [], :meta => {}, :lines => 0
317
+ }
318
+ if file_map[r[:file]][:lines] < r[:lineto]
319
+ file_map[r[:file]][:lines] = r[:lineto]
426
320
  end
427
- end
428
- {:file => file, :brief => brief, :defgroup => defgroup, :ingroup => ingroup}
429
- end
430
321
 
431
- def extract_functions(file, data)
432
- @data[:functions]
433
- funcs = []
434
- data.each do |block|
435
- ignore = false
436
- code = block[:code].join(" ")
437
- code = code.gsub(/\{(.*)\}/, '') # strip inline code
438
- rawComments = block[:comments]
439
- comments = block[:comments]
440
-
441
- if m = /^(.*?) ([a-z_]+)\((.*)\)/.match(code)
442
- ret = m[1].strip
443
- if r = /\((.*)\)/.match(ret) # strip macro
444
- ret = r[1]
322
+ # process this type of record
323
+ case r[:type]
324
+ when :function
325
+ @data[:functions][r[:name]] ||= {}
326
+ wanted[:functions].each do |k|
327
+ next unless r.has_key? k
328
+ conents = nil
329
+ if k == :description || k == :comments
330
+ contents = md.render r[k]
331
+ else
332
+ contents = r[k]
333
+ end
334
+ @data[:functions][r[:name]][k] = contents
445
335
  end
446
- fun = m[2].strip
447
- origArgs = m[3].strip
448
-
449
- # replace ridiculous syntax
450
- args = origArgs.gsub(/(\w+) \(\*(.*?)\)\(([^\)]*)\)/) do |m|
451
- type, name = $1, $2
452
- cast = $3.gsub(',', '###')
453
- "#{type}(*)(#{cast}) #{name}"
336
+ file_map[r[:file]][:functions] << r[:name]
337
+
338
+ when :define, :macro
339
+ @data[:globals][r[:decl]] ||= {}
340
+ wanted[:globals].each do |k|
341
+ @data[:globals][r[:decl]][k] = r[k] if r.has_key?(k)
454
342
  end
455
343
 
456
- args = args.split(',').map do |arg|
457
- argarry = arg.split(' ')
458
- var = argarry.pop
459
- type = argarry.join(' ').gsub('###', ',') + ' '
344
+ when :file
345
+ wanted[:meta].each do |k|
346
+ file_map[r[:file]][:meta][k] = r[k] if r.has_key?(k)
347
+ end
460
348
 
461
- ## split pointers off end of type or beg of name
462
- var.gsub!('*') do |m|
463
- type += '*'
464
- ''
349
+ when :enum
350
+ if !r[:name]
351
+ # Explode unnamed enum into multiple global defines
352
+ r[:decl].each do |n|
353
+ @data[:globals][n] ||= {
354
+ :file => r[:file], :line => r[:line],
355
+ :value => "", :comments => r[:comments],
356
+ }
357
+ m = /#{Regexp.quote(n)}/.match(r[:body])
358
+ if m
359
+ @data[:globals][n][:line] += m.pre_match.scan("\n").length
360
+ if m.post_match =~ /\s*=\s*([^,\}]+)/
361
+ @data[:globals][n][:value] = $1
362
+ end
363
+ end
465
364
  end
466
- desc = ''
467
- comments = comments.gsub(/\@param #{Regexp.escape(var)} ([^@]*)/m) do |m|
468
- desc = $1.gsub("\n", ' ').gsub("\t", ' ').strip
469
- ''
365
+ else
366
+ @data[:types][r[:name]] ||= {}
367
+ wanted[:types].each do |k|
368
+ @data[:types][r[:name]][k] = r[k] if r.has_key?(k)
470
369
  end
471
- ## TODO: parse comments to extract data about args
472
- {:type => type.strip, :name => var, :comment => desc}
473
370
  end
474
371
 
475
- sig = args.map do |arg|
476
- arg[:type].to_s
477
- end.join('::')
478
-
479
- return_comment = ''
480
- comments.gsub!(/\@return ([^@]*)/m) do |m|
481
- return_comment = $1.gsub("\n", ' ').gsub("\t", ' ').strip
482
- ''
372
+ when :struct, :fnptr
373
+ @data[:types][r[:name]] ||= {}
374
+ r[:value] ||= r[:name]
375
+ wanted[:types].each do |k|
376
+ @data[:types][r[:name]][k] = r[k] if r.has_key?(k)
483
377
  end
484
-
485
- comments = strip_block(comments)
486
- comment_lines = comments.split("\n\n")
487
-
488
- desc = ''
489
- if comments.size > 0
490
- desc = comment_lines.shift.split("\n").map { |e| e.strip }.join(' ')
491
- comments = comment_lines.join("\n\n").strip
378
+ if r[:type] == :fnptr
379
+ @data[:types][r[:name]][:type] = "function pointer"
492
380
  end
493
381
 
494
- next if fun == 'defined'
495
- @data[:functions][fun] = {
496
- :description => desc,
497
- :return => {:type => ret, :comment => return_comment},
498
- :args => args,
499
- :argline => origArgs,
500
- :file => file,
501
- :line => block[:line],
502
- :lineto => block[:lineto],
503
- :comments => comments,
504
- :sig => sig,
505
- :rawComments => rawComments
506
- }
507
- funcs << fun
382
+ else
383
+ # Anything else we want to record?
508
384
  end
509
- end
510
- funcs
511
- end
512
385
 
513
- # TODO: rolled this back, want to strip the first few spaces, not everything
514
- def strip_block(block)
515
- block.strip
516
- end
517
-
518
- def mkdir_temp
519
- tf = Tempfile.new('docurium')
520
- tpath = tf.path
521
- tf.unlink
522
- FileUtils.mkdir_p(tpath)
523
- tpath
524
- end
386
+ end
525
387
 
526
- def mkfile_temp
527
- tf = Tempfile.new('docurium-index')
528
- tpath = tf.path
529
- tf.unlink
530
- tpath
388
+ @data[:files] << file_map.values[0]
531
389
  end
532
390
 
533
- def copy_site(outdir)
534
- here = File.expand_path(File.dirname(__FILE__))
535
- FileUtils.mkdir_p(outdir)
536
- Dir.chdir(outdir) do
537
- FileUtils.cp_r(File.join(here, '..', 'site', '.'), '.')
391
+ def add_dir_to_index(index, prefix, dir)
392
+ Dir.new(dir).each do |filename|
393
+ next if [".", ".."].include? filename
394
+ name = File.join(dir, filename)
395
+ if File.directory? name
396
+ add_dir_to_index(index, prefix, name)
397
+ else
398
+ rel_path = name.gsub(prefix, '')
399
+ content = File.read(name)
400
+ sha = @repo.write(content, :blob)
401
+ index.add(:path => rel_path, :oid => sha, :mode => 0100644)
402
+ end
538
403
  end
539
404
  end
540
405
 
541
- def write_dir
542
- out "Writing to directory #{output_dir}"
543
- out "Done!"
406
+ def write_site(index)
407
+ here = File.expand_path(File.dirname(__FILE__))
408
+ dirname = File.join(here, '..', 'site')
409
+ dirname = File.realpath(dirname)
410
+ add_dir_to_index(index, dirname + '/', dirname)
544
411
  end
545
412
 
546
413
  def out(text)