#!/usr/bin/env ruby
#
# Goes through every file under this directory,
# fixing it's `#include` statement.
#
# * Gets a file name by looking at the last
#   path component of a `#include`
# * Searches for it under this directory tree
# * If found, inserts it's new relative path
# * If not, simply prints the output.
#   That might be the case when it finds, say,
#   `#include <vector>` or `#include <string.h>`
#
# NOTE: It modifies the original files, so make
#       sure to use a VCS (like Git or SVN) or
#       at least have a backup somewhere!
#
# NOTE: You MUST be on the root of the source code
#       directory, since all `#include`s will be
#       based on that.
#       For example, if you have "src/file.cpp" you
#       must be on "src".

require 'tempfile'
require 'fileutils'

# START OF USER CONFIGURABLE STUFF

# Will not even touch other files
allowed_extensions = ['.cpp', '.hpp']

# Will put all the lines on this file
# and then rename it to the original
tmp_file_name = '/tmp/temporary_file'

# END OF USER CONFIGURABLE STUFF

begin
  # Matches any line like "#include <path/to/File.cpp>"
  regexp_include = /\#include\s+<(.+)>/

  # List of all files under this directory tree
  all_files = Dir.glob('**/*')

  all_files.each do |file|
    next if File.directory? file
    next if not allowed_extensions.member? File.extname(file)

    tmp = File.new(tmp_file_name, 'w')

    File.readlines(file).each do |line|

      match = line.match regexp_include
      if match.nil?
        tmp << line
        next
      end

      included = match[1]
      new_included = ""

      all_files.each do |this_file|
        if File.basename(this_file) == File.basename(included)
          new_included = this_file
          break
        end
      end

      # Didn't found the new file
      if (new_included.empty?)
        puts "Couldn't find file '#{included}'"
        tmp << line
      else
        tmp << "#include <#{new_included}>\n"
      end
    end

    tmp.close
    FileUtils.mv(File.path(tmp), file)
  end
end