{"action":"created","comment":{"url":"https://api.github.com/repos/deep-cover/deep-cover/pulls/comments/191608141","pull_request_review_id":124210991,"id":191608141,"diff_hunk":"@@ -43,96 +41,162 @@ def compute_subset\n       end\n     end\n \n+    class EveryLoadPaths\n+      attr_reader :load_paths\n+      def initialize(load_paths)\n+        @load_paths = load_paths\n+      end\n+\n+      def exist?(full_path)\n+        File.exist?(full_path)\n+      end\n+\n+      def within_lookup?(full_path)\n+        true\n+      end\n+    end\n+\n     attr_reader :load_paths, :loaded_features, :filter\n     def initialize(load_paths: $LOAD_PATH, loaded_features: $LOADED_FEATURES, lookup_paths: nil, &filter)\n       @load_paths = load_paths\n       lookup_paths ||= Dir.getwd\n       lookup_paths = Array(lookup_paths)\n-      @load_paths_subset = lookup_paths.include?('/') ? nil : LoadPathsSubset.new(load_paths: load_paths, lookup_paths: lookup_paths)\n+\n+      if lookup_paths.include?('/')\n+        @load_paths_subset = EveryLoadPaths.new(load_paths)\n+      else\n+        @load_paths_subset = LoadPathsSubset.new(load_paths: load_paths, lookup_paths: lookup_paths)\n+      end\n+\n       @loaded_features = loaded_features\n       @filter = filter\n+      @paths_being_required = Set.new\n     end\n \n     # Returns a path to an existing file or nil if none can be found.\n-    # The search follows how ruby search for files using the $LOAD_PATH\n+    # The search follows how ruby search for files using the $LOAD_PATH, but limits\n+    # those it checks based on the LoadPathsSubset.\n     #\n-    # An absolute path is returned directly if it exists, otherwise nil\n-    # is returned without searching anywhere else.\n-    def resolve_path(path)\n-      path = File.absolute_path(path) if path.start_with?('./', '../')\n+    # An absolute path is returned directly if it exists, otherwise nil is returned\n+    # without searching anywhere else.\n+    def resolve_path(path, extensions_to_try = ['.rb', '.so'])\n+      if extensions_to_try\n+        extensions_to_try = [''] if extensions_to_try.any? { |ext| path.end_with?(ext) }\n+      else\n+        extensions_to_try = ['']\n+      end\n \n       abs_path = File.absolute_path(path)\n+      path = abs_path if path.start_with?('./', '../')\n+\n+      paths_with_ext = extensions_to_try.map { |ext| path + ext }\n+\n+      # Doing this check in every case instead of only for absolute_path because ruby has some\n+      # built-in $LOADED_FEATURES which aren't an absolute path. Ex: enumerator.so, thread.rb\n+      paths_with_ext.each do |path_with_ext|\n+        return path_with_ext if @loaded_features.include?(path_with_ext)\n+      end\n+\n       if path == abs_path\n-        path if (@load_paths_subset || File).exist?(path)\n+        paths_with_ext.each do |path_with_ext|\n+          return path_with_ext if File.exist?(path_with_ext)\n+        end\n       else\n-        (@load_paths_subset || self).load_paths.each do |load_path|\n-          possible_path = File.absolute_path(path, load_path)\n+        possible_paths = paths_with_load_paths(paths_with_ext)\n+        possible_paths.each do |possible_path|\n+          return possible_path if @loaded_features.include?(possible_path)\n+        end\n \n-          next unless (@load_paths_subset || File).exist?(possible_path)\n+        possible_paths.each do |possible_path|\n+          next unless File.exist?(possible_path)\n           # Ruby 2.5 changed some behaviors of require related to symlinks in $LOAD_PATH\n           # https://bugs.ruby-lang.org/issues/10222\n           return File.realpath(possible_path) if RUBY_VERSION >= '2.5'\n           return possible_path\n         end\n-        nil\n       end\n+      nil\n     end\n \n     # Homemade #require to be able to instrument the code before it gets executed.\n     # Returns true when everything went right. (Same as regular ruby)\n     # Returns false when the found file was already required. (Same as regular ruby)\n-    # Throws :use_fallback in case caller should delegate to the default #require.\n-    # Reasons given could be:\n+    # Calls &fallback_block with the reason as parameter if the work couldn't be done.\n+    # The possible reasons are:\n     #  - :not_found if the file couldn't be found.\n+    #  - :not_in_covered_paths if the file is not in the paths to cover\n     #  - :cover_failed if DeepCover couldn't apply instrumentation the file found.\n-    #  - :not_supported for files that are not supported (such as ike .so files)\n+    #  - :not_supported for files that are not supported (such as .so files)\n     #  - :skipped if the filter block returned `true`\n-    # Exceptions raised by the required code bubble up as normal.\n-    #     It is *NOT* recommended to simply delegate to the default #require, since it\n-    #     might not be safe to run part of the code again.\n-    def require(path)\n+    # Exceptions raised by the required code bubble up as normal, except for\n+    # SyntaxError, which is turned into a :cover_failed which calls the fallback_block.\n+    def require(path, &fallback_block)\n       path = path.to_s\n-      ext = File.extname(path)\n-      throw :use_fallback, :not_supported if ext == '.so'\n-      path += '.rb' if ext != '.rb'\n-      return false if @loaded_features.include?(path)\n \n       found_path = resolve_path(path)\n \n-      throw :use_fallback, :not_found unless found_path\n-      return false if @loaded_features.include?(found_path)\n+      if found_path\n+        return false if @loaded_features.include?(found_path)\n+        return false if @paths_being_required.include?(found_path)\n+      end\n+\n+      DeepCover.autoload_tracker.wrap_require(path, found_path) do\n+        # Either a problem with resolve_path, or a gem that will be added to the load_path by RubyGems\n+        return yield(:not_found) unless found_path\n \n-      throw :use_fallback, :skipped if filter && filter.call(found_path)\n+        begin\n+          @paths_being_required.add(found_path)\n+          return yield(:not_in_covered_paths) unless @load_paths_subset.within_lookup?(found_path)\n+          return yield(:not_supported) if found_path.end_with?('.so')\n+          return yield(:skipped) if filter && filter.call(found_path)\n \n-      cover_and_execute(found_path)\n+          cover_and_execute(found_path) { |reason| return yield(reason) }\n \n-      @loaded_features << found_path\n+          @loaded_features << found_path\n+        ensure\n+          @paths_being_required.delete(found_path)\n+        end\n+      end\n       true\n     end\n \n+    ### Not currently used ###\n     # Homemade #load to be able to instrument the code before it gets executed.\n     # Note, this doesn't support the `wrap` parameter that ruby's #load has.\n     # Same return/throw as CustomRequirer#require, except:\n     # Cannot return false since #load doesn't care about a file already being executed.\n-    def load(path)\n-      found_path = resolve_path(path)\n+    def load(path, &fallback_block)","path":"lib/deep_cover/custom_requirer.rb","position":null,"original_position":165,"commit_id":"fcd4a43670618f1d3d7e9848956411eb6a22e9a6","original_commit_id":"39f1be57e0195cce5c8a4ca094c88adaf6d2604a","user":{"login":"MaxLap","id":894561,"avatar_url":"https://avatars0.githubusercontent.com/u/894561?v=4","gravatar_id":"","url":"https://api.github.com/users/MaxLap","html_url":"https://github.com/MaxLap","followers_url":"https://api.github.com/users/MaxLap/followers","following_url":"https://api.github.com/users/MaxLap/following{/other_user}","gists_url":"https://api.github.com/users/MaxLap/gists{/gist_id}","starred_url":"https://api.github.com/users/MaxLap/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/MaxLap/subscriptions","organizations_url":"https://api.github.com/users/MaxLap/orgs","repos_url":"https://api.github.com/users/MaxLap/repos","events_url":"https://api.github.com/users/MaxLap/events{/privacy}","received_events_url":"https://api.github.com/users/MaxLap/received_events","type":"User","site_admin":false},"body":"As discussed, replaced with comment to keep the information available near the signature.","created_at":"2018-05-29T23:49:18Z","updated_at":"2018-05-29T23:49:18Z","html_url":"https://github.com/deep-cover/deep-cover/pull/29#discussion_r191608141","pull_request_url":"https://api.github.com/repos/deep-cover/deep-cover/pulls/29","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/deep-cover/deep-cover/pulls/comments/191608141"},"html":{"href":"https://github.com/deep-cover/deep-cover/pull/29#discussion_r191608141"},"pull_request":{"href":"https://api.github.com/repos/deep-cover/deep-cover/pulls/29"}},"in_reply_to_id":191492423},"pull_request":{"url":"https://api.github.com/repos/deep-cover/deep-cover/pulls/29","id":190439983,"html_url":"https://github.com/deep-cover/deep-cover/pull/29","diff_url":"https://github.com/deep-cover/deep-cover/pull/29.diff","patch_url":"https://github.com/deep-cover/deep-cover/pull/29.patch","issue_url":"https://api.github.com/repos/deep-cover/deep-cover/issues/29","number":29,"state":"open","locked":false,"title":"Review fix_autoload branch","user":{"login":"MaxLap","id":894561,"avatar_url":"https://avatars0.githubusercontent.com/u/894561?v=4","gravatar_id":"","url":"https://api.github.com/users/MaxLap","html_url":"https://github.com/MaxLap","followers_url":"https://api.github.com/users/MaxLap/followers","following_url":"https://api.github.com/users/MaxLap/following{/other_user}","gists_url":"https://api.github.com/users/MaxLap/gists{/gist_id}","starred_url":"https://api.github.com/users/MaxLap/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/MaxLap/subscriptions","organizations_url":"https://api.github.com/users/MaxLap/orgs","repos_url":"https://api.github.com/users/MaxLap/repos","events_url":"https://api.github.com/users/MaxLap/events{/privacy}","received_events_url":"https://api.github.com/users/MaxLap/received_events","type":"User","site_admin":false},"body":"This seems to fix all of the issues i've found with autoload.","created_at":"2018-05-24T22:44:00Z","updated_at":"2018-05-29T23:49:18Z","closed_at":null,"merged_at":null,"merge_commit_sha":"b181b745d9a4741181757063df602a0c921ea306","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/deep-cover/deep-cover/pulls/29/commits","review_comments_url":"https://api.github.com/repos/deep-cover/deep-cover/pulls/29/comments","review_comment_url":"https://api.github.com/repos/deep-cover/deep-cover/pulls/comments{/number}","comments_url":"https://api.github.com/repos/deep-cover/deep-cover/issues/29/comments","statuses_url":"https://api.github.com/repos/deep-cover/deep-cover/statuses/fcd4a43670618f1d3d7e9848956411eb6a22e9a6","head":{"label":"deep-cover:fix_autoload","ref":"fix_autoload","sha":"fcd4a43670618f1d3d7e9848956411eb6a22e9a6","user":{"login":"deep-cover","id":32180687,"avatar_url":"https://avatars0.githubusercontent.com/u/32180687?v=4","gravatar_id":"","url":"https://api.github.com/users/deep-cover","html_url":"https://github.com/deep-cover","followers_url":"https://api.github.com/users/deep-cover/followers","following_url":"https://api.github.com/users/deep-cover/following{/other_user}","gists_url":"https://api.github.com/users/deep-cover/gists{/gist_id}","starred_url":"https://api.github.com/users/deep-cover/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/deep-cover/subscriptions","organizations_url":"https://api.github.com/users/deep-cover/orgs","repos_url":"https://api.github.com/users/deep-cover/repos","events_url":"https://api.github.com/users/deep-cover/events{/privacy}","received_events_url":"https://api.github.com/users/deep-cover/received_events","type":"Organization","site_admin":false},"repo":{"id":104405256,"name":"deep-cover","full_name":"deep-cover/deep-cover","owner":{"login":"deep-cover","id":32180687,"avatar_url":"https://avatars0.githubusercontent.com/u/32180687?v=4","gravatar_id":"","url":"https://api.github.com/users/deep-cover","html_url":"https://github.com/deep-cover","followers_url":"https://api.github.com/users/deep-cover/followers","following_url":"https://api.github.com/users/deep-cover/following{/other_user}","gists_url":"https://api.github.com/users/deep-cover/gists{/gist_id}","starred_url":"https://api.github.com/users/deep-cover/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/deep-cover/subscriptions","organizations_url":"https://api.github.com/users/deep-cover/orgs","repos_url":"https://api.github.com/users/deep-cover/repos","events_url":"https://api.github.com/users/deep-cover/events{/privacy}","received_events_url":"https://api.github.com/users/deep-cover/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/deep-cover/deep-cover","description":"The best coverage tool for Ruby code","fork":false,"url":"https://api.github.com/repos/deep-cover/deep-cover","forks_url":"https://api.github.com/repos/deep-cover/deep-cover/forks","keys_url":"https://api.github.com/repos/deep-cover/deep-cover/keys{/key_id}","collaborators_url":"https://api.github.com/repos/deep-cover/deep-cover/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/deep-cover/deep-cover/teams","hooks_url":"https://api.github.com/repos/deep-cover/deep-cover/hooks","issue_events_url":"https://api.github.com/repos/deep-cover/deep-cover/issues/events{/number}","events_url":"https://api.github.com/repos/deep-cover/deep-cover/events","assignees_url":"https://api.github.com/repos/deep-cover/deep-cover/assignees{/user}","branches_url":"https://api.github.com/repos/deep-cover/deep-cover/branches{/branch}","tags_url":"https://api.github.com/repos/deep-cover/deep-cover/tags","blobs_url":"https://api.github.com/repos/deep-cover/deep-cover/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/deep-cover/deep-cover/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/deep-cover/deep-cover/git/refs{/sha}","trees_url":"https://api.github.com/repos/deep-cover/deep-cover/git/trees{/sha}","statuses_url":"https://api.github.com/repos/deep-cover/deep-cover/statuses/{sha}","languages_url":"https://api.github.com/repos/deep-cover/deep-cover/languages","stargazers_url":"https://api.github.com/repos/deep-cover/deep-cover/stargazers","contributors_url":"https://api.github.com/repos/deep-cover/deep-cover/contributors","subscribers_url":"https://api.github.com/repos/deep-cover/deep-cover/subscribers","subscription_url":"https://api.github.com/repos/deep-cover/deep-cover/subscription","commits_url":"https://api.github.com/repos/deep-cover/deep-cover/commits{/sha}","git_commits_url":"https://api.github.com/repos/deep-cover/deep-cover/git/commits{/sha}","comments_url":"https://api.github.com/repos/deep-cover/deep-cover/comments{/number}","issue_comment_url":"https://api.github.com/repos/deep-cover/deep-cover/issues/comments{/number}","contents_url":"https://api.github.com/repos/deep-cover/deep-cover/contents/{+path}","compare_url":"https://api.github.com/repos/deep-cover/deep-cover/compare/{base}...{head}","merges_url":"https://api.github.com/repos/deep-cover/deep-cover/merges","archive_url":"https://api.github.com/repos/deep-cover/deep-cover/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/deep-cover/deep-cover/downloads","issues_url":"https://api.github.com/repos/deep-cover/deep-cover/issues{/number}","pulls_url":"https://api.github.com/repos/deep-cover/deep-cover/pulls{/number}","milestones_url":"https://api.github.com/repos/deep-cover/deep-cover/milestones{/number}","notifications_url":"https://api.github.com/repos/deep-cover/deep-cover/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/deep-cover/deep-cover/labels{/name}","releases_url":"https://api.github.com/repos/deep-cover/deep-cover/releases{/id}","deployments_url":"https://api.github.com/repos/deep-cover/deep-cover/deployments","created_at":"2017-09-21T22:33:30Z","updated_at":"2018-05-29T17:04:15Z","pushed_at":"2018-05-29T23:47:02Z","git_url":"git://github.com/deep-cover/deep-cover.git","ssh_url":"git@github.com:deep-cover/deep-cover.git","clone_url":"https://github.com/deep-cover/deep-cover.git","svn_url":"https://github.com/deep-cover/deep-cover","homepage":"","size":1321,"stargazers_count":36,"watchers_count":36,"language":"Ruby","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":6,"mirror_url":null,"archived":false,"open_issues_count":2,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit"},"forks":6,"open_issues":2,"watchers":36,"default_branch":"master"}},"base":{"label":"deep-cover:master","ref":"master","sha":"e6e23aa1798fd2b6a70d8fd039a6ba98c7bddcbe","user":{"login":"deep-cover","id":32180687,"avatar_url":"https://avatars0.githubusercontent.com/u/32180687?v=4","gravatar_id":"","url":"https://api.github.com/users/deep-cover","html_url":"https://github.com/deep-cover","followers_url":"https://api.github.com/users/deep-cover/followers","following_url":"https://api.github.com/users/deep-cover/following{/other_user}","gists_url":"https://api.github.com/users/deep-cover/gists{/gist_id}","starred_url":"https://api.github.com/users/deep-cover/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/deep-cover/subscriptions","organizations_url":"https://api.github.com/users/deep-cover/orgs","repos_url":"https://api.github.com/users/deep-cover/repos","events_url":"https://api.github.com/users/deep-cover/events{/privacy}","received_events_url":"https://api.github.com/users/deep-cover/received_events","type":"Organization","site_admin":false},"repo":{"id":104405256,"name":"deep-cover","full_name":"deep-cover/deep-cover","owner":{"login":"deep-cover","id":32180687,"avatar_url":"https://avatars0.githubusercontent.com/u/32180687?v=4","gravatar_id":"","url":"https://api.github.com/users/deep-cover","html_url":"https://github.com/deep-cover","followers_url":"https://api.github.com/users/deep-cover/followers","following_url":"https://api.github.com/users/deep-cover/following{/other_user}","gists_url":"https://api.github.com/users/deep-cover/gists{/gist_id}","starred_url":"https://api.github.com/users/deep-cover/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/deep-cover/subscriptions","organizations_url":"https://api.github.com/users/deep-cover/orgs","repos_url":"https://api.github.com/users/deep-cover/repos","events_url":"https://api.github.com/users/deep-cover/events{/privacy}","received_events_url":"https://api.github.com/users/deep-cover/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/deep-cover/deep-cover","description":"The best coverage tool for Ruby code","fork":false,"url":"https://api.github.com/repos/deep-cover/deep-cover","forks_url":"https://api.github.com/repos/deep-cover/deep-cover/forks","keys_url":"https://api.github.com/repos/deep-cover/deep-cover/keys{/key_id}","collaborators_url":"https://api.github.com/repos/deep-cover/deep-cover/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/deep-cover/deep-cover/teams","hooks_url":"https://api.github.com/repos/deep-cover/deep-cover/hooks","issue_events_url":"https://api.github.com/repos/deep-cover/deep-cover/issues/events{/number}","events_url":"https://api.github.com/repos/deep-cover/deep-cover/events","assignees_url":"https://api.github.com/repos/deep-cover/deep-cover/assignees{/user}","branches_url":"https://api.github.com/repos/deep-cover/deep-cover/branches{/branch}","tags_url":"https://api.github.com/repos/deep-cover/deep-cover/tags","blobs_url":"https://api.github.com/repos/deep-cover/deep-cover/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/deep-cover/deep-cover/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/deep-cover/deep-cover/git/refs{/sha}","trees_url":"https://api.github.com/repos/deep-cover/deep-cover/git/trees{/sha}","statuses_url":"https://api.github.com/repos/deep-cover/deep-cover/statuses/{sha}","languages_url":"https://api.github.com/repos/deep-cover/deep-cover/languages","stargazers_url":"https://api.github.com/repos/deep-cover/deep-cover/stargazers","contributors_url":"https://api.github.com/repos/deep-cover/deep-cover/contributors","subscribers_url":"https://api.github.com/repos/deep-cover/deep-cover/subscribers","subscription_url":"https://api.github.com/repos/deep-cover/deep-cover/subscription","commits_url":"https://api.github.com/repos/deep-cover/deep-cover/commits{/sha}","git_commits_url":"https://api.github.com/repos/deep-cover/deep-cover/git/commits{/sha}","comments_url":"https://api.github.com/repos/deep-cover/deep-cover/comments{/number}","issue_comment_url":"https://api.github.com/repos/deep-cover/deep-cover/issues/comments{/number}","contents_url":"https://api.github.com/repos/deep-cover/deep-cover/contents/{+path}","compare_url":"https://api.github.com/repos/deep-cover/deep-cover/compare/{base}...{head}","merges_url":"https://api.github.com/repos/deep-cover/deep-cover/merges","archive_url":"https://api.github.com/repos/deep-cover/deep-cover/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/deep-cover/deep-cover/downloads","issues_url":"https://api.github.com/repos/deep-cover/deep-cover/issues{/number}","pulls_url":"https://api.github.com/repos/deep-cover/deep-cover/pulls{/number}","milestones_url":"https://api.github.com/repos/deep-cover/deep-cover/milestones{/number}","notifications_url":"https://api.github.com/repos/deep-cover/deep-cover/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/deep-cover/deep-cover/labels{/name}","releases_url":"https://api.github.com/repos/deep-cover/deep-cover/releases{/id}","deployments_url":"https://api.github.com/repos/deep-cover/deep-cover/deployments","created_at":"2017-09-21T22:33:30Z","updated_at":"2018-05-29T17:04:15Z","pushed_at":"2018-05-29T23:47:02Z","git_url":"git://github.com/deep-cover/deep-cover.git","ssh_url":"git@github.com:deep-cover/deep-cover.git","clone_url":"https://github.com/deep-cover/deep-cover.git","svn_url":"https://github.com/deep-cover/deep-cover","homepage":"","size":1321,"stargazers_count":36,"watchers_count":36,"language":"Ruby","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":6,"mirror_url":null,"archived":false,"open_issues_count":2,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit"},"forks":6,"open_issues":2,"watchers":36,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/deep-cover/deep-cover/pulls/29"},"html":{"href":"https://github.com/deep-cover/deep-cover/pull/29"},"issue":{"href":"https://api.github.com/repos/deep-cover/deep-cover/issues/29"},"comments":{"href":"https://api.github.com/repos/deep-cover/deep-cover/issues/29/comments"},"review_comments":{"href":"https://api.github.com/repos/deep-cover/deep-cover/pulls/29/comments"},"review_comment":{"href":"https://api.github.com/repos/deep-cover/deep-cover/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/deep-cover/deep-cover/pulls/29/commits"},"statuses":{"href":"https://api.github.com/repos/deep-cover/deep-cover/statuses/fcd4a43670618f1d3d7e9848956411eb6a22e9a6"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"MaxLap"}}