Module: WatchTower::Eye

Extended by:
Eye
Included in:
Eye
Defined in:
lib/watch_tower/eye.rb

Constant Summary collapse

IGNORED_PATHS =

Ignore paths

%r(/(.git|.svn)/)

Instance Method Summary collapse

Instance Method Details

#start(options = {}) ⇒ Object

Start the watch loop

Parameters:

  • options (Hash) (defaults to: {})

Raises:



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/watch_tower/eye.rb', line 16

def start(options = {})
  LOG.debug("#{__FILE__}:#{__LINE__}: The Eye loop has just started")
  loop do
    # Try getting the mtime of the document opened by each editor in the
    # editors list.
    Editor.editors.each do |editor|
      # Create an instance of the editor
      # TODO: Should be used as a class instead
      editor = editor.new
      # Check if the editor is running
      if editor.is_running?
        LOG.debug("#{__FILE__}:#{__LINE__}: #{editor.to_s} is running")
        # Get the currently being edited file from the editor
        files_paths = editor.current_paths
        # Iterate over the files to fill the database
        files_paths.each do |file_path|
          begin
            next unless file_path
            LOG.debug("#{__FILE__}:#{__LINE__}: Ignoring #{file_path}") and next if file_path =~ IGNORED_PATHS
            LOG.debug("#{__FILE__}:#{__LINE__}: #{file_path} does not exist.") and next unless File.exists?(file_path)
            LOG.debug("#{__FILE__}:#{__LINE__}: #{file_path} is not a file") and next unless File.file?(file_path)
            # Get the file_hash of the file
            file_hash = Digest::SHA1.file(file_path).hexdigest
            LOG.debug("#{__FILE__}:#{__LINE__ - 1}: The hash of #{file_path} is #{file_hash}.")
            # Create a project from the file_path
            project = Project.new_from_path(file_path)
          rescue PathNotUnderCodePath
            LOG.debug("#{__FILE__}:#{__LINE__ - 2}: The file '#{file_path}' is not located under '#{Config[:code_path]}', it has been ignored")
            next
          rescue FileNotFound
            LOG.debug "#{__FILE__}:#{__LINE__ - 5}: The file '#{file_path}' does not exist, it has been ignored"
            next
          end

          begin
            # Create (or fetch) a project
            project_model = Server::Project.find_or_create_by_name_and_path(project.name, project.path)
            LOG.debug("#{__FILE__}:#{__LINE__ - 1}: Created (or fetched) the project with the id #{project_model.id}")

            # Create (or fetch) a file
            file_model = project_model.files.find_or_create_by_path(file_path)
            LOG.debug("#{__FILE__}:#{__LINE__ - 1}: Created (or fetched) the file with the id #{file_model.id}")
            begin
              # Create a time entry
              time_entry_model =  file_model.time_entries.create! mtime: ::File.stat(file_path).mtime,
                file_hash: file_hash,
                editor_name: editor.name,
                editor_version: editor.version
              LOG.debug("#{__FILE__}:#{__LINE__ - 4}: Created a time_entry with the id #{time_entry_model.id}")
            rescue ActiveRecord::RecordInvalid => e
              if e.message =~ /Validation failed: Mtime has already been taken/
                # This should happen if the mtime is already present
                LOG.debug("#{__FILE__}:#{__LINE__ - 8}: The time_entry already exists, nothing were created, error message is #{e.message}")
              elsif e.message =~ /Validation failed: /
                # This should not happen
                LOG.fatal("#{__FILE__}:#{__LINE__ - 11}: The time_entry did not pass validations, #{e.message}.")
                $close_eye = true
              else
                # Some other error happened
                LOG.fatal("#{__FILE__}:#{__LINE__ - 15}: An unknown error has been raised while creating the time_entry, #{e.message}")
                $close_eye = true
              end
            end
          rescue ActiveRecord::RecordInvalid => e
            # This should not happen
            LOG.fatal("#{__FILE__}:#{__LINE__}: #{e}")
            $close_eye = true
          end
        end
      else
        LOG.debug("#{__FILE__}:#{__LINE__}: #{editor.to_s} is not running")
      end
    end unless $pause_eye

    # If $stop global is set, please stop, otherwise sleep for 10 seconds.
    if $close_eye
      LOG.debug("#{__FILE__}:#{__LINE__}: Closing eye has been requested, end the loop")
      break
    else
      # TODO: This should be in the config file, let the user decide how often the loop should start
      sleep 10
    end
  end
end

#start!(options = {}) ⇒ Object

Start the Eye, a method invoked from the Watch Tower command line interface

Parameters:

  • options (Hash) (defaults to: {})


104
105
106
107
108
109
110
# File 'lib/watch_tower/eye.rb', line 104

def start!(options = {})
  # Signal handling
  Signal.trap("INT")  { $close_eye = true }
  Signal.trap("TERM") { $close_eye = true }

  start(options)
end