Class: Quik::Merger

Inherits:
Object
  • Object
show all
Defined in:
lib/quik/merger.rb

Instance Method Summary collapse

Instance Method Details

#find_files(root_dir) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/quik/merger.rb', line 9

def find_files( root_dir )
  tree = []

  files =  Dir.entries( root_dir )
  files = files.sort
  puts "#{root_dir}:"
  pp files

  files.each do |file|
    if File.directory?( "#{root_dir}/#{file}" )
      ## note: skip directory if it starts with dot e.g. . or .. or .git etc.
      if file.start_with?( '.' )
        puts "skipping directory >#{file}< (#{root_dir})"
        next
      end
      subtree = find_files( "#{root_dir}/#{file}" )
      tree << [ file, subtree ]
    else
      ## just a "regular" file
      tree << file
    end
  end
  tree
end

#merge(root_dir, hash, opts = {}) ⇒ Object



194
195
196
197
198
199
# File 'lib/quik/merger.rb', line 194

def merge( root_dir, hash, opts={} )
  puts "  merge #{root_dir}, #{hash.inspect}"

  merge_filenames( root_dir, hash, opts )
  merge_files( root_dir, hash, opts )
end

#merge_filenames(root_dir, hash, opts = {}) ⇒ Object

flags e.g. noop, verbose, etc. see FileUtils



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/quik/merger.rb', line 35

def merge_filenames( root_dir, hash, opts={} )  ## flags e.g. noop, verbose, etc. see FileUtils
  tree = find_files( root_dir )
  pp tree

  flags = {     ## always use verbose mode for now
    verbose: true
  }

  ## todo/check: move opts={} to initialize e.g. Merger.new( opts={}) why? why not??

  ## check for noop e.g. test mode/dry run
  flags[ :noop ] = true  if opts[:test] || opts[:dry_run] || opts[:noop]

  puts "walk tree:"
  merge_filenames_worker_step1( root_dir, hash, tree, flags )
  merge_filenames_worker_step2( root_dir, hash, tree, flags )
end

#merge_filenames_worker_step1(root_dir, hash, tree, flags) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/quik/merger.rb', line 53

def merge_filenames_worker_step1( root_dir, hash, tree, flags )
  ## note:  step 1 move all files
  ##        step 2 move all dirs

  tree.each do |node|
    if node.is_a? Array ## assume it's a directory
      merge_filenames_worker_step1( "#{root_dir}/#{node[0]}", hash, node[1], flags )
    else  ## assume it's a file
      old_name = node
      new_name = merge_path( old_name, hash )
      if old_name == new_name
         puts "  keep file #{node} (#{root_dir})"
      else
         puts "  *** move file #{old_name} => #{new_name} (#{root_dir})"
         src_path  = "#{root_dir}/#{old_name}"
         dest_path = "#{root_dir}/#{new_name}"
         FileUtils.mv( src_path, dest_path, flags )
      end
    end
  end
end

#merge_filenames_worker_step2(root_dir, hash, tree, flags) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/quik/merger.rb', line 75

def merge_filenames_worker_step2( root_dir, hash, tree, flags )
  ## note:  step 1 move all files
  ##        step 2 move all dirs

  tree.each do |node|
    if node.is_a? Array ## assume it's a directory
      merge_filenames_worker_step2( "#{root_dir}/#{node[0]}", hash, node[1], flags )
      old_name = node[0]
      new_name = merge_path( old_name, hash )
      if old_name == new_name
         puts "  keep dir #{node[0]} (#{root_dir})"
      else
         puts "  *** move dir #{old_name} => #{new_name} (#{root_dir})"
         src_path  = "#{root_dir}/#{old_name}"
         dest_path = "#{root_dir}/#{new_name}"
         FileUtils.mv( src_path, dest_path, flags )
      end
    end
  end
end

#merge_files(root_dir, hash, opts = {}) ⇒ Object



98
99
100
101
102
103
104
105
# File 'lib/quik/merger.rb', line 98

def merge_files( root_dir, hash, opts={} )
  ## note: rescan files (after renames)
  tree = find_files( root_dir )
  pp tree

  puts "walk tree:"
  merge_files_worker( root_dir, '', hash, tree, opts )
end

#merge_files_worker(root_dir, relative_dir, hash, tree, opts) ⇒ Object



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/quik/merger.rb', line 107

def merge_files_worker( root_dir, relative_dir, hash, tree, opts )
  tree.each do |node|
    if node.is_a? Array ## assume it's a directory
      if relative_dir.empty?   # e.g. just add w/o leading slash e.g. 'lib' and not '/lib'
        new_relative_dir = node[0].dup  # note: create a new string; just in case
      else
        new_relative_dir = "#{relative_dir}/#{node[0]}"
      end
      merge_files_worker( root_dir, new_relative_dir, hash, node[1], opts )
    else  ## assume it's a file
      if relative_dir.empty?
        relative_path = node
      else
        relative_path = "#{relative_dir}/#{node}"
      end

      src_path = "#{root_dir}/#{relative_path}"
      
      ## note: for now assume always assume text files/utf8
      ##  fix: change to File.read_utf8 ??
      old_text = File.read( src_path )
      new_text = merge_text( old_text, hash )

      if opts[:o]
        dest_root = opts[:o]
        dest_path = "#{dest_root}/#{relative_path}"
        ## make sure dest_path exists
        dest_dir = File.dirname( dest_path )
        FileUtils.mkdir_p( dest_dir ) unless Dir.exists?( dest_dir )
      else
        dest_root = root_dir
        dest_path = "#{dest_root}/#{relative_path}"
      end

      if old_text == new_text
         if opts[:o]  ## for testing copy file 1:1
           puts "  copy file 1:1 #{node} (#{relative_dir}) in (#{dest_root})"
           FileUtils.cp( src_path, dest_path, verbose: true )
         else
           puts "  skip file #{node} (#{relative_dir})"
         end
      else
         puts "  *** update file #{node} (#{relative_dir}) in (#{dest_root})"
         File.open( dest_path, 'w' ) do |f|
           f.write new_text
         end
      end
    end
  end
end

#merge_path(path, hash) ⇒ Object



160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/quik/merger.rb', line 160

def merge_path( path, hash )
  ## e.g. allow
  ##  __filename__  or
  ##  $filename$   for now
  ##   note: allow underline too  e.g $file_name$ etc.
  path.gsub( /(__|\$)([a-z_]+)\1/i ) do |_|
    key   = $2.to_s
    value = hash[ key ]
    puts "   [path] replacing #{key} w/ >#{value}< in (#{path})"
    value
  end
end

#merge_text(text, hash) ⇒ Object



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/quik/merger.rb', line 173

def merge_text( text, hash )
  ## e.g. allow
  ##  $filename$  for now only in text
  ##  note: must include leading and trailing word boundry (/B)
  ##   e.g. hello$test$ will not match only "free-standing $test
  ##  or in quote e.g. "$test$"
  ##  e.g. no letters or digits allowed before or after $ to match
  ##  note: allow underline too e.g. $test_klass$ etc.

  ## pp text

  text.gsub( /\B\$([a-z_]+)\$\B/i ) do |_|
    key   = $1.to_s
    value = hash[ key ]
    puts "   [text] replacing #{key} w/ >#{value}<"
    value
  end
end