{"action":"created","comment":{"url":"https://api.github.com/repos/jordansissel/ruby-filewatch/pulls/comments/28155979","id":28155979,"diff_hunk":"@@ -0,0 +1,65 @@\n+# code downloaded from Ruby on Rails 4.2.1\n+# https://raw.githubusercontent.com/rails/rails/v4.2.1/activesupport/lib/active_support/core_ext/file/atomic.rb\n+require 'fileutils'\n+\n+class File\n+  # Write to a file atomically. Useful for situations where you don't\n+  # want other processes or threads to see half-written files.\n+  #\n+  #   File.atomic_write('important.file') do |file|\n+  #     file.write('hello')\n+  #   end\n+  #\n+  # If your temp directory is not on the same filesystem as the file you're\n+  # trying to write, you can provide a different temporary directory.\n+  #\n+  #   File.atomic_write('/data/something.important', '/data/tmp') do |file|\n+  #     file.write('hello')\n+  #   end\n+  def self.atomic_write(file_name)\n+\n+    if File.exist?(file_name)\n+      # Get original file permissions\n+      old_stat = stat(file_name)\n+    else\n+      # If not possible, probe which are the default permissions in the\n+      # destination directory.\n+      old_stat = probe_stat_in(dirname(file_name))\n+    end\n+\n+    mode = old_stat ? old_stat.mode : nil\n+\n+    # Create temporary file with identical permissions\n+    temp_file = File.new(rand_filename(file_name), \"w\", mode)\n+    temp_file.binmode\n+    return_val = yield temp_file\n+    temp_file.close\n+\n+    # Overwrite original file with temp file\n+    File.rename(temp_file.path, file_name)\n+\n+    # Unable to get permissions of the original file => return\n+    return return_val if old_stat.nil?\n+\n+    # Set correct uid/gid on new file\n+    chown(old_stat.uid, old_stat.gid, file_name) if old_stat\n+\n+    return_val\n+  end\n+\n+  # Private utility method.\n+  def self.probe_stat_in(dir) #:nodoc:\n+    basename = rand_filename(\".permissions_check\")\n+    file_name = join(dir, basename)\n+    FileUtils.touch(file_name)\n+    stat(file_name)\n+  rescue\n+    # ...\n+  ensure\n+    FileUtils.rm_f(file_name) if file_name","path":"lib/filewatch/helper.rb","position":59,"original_position":59,"commit_id":"5320a0ad83cbadf1a5cce8faefbd0de4c22702c8","original_commit_id":"5320a0ad83cbadf1a5cce8faefbd0de4c22702c8","user":{"login":"ph","id":640,"avatar_url":"https://avatars.githubusercontent.com/u/640?v=3","gravatar_id":"","url":"https://api.github.com/users/ph","html_url":"https://github.com/ph","followers_url":"https://api.github.com/users/ph/followers","following_url":"https://api.github.com/users/ph/following{/other_user}","gists_url":"https://api.github.com/users/ph/gists{/gist_id}","starred_url":"https://api.github.com/users/ph/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ph/subscriptions","organizations_url":"https://api.github.com/users/ph/orgs","repos_url":"https://api.github.com/users/ph/repos","events_url":"https://api.github.com/users/ph/events{/privacy}","received_events_url":"https://api.github.com/users/ph/received_events","type":"User","site_admin":false},"body":"I am wondering here if we should check against `File.exist?` instead of nil? ","created_at":"2015-04-10T15:48:54Z","updated_at":"2015-04-10T15:48:54Z","html_url":"https://github.com/jordansissel/ruby-filewatch/pull/54#discussion_r28155979","pull_request_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/pulls/54","_links":{"self":{"href":"https://api.github.com/repos/jordansissel/ruby-filewatch/pulls/comments/28155979"},"html":{"href":"https://github.com/jordansissel/ruby-filewatch/pull/54#discussion_r28155979"},"pull_request":{"href":"https://api.github.com/repos/jordansissel/ruby-filewatch/pulls/54"}}},"pull_request":{"url":"https://api.github.com/repos/jordansissel/ruby-filewatch/pulls/54","id":32976979,"html_url":"https://github.com/jordansissel/ruby-filewatch/pull/54","diff_url":"https://github.com/jordansissel/ruby-filewatch/pull/54.diff","patch_url":"https://github.com/jordansissel/ruby-filewatch/pull/54.patch","issue_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/issues/54","number":54,"state":"open","locked":false,"title":"change _sincedb_write to use Dir.tmpdir","user":{"login":"jsvd","id":31809,"avatar_url":"https://avatars.githubusercontent.com/u/31809?v=3","gravatar_id":"","url":"https://api.github.com/users/jsvd","html_url":"https://github.com/jsvd","followers_url":"https://api.github.com/users/jsvd/followers","following_url":"https://api.github.com/users/jsvd/following{/other_user}","gists_url":"https://api.github.com/users/jsvd/gists{/gist_id}","starred_url":"https://api.github.com/users/jsvd/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jsvd/subscriptions","organizations_url":"https://api.github.com/users/jsvd/orgs","repos_url":"https://api.github.com/users/jsvd/repos","events_url":"https://api.github.com/users/jsvd/events{/privacy}","received_events_url":"https://api.github.com/users/jsvd/received_events","type":"User","site_admin":false},"body":"Currently, in order to prevent sincedb corruption during _sincedb_write, the new sincedb state is written in a temporary file in the same path as sincedb, then replaced. However this fails in certain situations:\r\n\r\na) sincedb_path can point to \"/dev/null\". replacing it will result in a permission denied\r\nb) the sincedb file can be in a directory where the user cannot write to, only modify that single file.\r\n\r\nSolution: \r\na) skip sincedb_write if sincedb_path is \"/dev/null\"\r\nb) write the temporary file in Dir.tmpdir, then move the file\r\n\r\nThis uses File#atomic_write implementation extracted from Ruby on Rails, with some modifications\r\n\r\naddresses https://github.com/elastic/logstash/issues/2964, https://github.com/elastic/logstash/issues/2935, https://github.com/elastic/logstash/issues/2882, https://github.com/logstash-plugins/logstash-input-file/issues/16","created_at":"2015-04-09T17:21:48Z","updated_at":"2015-04-10T15:48:54Z","closed_at":null,"merged_at":null,"merge_commit_sha":"97852c0afb22d34a5e96bd6bb2d360c4a2f82749","assignee":{"login":"ph","id":640,"avatar_url":"https://avatars.githubusercontent.com/u/640?v=3","gravatar_id":"","url":"https://api.github.com/users/ph","html_url":"https://github.com/ph","followers_url":"https://api.github.com/users/ph/followers","following_url":"https://api.github.com/users/ph/following{/other_user}","gists_url":"https://api.github.com/users/ph/gists{/gist_id}","starred_url":"https://api.github.com/users/ph/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ph/subscriptions","organizations_url":"https://api.github.com/users/ph/orgs","repos_url":"https://api.github.com/users/ph/repos","events_url":"https://api.github.com/users/ph/events{/privacy}","received_events_url":"https://api.github.com/users/ph/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/pulls/54/commits","review_comments_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/pulls/54/comments","review_comment_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/pulls/comments{/number}","comments_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/issues/54/comments","statuses_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/statuses/5320a0ad83cbadf1a5cce8faefbd0de4c22702c8","head":{"label":"jsvd:fix_sincedb_atomic_write","ref":"fix_sincedb_atomic_write","sha":"5320a0ad83cbadf1a5cce8faefbd0de4c22702c8","user":{"login":"jsvd","id":31809,"avatar_url":"https://avatars.githubusercontent.com/u/31809?v=3","gravatar_id":"","url":"https://api.github.com/users/jsvd","html_url":"https://github.com/jsvd","followers_url":"https://api.github.com/users/jsvd/followers","following_url":"https://api.github.com/users/jsvd/following{/other_user}","gists_url":"https://api.github.com/users/jsvd/gists{/gist_id}","starred_url":"https://api.github.com/users/jsvd/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jsvd/subscriptions","organizations_url":"https://api.github.com/users/jsvd/orgs","repos_url":"https://api.github.com/users/jsvd/repos","events_url":"https://api.github.com/users/jsvd/events{/privacy}","received_events_url":"https://api.github.com/users/jsvd/received_events","type":"User","site_admin":false},"repo":{"id":30717360,"name":"ruby-filewatch","full_name":"jsvd/ruby-filewatch","owner":{"login":"jsvd","id":31809,"avatar_url":"https://avatars.githubusercontent.com/u/31809?v=3","gravatar_id":"","url":"https://api.github.com/users/jsvd","html_url":"https://github.com/jsvd","followers_url":"https://api.github.com/users/jsvd/followers","following_url":"https://api.github.com/users/jsvd/following{/other_user}","gists_url":"https://api.github.com/users/jsvd/gists{/gist_id}","starred_url":"https://api.github.com/users/jsvd/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jsvd/subscriptions","organizations_url":"https://api.github.com/users/jsvd/orgs","repos_url":"https://api.github.com/users/jsvd/repos","events_url":"https://api.github.com/users/jsvd/events{/privacy}","received_events_url":"https://api.github.com/users/jsvd/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/jsvd/ruby-filewatch","description":"ruby api for file watching and tailing.","fork":true,"url":"https://api.github.com/repos/jsvd/ruby-filewatch","forks_url":"https://api.github.com/repos/jsvd/ruby-filewatch/forks","keys_url":"https://api.github.com/repos/jsvd/ruby-filewatch/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jsvd/ruby-filewatch/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jsvd/ruby-filewatch/teams","hooks_url":"https://api.github.com/repos/jsvd/ruby-filewatch/hooks","issue_events_url":"https://api.github.com/repos/jsvd/ruby-filewatch/issues/events{/number}","events_url":"https://api.github.com/repos/jsvd/ruby-filewatch/events","assignees_url":"https://api.github.com/repos/jsvd/ruby-filewatch/assignees{/user}","branches_url":"https://api.github.com/repos/jsvd/ruby-filewatch/branches{/branch}","tags_url":"https://api.github.com/repos/jsvd/ruby-filewatch/tags","blobs_url":"https://api.github.com/repos/jsvd/ruby-filewatch/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jsvd/ruby-filewatch/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jsvd/ruby-filewatch/git/refs{/sha}","trees_url":"https://api.github.com/repos/jsvd/ruby-filewatch/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jsvd/ruby-filewatch/statuses/{sha}","languages_url":"https://api.github.com/repos/jsvd/ruby-filewatch/languages","stargazers_url":"https://api.github.com/repos/jsvd/ruby-filewatch/stargazers","contributors_url":"https://api.github.com/repos/jsvd/ruby-filewatch/contributors","subscribers_url":"https://api.github.com/repos/jsvd/ruby-filewatch/subscribers","subscription_url":"https://api.github.com/repos/jsvd/ruby-filewatch/subscription","commits_url":"https://api.github.com/repos/jsvd/ruby-filewatch/commits{/sha}","git_commits_url":"https://api.github.com/repos/jsvd/ruby-filewatch/git/commits{/sha}","comments_url":"https://api.github.com/repos/jsvd/ruby-filewatch/comments{/number}","issue_comment_url":"https://api.github.com/repos/jsvd/ruby-filewatch/issues/comments{/number}","contents_url":"https://api.github.com/repos/jsvd/ruby-filewatch/contents/{+path}","compare_url":"https://api.github.com/repos/jsvd/ruby-filewatch/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jsvd/ruby-filewatch/merges","archive_url":"https://api.github.com/repos/jsvd/ruby-filewatch/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jsvd/ruby-filewatch/downloads","issues_url":"https://api.github.com/repos/jsvd/ruby-filewatch/issues{/number}","pulls_url":"https://api.github.com/repos/jsvd/ruby-filewatch/pulls{/number}","milestones_url":"https://api.github.com/repos/jsvd/ruby-filewatch/milestones{/number}","notifications_url":"https://api.github.com/repos/jsvd/ruby-filewatch/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jsvd/ruby-filewatch/labels{/name}","releases_url":"https://api.github.com/repos/jsvd/ruby-filewatch/releases{/id}","created_at":"2015-02-12T18:36:39Z","updated_at":"2015-02-12T18:36:40Z","pushed_at":"2015-04-10T12:13:29Z","git_url":"git://github.com/jsvd/ruby-filewatch.git","ssh_url":"git@github.com:jsvd/ruby-filewatch.git","clone_url":"https://github.com/jsvd/ruby-filewatch.git","svn_url":"https://github.com/jsvd/ruby-filewatch","homepage":"","size":244,"stargazers_count":0,"watchers_count":0,"language":"Ruby","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"jordansissel:master","ref":"master","sha":"69f94fe2634be8bc5a88ecfd2ebac99998a9bc94","user":{"login":"jordansissel","id":131818,"avatar_url":"https://avatars.githubusercontent.com/u/131818?v=3","gravatar_id":"","url":"https://api.github.com/users/jordansissel","html_url":"https://github.com/jordansissel","followers_url":"https://api.github.com/users/jordansissel/followers","following_url":"https://api.github.com/users/jordansissel/following{/other_user}","gists_url":"https://api.github.com/users/jordansissel/gists{/gist_id}","starred_url":"https://api.github.com/users/jordansissel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jordansissel/subscriptions","organizations_url":"https://api.github.com/users/jordansissel/orgs","repos_url":"https://api.github.com/users/jordansissel/repos","events_url":"https://api.github.com/users/jordansissel/events{/privacy}","received_events_url":"https://api.github.com/users/jordansissel/received_events","type":"User","site_admin":false},"repo":{"id":1442359,"name":"ruby-filewatch","full_name":"jordansissel/ruby-filewatch","owner":{"login":"jordansissel","id":131818,"avatar_url":"https://avatars.githubusercontent.com/u/131818?v=3","gravatar_id":"","url":"https://api.github.com/users/jordansissel","html_url":"https://github.com/jordansissel","followers_url":"https://api.github.com/users/jordansissel/followers","following_url":"https://api.github.com/users/jordansissel/following{/other_user}","gists_url":"https://api.github.com/users/jordansissel/gists{/gist_id}","starred_url":"https://api.github.com/users/jordansissel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jordansissel/subscriptions","organizations_url":"https://api.github.com/users/jordansissel/orgs","repos_url":"https://api.github.com/users/jordansissel/repos","events_url":"https://api.github.com/users/jordansissel/events{/privacy}","received_events_url":"https://api.github.com/users/jordansissel/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/jordansissel/ruby-filewatch","description":"ruby api for file watching and tailing.","fork":false,"url":"https://api.github.com/repos/jordansissel/ruby-filewatch","forks_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/forks","keys_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/teams","hooks_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/hooks","issue_events_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/issues/events{/number}","events_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/events","assignees_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/assignees{/user}","branches_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/branches{/branch}","tags_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/tags","blobs_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/git/refs{/sha}","trees_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/statuses/{sha}","languages_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/languages","stargazers_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/stargazers","contributors_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/contributors","subscribers_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/subscribers","subscription_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/subscription","commits_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/commits{/sha}","git_commits_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/git/commits{/sha}","comments_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/comments{/number}","issue_comment_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/issues/comments{/number}","contents_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/contents/{+path}","compare_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/merges","archive_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/downloads","issues_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/issues{/number}","pulls_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/pulls{/number}","milestones_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/milestones{/number}","notifications_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/labels{/name}","releases_url":"https://api.github.com/repos/jordansissel/ruby-filewatch/releases{/id}","created_at":"2011-03-05T05:57:20Z","updated_at":"2015-02-26T13:16:30Z","pushed_at":"2015-04-10T12:13:29Z","git_url":"git://github.com/jordansissel/ruby-filewatch.git","ssh_url":"git@github.com:jordansissel/ruby-filewatch.git","clone_url":"https://github.com/jordansissel/ruby-filewatch.git","svn_url":"https://github.com/jordansissel/ruby-filewatch","homepage":"","size":495,"stargazers_count":63,"watchers_count":63,"language":"Ruby","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":45,"mirror_url":null,"open_issues_count":26,"forks":45,"open_issues":26,"watchers":63,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/jordansissel/ruby-filewatch/pulls/54"},"html":{"href":"https://github.com/jordansissel/ruby-filewatch/pull/54"},"issue":{"href":"https://api.github.com/repos/jordansissel/ruby-filewatch/issues/54"},"comments":{"href":"https://api.github.com/repos/jordansissel/ruby-filewatch/issues/54/comments"},"review_comments":{"href":"https://api.github.com/repos/jordansissel/ruby-filewatch/pulls/54/comments"},"review_comment":{"href":"https://api.github.com/repos/jordansissel/ruby-filewatch/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/jordansissel/ruby-filewatch/pulls/54/commits"},"statuses":{"href":"https://api.github.com/repos/jordansissel/ruby-filewatch/statuses/5320a0ad83cbadf1a5cce8faefbd0de4c22702c8"}}}}