{"action":"created","comment":{"url":"https://api.github.com/repos/puppetlabs/leatherman/pulls/comments/32965223","id":32965223,"diff_hunk":"@@ -0,0 +1,162 @@\n+#include <leatherman/file_util/file.hpp>\n+#include <boost/nowide/fstream.hpp>\n+#include <sstream>\n+#include <leatherman/logging/logging.hpp>\n+\n+using namespace std;\n+\n+namespace leatherman { namespace file_util {\n+\n+    bool each_line(string const& path, function<bool(string&)> callback)\n+    {\n+        boost::nowide::ifstream in(path.c_str());\n+        if (!in) {\n+            return false;\n+        }\n+\n+        string line;\n+        while (getline(in, line)) {\n+            if (!callback(line)) {\n+                break;\n+            }\n+        }\n+        return true;\n+    }\n+\n+    string read(string const& path)\n+    {\n+        string contents;\n+        if (!read(path, contents)) {\n+            return {};\n+        }\n+        return contents;\n+    }\n+\n+    bool read(string const& path, string& contents)\n+    {\n+        boost::nowide::ifstream in(path.c_str(), ios::in | ios::binary);\n+        ostringstream buffer;\n+        if (!in) {\n+            return false;\n+        }\n+        buffer << in.rdbuf();\n+        contents = buffer.str();\n+        return true;\n+    }\n+\n+    std::string shellExpand(std::string txt) {\n+        // This will store the expansion outcome\n+        wordexp_t result;\n+\n+        // Expand and check the success\n+        if (wordexp(txt.c_str(), &result, 0) != 0 || result.we_wordc == 0) {\n+            wordfree(&result);\n+            return \"\";\n+        }\n+\n+        // Get the expanded text and free the memory\n+        std::string expanded_txt { result.we_wordv[0] };\n+        wordfree(&result);\n+        return expanded_txt;\n+    }\n+\n+    bool fileExists(const std::string& file_path) {\n+        bool exists { false };\n+        if (file_path.empty()) {\n+            LOG_WARNING(\"file path is an empty string\");\n+        } else {\n+            std::ifstream file_stream { file_path };\n+            exists = file_stream.good();\n+            file_stream.close();\n+        }\n+        return exists;\n+    }\n+\n+    void removeFile(const std::string& file_path) {\n+        if (file_util::fileExists(file_path)) {\n+            if (std::remove(file_path.c_str()) != 0) {\n+                throw file_error { \"failed to remove \" + file_path };\n+            }\n+        }\n+    }\n+\n+    void streamToFile(const std::string& text,\n+                      const std::string& file_path,\n+                      std::ios_base::openmode mode) {\n+        std::ofstream ofs;\n+        std::string tmp_name = file_path + \"~\";\n+        ofs.open(tmp_name, mode);\n+        if (!ofs.is_open()) {\n+            throw file_error { \"failed to open \" + file_path };\n+        }\n+        ofs << text;\n+        ofs.close();\n+        rename(tmp_name.data(), file_path.data());\n+    }\n+\n+    void writeToFile(const std::string& text, const std::string& file_path) {\n+        streamToFile(text, file_path, std::ofstream::out | std::ofstream::trunc);\n+    }\n+\n+    std::string readFileAsString(std::string path) {\n+        std::string content = \"\";\n+\n+        if (!fileExists(path)) {\n+            return content;\n+        }\n+\n+        std::ifstream file { path };\n+        std::string buffer;\n+\n+        while (std::getline(file, buffer)) {\n+            content += buffer;\n+            content.push_back('\\n');\n+        }\n+\n+        return content;\n+    }\n+\n+    std::string tildeExpand(std::string path) {\n+        if (path[0] == '~' && (path.size() == 1 || path[1] == '/')) {\n+            #ifdef _WIN32\n+                std::string result { getenv(\"USERPROFILE\") };\n+            #else\n+                std::string result { getenv(\"HOME\") };\n+            #endif\n+\n+            result.append(path.begin() + 1, path.end());\n+            return result;\n+        }\n+        return path;\n+    }\n+\n+    std::string shellQuote(std::string path) {\n+        std::stringstream ss;\n+        ss << boost::io::quoted(path);","path":"file_util/src/file.cc","position":135,"original_position":135,"commit_id":"37bd746febefbee4268a5f5312c6c6c71b9dd278","original_commit_id":"37bd746febefbee4268a5f5312c6c6c71b9dd278","user":{"login":"MikaelSmith","id":8162496,"avatar_url":"https://avatars.githubusercontent.com/u/8162496?v=3","gravatar_id":"","url":"https://api.github.com/users/MikaelSmith","html_url":"https://github.com/MikaelSmith","followers_url":"https://api.github.com/users/MikaelSmith/followers","following_url":"https://api.github.com/users/MikaelSmith/following{/other_user}","gists_url":"https://api.github.com/users/MikaelSmith/gists{/gist_id}","starred_url":"https://api.github.com/users/MikaelSmith/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/MikaelSmith/subscriptions","organizations_url":"https://api.github.com/users/MikaelSmith/orgs","repos_url":"https://api.github.com/users/MikaelSmith/repos","events_url":"https://api.github.com/users/MikaelSmith/events{/privacy}","received_events_url":"https://api.github.com/users/MikaelSmith/received_events","type":"User","site_admin":false},"body":"What's the header file for `boost::io`?","created_at":"2015-06-22T18:13:29Z","updated_at":"2015-06-22T18:13:29Z","html_url":"https://github.com/puppetlabs/leatherman/pull/28#discussion_r32965223","pull_request_url":"https://api.github.com/repos/puppetlabs/leatherman/pulls/28","_links":{"self":{"href":"https://api.github.com/repos/puppetlabs/leatherman/pulls/comments/32965223"},"html":{"href":"https://github.com/puppetlabs/leatherman/pull/28#discussion_r32965223"},"pull_request":{"href":"https://api.github.com/repos/puppetlabs/leatherman/pulls/28"}}},"pull_request":{"url":"https://api.github.com/repos/puppetlabs/leatherman/pulls/28","id":38248978,"html_url":"https://github.com/puppetlabs/leatherman/pull/28","diff_url":"https://github.com/puppetlabs/leatherman/pull/28.diff","patch_url":"https://github.com/puppetlabs/leatherman/pull/28.patch","issue_url":"https://api.github.com/repos/puppetlabs/leatherman/issues/28","number":28,"state":"open","locked":false,"title":"(LTH-17) Extract various file and directory utility classes to LTH","user":{"login":"Magisus","id":839145,"avatar_url":"https://avatars.githubusercontent.com/u/839145?v=3","gravatar_id":"","url":"https://api.github.com/users/Magisus","html_url":"https://github.com/Magisus","followers_url":"https://api.github.com/users/Magisus/followers","following_url":"https://api.github.com/users/Magisus/following{/other_user}","gists_url":"https://api.github.com/users/Magisus/gists{/gist_id}","starred_url":"https://api.github.com/users/Magisus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Magisus/subscriptions","organizations_url":"https://api.github.com/users/Magisus/orgs","repos_url":"https://api.github.com/users/Magisus/repos","events_url":"https://api.github.com/users/Magisus/events{/privacy}","received_events_url":"https://api.github.com/users/Magisus/received_events","type":"User","site_admin":false},"body":"Extracts the file utility classes from facter, cthun-agent, and Pegasus to Leatherman.","created_at":"2015-06-22T16:16:36Z","updated_at":"2015-06-22T18:13:29Z","closed_at":null,"merged_at":null,"merge_commit_sha":"0a45c52e185da0719134212665daf12e3fcfa0e7","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/puppetlabs/leatherman/pulls/28/commits","review_comments_url":"https://api.github.com/repos/puppetlabs/leatherman/pulls/28/comments","review_comment_url":"https://api.github.com/repos/puppetlabs/leatherman/pulls/comments{/number}","comments_url":"https://api.github.com/repos/puppetlabs/leatherman/issues/28/comments","statuses_url":"https://api.github.com/repos/puppetlabs/leatherman/statuses/37bd746febefbee4268a5f5312c6c6c71b9dd278","head":{"label":"Magisus:file-util","ref":"file-util","sha":"37bd746febefbee4268a5f5312c6c6c71b9dd278","user":{"login":"Magisus","id":839145,"avatar_url":"https://avatars.githubusercontent.com/u/839145?v=3","gravatar_id":"","url":"https://api.github.com/users/Magisus","html_url":"https://github.com/Magisus","followers_url":"https://api.github.com/users/Magisus/followers","following_url":"https://api.github.com/users/Magisus/following{/other_user}","gists_url":"https://api.github.com/users/Magisus/gists{/gist_id}","starred_url":"https://api.github.com/users/Magisus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Magisus/subscriptions","organizations_url":"https://api.github.com/users/Magisus/orgs","repos_url":"https://api.github.com/users/Magisus/repos","events_url":"https://api.github.com/users/Magisus/events{/privacy}","received_events_url":"https://api.github.com/users/Magisus/received_events","type":"User","site_admin":false},"repo":{"id":37147341,"name":"leatherman","full_name":"Magisus/leatherman","owner":{"login":"Magisus","id":839145,"avatar_url":"https://avatars.githubusercontent.com/u/839145?v=3","gravatar_id":"","url":"https://api.github.com/users/Magisus","html_url":"https://github.com/Magisus","followers_url":"https://api.github.com/users/Magisus/followers","following_url":"https://api.github.com/users/Magisus/following{/other_user}","gists_url":"https://api.github.com/users/Magisus/gists{/gist_id}","starred_url":"https://api.github.com/users/Magisus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Magisus/subscriptions","organizations_url":"https://api.github.com/users/Magisus/orgs","repos_url":"https://api.github.com/users/Magisus/repos","events_url":"https://api.github.com/users/Magisus/events{/privacy}","received_events_url":"https://api.github.com/users/Magisus/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/Magisus/leatherman","description":"A collection of C++ and CMake utility libraries.","fork":true,"url":"https://api.github.com/repos/Magisus/leatherman","forks_url":"https://api.github.com/repos/Magisus/leatherman/forks","keys_url":"https://api.github.com/repos/Magisus/leatherman/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Magisus/leatherman/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Magisus/leatherman/teams","hooks_url":"https://api.github.com/repos/Magisus/leatherman/hooks","issue_events_url":"https://api.github.com/repos/Magisus/leatherman/issues/events{/number}","events_url":"https://api.github.com/repos/Magisus/leatherman/events","assignees_url":"https://api.github.com/repos/Magisus/leatherman/assignees{/user}","branches_url":"https://api.github.com/repos/Magisus/leatherman/branches{/branch}","tags_url":"https://api.github.com/repos/Magisus/leatherman/tags","blobs_url":"https://api.github.com/repos/Magisus/leatherman/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Magisus/leatherman/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Magisus/leatherman/git/refs{/sha}","trees_url":"https://api.github.com/repos/Magisus/leatherman/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Magisus/leatherman/statuses/{sha}","languages_url":"https://api.github.com/repos/Magisus/leatherman/languages","stargazers_url":"https://api.github.com/repos/Magisus/leatherman/stargazers","contributors_url":"https://api.github.com/repos/Magisus/leatherman/contributors","subscribers_url":"https://api.github.com/repos/Magisus/leatherman/subscribers","subscription_url":"https://api.github.com/repos/Magisus/leatherman/subscription","commits_url":"https://api.github.com/repos/Magisus/leatherman/commits{/sha}","git_commits_url":"https://api.github.com/repos/Magisus/leatherman/git/commits{/sha}","comments_url":"https://api.github.com/repos/Magisus/leatherman/comments{/number}","issue_comment_url":"https://api.github.com/repos/Magisus/leatherman/issues/comments{/number}","contents_url":"https://api.github.com/repos/Magisus/leatherman/contents/{+path}","compare_url":"https://api.github.com/repos/Magisus/leatherman/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Magisus/leatherman/merges","archive_url":"https://api.github.com/repos/Magisus/leatherman/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Magisus/leatherman/downloads","issues_url":"https://api.github.com/repos/Magisus/leatherman/issues{/number}","pulls_url":"https://api.github.com/repos/Magisus/leatherman/pulls{/number}","milestones_url":"https://api.github.com/repos/Magisus/leatherman/milestones{/number}","notifications_url":"https://api.github.com/repos/Magisus/leatherman/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Magisus/leatherman/labels{/name}","releases_url":"https://api.github.com/repos/Magisus/leatherman/releases{/id}","created_at":"2015-06-09T17:31:19Z","updated_at":"2015-06-09T17:31:19Z","pushed_at":"2015-06-22T17:15:30Z","git_url":"git://github.com/Magisus/leatherman.git","ssh_url":"git@github.com:Magisus/leatherman.git","clone_url":"https://github.com/Magisus/leatherman.git","svn_url":"https://github.com/Magisus/leatherman","homepage":"","size":586,"stargazers_count":0,"watchers_count":0,"language":"C++","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":"puppetlabs:master","ref":"master","sha":"a3ddd9a2d37bd6c98a88759039237120d84ca1a8","user":{"login":"puppetlabs","id":234268,"avatar_url":"https://avatars.githubusercontent.com/u/234268?v=3","gravatar_id":"","url":"https://api.github.com/users/puppetlabs","html_url":"https://github.com/puppetlabs","followers_url":"https://api.github.com/users/puppetlabs/followers","following_url":"https://api.github.com/users/puppetlabs/following{/other_user}","gists_url":"https://api.github.com/users/puppetlabs/gists{/gist_id}","starred_url":"https://api.github.com/users/puppetlabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/puppetlabs/subscriptions","organizations_url":"https://api.github.com/users/puppetlabs/orgs","repos_url":"https://api.github.com/users/puppetlabs/repos","events_url":"https://api.github.com/users/puppetlabs/events{/privacy}","received_events_url":"https://api.github.com/users/puppetlabs/received_events","type":"Organization","site_admin":false},"repo":{"id":31226286,"name":"leatherman","full_name":"puppetlabs/leatherman","owner":{"login":"puppetlabs","id":234268,"avatar_url":"https://avatars.githubusercontent.com/u/234268?v=3","gravatar_id":"","url":"https://api.github.com/users/puppetlabs","html_url":"https://github.com/puppetlabs","followers_url":"https://api.github.com/users/puppetlabs/followers","following_url":"https://api.github.com/users/puppetlabs/following{/other_user}","gists_url":"https://api.github.com/users/puppetlabs/gists{/gist_id}","starred_url":"https://api.github.com/users/puppetlabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/puppetlabs/subscriptions","organizations_url":"https://api.github.com/users/puppetlabs/orgs","repos_url":"https://api.github.com/users/puppetlabs/repos","events_url":"https://api.github.com/users/puppetlabs/events{/privacy}","received_events_url":"https://api.github.com/users/puppetlabs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/puppetlabs/leatherman","description":"A collection of C++ and CMake utility libraries.","fork":false,"url":"https://api.github.com/repos/puppetlabs/leatherman","forks_url":"https://api.github.com/repos/puppetlabs/leatherman/forks","keys_url":"https://api.github.com/repos/puppetlabs/leatherman/keys{/key_id}","collaborators_url":"https://api.github.com/repos/puppetlabs/leatherman/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/puppetlabs/leatherman/teams","hooks_url":"https://api.github.com/repos/puppetlabs/leatherman/hooks","issue_events_url":"https://api.github.com/repos/puppetlabs/leatherman/issues/events{/number}","events_url":"https://api.github.com/repos/puppetlabs/leatherman/events","assignees_url":"https://api.github.com/repos/puppetlabs/leatherman/assignees{/user}","branches_url":"https://api.github.com/repos/puppetlabs/leatherman/branches{/branch}","tags_url":"https://api.github.com/repos/puppetlabs/leatherman/tags","blobs_url":"https://api.github.com/repos/puppetlabs/leatherman/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/puppetlabs/leatherman/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/puppetlabs/leatherman/git/refs{/sha}","trees_url":"https://api.github.com/repos/puppetlabs/leatherman/git/trees{/sha}","statuses_url":"https://api.github.com/repos/puppetlabs/leatherman/statuses/{sha}","languages_url":"https://api.github.com/repos/puppetlabs/leatherman/languages","stargazers_url":"https://api.github.com/repos/puppetlabs/leatherman/stargazers","contributors_url":"https://api.github.com/repos/puppetlabs/leatherman/contributors","subscribers_url":"https://api.github.com/repos/puppetlabs/leatherman/subscribers","subscription_url":"https://api.github.com/repos/puppetlabs/leatherman/subscription","commits_url":"https://api.github.com/repos/puppetlabs/leatherman/commits{/sha}","git_commits_url":"https://api.github.com/repos/puppetlabs/leatherman/git/commits{/sha}","comments_url":"https://api.github.com/repos/puppetlabs/leatherman/comments{/number}","issue_comment_url":"https://api.github.com/repos/puppetlabs/leatherman/issues/comments{/number}","contents_url":"https://api.github.com/repos/puppetlabs/leatherman/contents/{+path}","compare_url":"https://api.github.com/repos/puppetlabs/leatherman/compare/{base}...{head}","merges_url":"https://api.github.com/repos/puppetlabs/leatherman/merges","archive_url":"https://api.github.com/repos/puppetlabs/leatherman/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/puppetlabs/leatherman/downloads","issues_url":"https://api.github.com/repos/puppetlabs/leatherman/issues{/number}","pulls_url":"https://api.github.com/repos/puppetlabs/leatherman/pulls{/number}","milestones_url":"https://api.github.com/repos/puppetlabs/leatherman/milestones{/number}","notifications_url":"https://api.github.com/repos/puppetlabs/leatherman/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/puppetlabs/leatherman/labels{/name}","releases_url":"https://api.github.com/repos/puppetlabs/leatherman/releases{/id}","created_at":"2015-02-23T19:50:46Z","updated_at":"2015-05-13T14:58:37Z","pushed_at":"2015-06-22T17:15:30Z","git_url":"git://github.com/puppetlabs/leatherman.git","ssh_url":"git@github.com:puppetlabs/leatherman.git","clone_url":"https://github.com/puppetlabs/leatherman.git","svn_url":"https://github.com/puppetlabs/leatherman","homepage":"","size":740,"stargazers_count":0,"watchers_count":0,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":6,"mirror_url":null,"open_issues_count":2,"forks":6,"open_issues":2,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/puppetlabs/leatherman/pulls/28"},"html":{"href":"https://github.com/puppetlabs/leatherman/pull/28"},"issue":{"href":"https://api.github.com/repos/puppetlabs/leatherman/issues/28"},"comments":{"href":"https://api.github.com/repos/puppetlabs/leatherman/issues/28/comments"},"review_comments":{"href":"https://api.github.com/repos/puppetlabs/leatherman/pulls/28/comments"},"review_comment":{"href":"https://api.github.com/repos/puppetlabs/leatherman/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/puppetlabs/leatherman/pulls/28/commits"},"statuses":{"href":"https://api.github.com/repos/puppetlabs/leatherman/statuses/37bd746febefbee4268a5f5312c6c6c71b9dd278"}}}}