{"action":"created","comment":{"url":"https://api.github.com/repos/genome/genome/pulls/comments/22879476","id":22879476,"diff_hunk":"@@ -0,0 +1,190 @@\n+package Genome::Sys::ShellPipeline;\n+\n+use strict;\n+use warnings;\n+\n+use Genome;\n+use Try::Tiny qw(try catch finally);\n+use Carp qw(croak);\n+use File::Spec qw();\n+use List::AllUtils qw(any);\n+use File::Slurp qw(read_file write_file);\n+\n+class Genome::Sys::ShellPipeline {\n+    is => \"UR::Object\",\n+    attributes_have => [qw(is_input is_output is_optional)],\n+    has_input => {\n+        pre_commands => {\n+            is => \"ARRAY\",\n+            doc => \"Arrayref of commands to execute before the main pipe commands\",\n+            default_value => [],\n+        },\n+\n+        post_commands => {\n+            is => \"ARRAY\",\n+            doc => \"Arrayref of commands to execute after the main pipe commands\",\n+            default_value => [],\n+        },\n+\n+        pipe_commands => {\n+            is => \"ARRAY\",\n+            doc => \"Arrayref of commands to be piped together\",\n+        },\n+\n+        redirects => {\n+            is => \"Text\",\n+            doc => \"If specified, this text is appended to the concatenated pipe \" .\n+                \"commands without a pipe inbetween (e.g., > /tmp/stdout.txt 2>> /tmp/log)\",\n+            is_optional => 1,\n+        },\n+\n+        interpreter => {\n+            is => \"Text\",\n+            doc => \"The interpreter to use to run the pipe script\",\n+            default_value => \"/bin/bash\",\n+        },\n+\n+        script_path => {\n+            is => \"Text\",\n+            doc => \"If specified, write the pipe script to this path. \" .\n+                \"By default, it is written to a temporary location.\",\n+            is_optional => 1,\n+        },\n+    },\n+\n+    has_output => [\n+        return_codes => {\n+            is => \"ARRAY\",\n+            doc => \"The return code of each command in pipe_commands\",\n+        },\n+    ]\n+};\n+\n+sub _validate_params {\n+    my $self = shift;\n+\n+    my $commands = $self->pipe_commands;\n+    croak $self->error_message(\"pipe_commands argument must be a nonempty arrayref\")\n+        unless (ref $commands eq \"ARRAY\" && scalar @$commands > 0);\n+\n+    for my $x (qw(pre post)) {\n+        my $var = sprintf \"%s_commands\", $x;\n+        my $value = $self->$var;\n+        croak $self->error_message(\"$var argument must be undef or an arrayref\")\n+            unless !defined $value || ref $value eq \"ARRAY\";\n+    }\n+\n+}\n+\n+sub execute {\n+    my $self = shift;\n+\n+    $self->_validate_params;\n+\n+    my $script_path = $self->script_path;\n+    my $tmpdir = Genome::Sys->create_temp_directory;\n+    if (!defined $script_path) {\n+        $script_path = File::Spec->catfile($tmpdir, \"pipe.sh\");\n+    }\n+\n+    my $pipestatus_path = File::Spec->catfile($tmpdir, \"pipe.status\");\n+\n+    write_file($script_path, $self->script_text($pipestatus_path));\n+\n+    $self->debug_message(\n+        sprintf\n+            \"Executing script $script_path:\\n\\n\" .\n+            \"-------- BEGIN SCRIPT --------\\n%s\" .\n+            \"--------- END SCRIPT ---------\\n\",\n+            join(\"\", read_file($script_path))\n+        );\n+\n+\n+    chmod oct(755), $script_path;\n+\n+    try {\n+        Genome::Sys->shellcmd(cmd => $script_path);\n+    }\n+    catch {\n+        croak $self->error_message($_);\n+    }\n+    finally {\n+        $self->_check_pipestatus($pipestatus_path);","path":"lib/perl/Genome/Sys/ShellPipeline.pm","position":112,"original_position":112,"commit_id":"6806f8e92ad138d921e4002745cd8c21ea04dbda","original_commit_id":"6806f8e92ad138d921e4002745cd8c21ea04dbda","user":{"login":"nnutter","id":207011,"avatar_url":"https://avatars.githubusercontent.com/u/207011?v=3","gravatar_id":"","url":"https://api.github.com/users/nnutter","html_url":"https://github.com/nnutter","followers_url":"https://api.github.com/users/nnutter/followers","following_url":"https://api.github.com/users/nnutter/following{/other_user}","gists_url":"https://api.github.com/users/nnutter/gists{/gist_id}","starred_url":"https://api.github.com/users/nnutter/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nnutter/subscriptions","organizations_url":"https://api.github.com/users/nnutter/orgs","repos_url":"https://api.github.com/users/nnutter/repos","events_url":"https://api.github.com/users/nnutter/events{/privacy}","received_events_url":"https://api.github.com/users/nnutter/received_events","type":"User","site_admin":false},"body":"Since `_check_pipestatus` wants to throw exceptions I'm not sure this is a safe use of `finally`.  From the docs:\r\n\r\n> Furthermore exceptions in finally blocks are not trappable and are unable to influence the execution of your program. This is due to limitation of DESTROY-based scope guards, which finally is implemented on top of. This may change in a future version of Try::Tiny.\r\n\r\nI think `_check_pipestatus` can just be moved inside the `try` block?","created_at":"2015-01-13T17:47:09Z","updated_at":"2015-01-13T17:47:09Z","html_url":"https://github.com/genome/genome/pull/405#discussion_r22879476","pull_request_url":"https://api.github.com/repos/genome/genome/pulls/405","_links":{"self":{"href":"https://api.github.com/repos/genome/genome/pulls/comments/22879476"},"html":{"href":"https://github.com/genome/genome/pull/405#discussion_r22879476"},"pull_request":{"href":"https://api.github.com/repos/genome/genome/pulls/405"}}},"pull_request":{"url":"https://api.github.com/repos/genome/genome/pulls/405","id":27245597,"html_url":"https://github.com/genome/genome/pull/405","diff_url":"https://github.com/genome/genome/pull/405.diff","patch_url":"https://github.com/genome/genome/pull/405.patch","issue_url":"https://api.github.com/repos/genome/genome/issues/405","number":405,"state":"open","locked":false,"title":"Shellpipes","user":{"login":"tabbott","id":463300,"avatar_url":"https://avatars.githubusercontent.com/u/463300?v=3","gravatar_id":"","url":"https://api.github.com/users/tabbott","html_url":"https://github.com/tabbott","followers_url":"https://api.github.com/users/tabbott/followers","following_url":"https://api.github.com/users/tabbott/following{/other_user}","gists_url":"https://api.github.com/users/tabbott/gists{/gist_id}","starred_url":"https://api.github.com/users/tabbott/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tabbott/subscriptions","organizations_url":"https://api.github.com/users/tabbott/orgs","repos_url":"https://api.github.com/users/tabbott/repos","events_url":"https://api.github.com/users/tabbott/events{/privacy}","received_events_url":"https://api.github.com/users/tabbott/received_events","type":"User","site_admin":false},"body":"I need to make some commands involving bash pipes. This PR generalizes the code for dealing with pipe exit codes found in gmt bwa run-mem into its own (reusable) module.","created_at":"2015-01-13T03:19:51Z","updated_at":"2015-01-13T17:47:09Z","closed_at":null,"merged_at":null,"merge_commit_sha":"8275bd3e4ccad71f27fcd865989d457afb5a8e53","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/genome/genome/pulls/405/commits","review_comments_url":"https://api.github.com/repos/genome/genome/pulls/405/comments","review_comment_url":"https://api.github.com/repos/genome/genome/pulls/comments/{number}","comments_url":"https://api.github.com/repos/genome/genome/issues/405/comments","statuses_url":"https://api.github.com/repos/genome/genome/statuses/6806f8e92ad138d921e4002745cd8c21ea04dbda","head":{"label":"tabbott:shellpipes","ref":"shellpipes","sha":"6806f8e92ad138d921e4002745cd8c21ea04dbda","user":{"login":"tabbott","id":463300,"avatar_url":"https://avatars.githubusercontent.com/u/463300?v=3","gravatar_id":"","url":"https://api.github.com/users/tabbott","html_url":"https://github.com/tabbott","followers_url":"https://api.github.com/users/tabbott/followers","following_url":"https://api.github.com/users/tabbott/following{/other_user}","gists_url":"https://api.github.com/users/tabbott/gists{/gist_id}","starred_url":"https://api.github.com/users/tabbott/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tabbott/subscriptions","organizations_url":"https://api.github.com/users/tabbott/orgs","repos_url":"https://api.github.com/users/tabbott/repos","events_url":"https://api.github.com/users/tabbott/events{/privacy}","received_events_url":"https://api.github.com/users/tabbott/received_events","type":"User","site_admin":false},"repo":{"id":27847314,"name":"genome","full_name":"tabbott/genome","owner":{"login":"tabbott","id":463300,"avatar_url":"https://avatars.githubusercontent.com/u/463300?v=3","gravatar_id":"","url":"https://api.github.com/users/tabbott","html_url":"https://github.com/tabbott","followers_url":"https://api.github.com/users/tabbott/followers","following_url":"https://api.github.com/users/tabbott/following{/other_user}","gists_url":"https://api.github.com/users/tabbott/gists{/gist_id}","starred_url":"https://api.github.com/users/tabbott/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tabbott/subscriptions","organizations_url":"https://api.github.com/users/tabbott/orgs","repos_url":"https://api.github.com/users/tabbott/repos","events_url":"https://api.github.com/users/tabbott/events{/privacy}","received_events_url":"https://api.github.com/users/tabbott/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/tabbott/genome","description":"Core modules used by the GMS","fork":true,"url":"https://api.github.com/repos/tabbott/genome","forks_url":"https://api.github.com/repos/tabbott/genome/forks","keys_url":"https://api.github.com/repos/tabbott/genome/keys{/key_id}","collaborators_url":"https://api.github.com/repos/tabbott/genome/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/tabbott/genome/teams","hooks_url":"https://api.github.com/repos/tabbott/genome/hooks","issue_events_url":"https://api.github.com/repos/tabbott/genome/issues/events{/number}","events_url":"https://api.github.com/repos/tabbott/genome/events","assignees_url":"https://api.github.com/repos/tabbott/genome/assignees{/user}","branches_url":"https://api.github.com/repos/tabbott/genome/branches{/branch}","tags_url":"https://api.github.com/repos/tabbott/genome/tags","blobs_url":"https://api.github.com/repos/tabbott/genome/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/tabbott/genome/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/tabbott/genome/git/refs{/sha}","trees_url":"https://api.github.com/repos/tabbott/genome/git/trees{/sha}","statuses_url":"https://api.github.com/repos/tabbott/genome/statuses/{sha}","languages_url":"https://api.github.com/repos/tabbott/genome/languages","stargazers_url":"https://api.github.com/repos/tabbott/genome/stargazers","contributors_url":"https://api.github.com/repos/tabbott/genome/contributors","subscribers_url":"https://api.github.com/repos/tabbott/genome/subscribers","subscription_url":"https://api.github.com/repos/tabbott/genome/subscription","commits_url":"https://api.github.com/repos/tabbott/genome/commits{/sha}","git_commits_url":"https://api.github.com/repos/tabbott/genome/git/commits{/sha}","comments_url":"https://api.github.com/repos/tabbott/genome/comments{/number}","issue_comment_url":"https://api.github.com/repos/tabbott/genome/issues/comments/{number}","contents_url":"https://api.github.com/repos/tabbott/genome/contents/{+path}","compare_url":"https://api.github.com/repos/tabbott/genome/compare/{base}...{head}","merges_url":"https://api.github.com/repos/tabbott/genome/merges","archive_url":"https://api.github.com/repos/tabbott/genome/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/tabbott/genome/downloads","issues_url":"https://api.github.com/repos/tabbott/genome/issues{/number}","pulls_url":"https://api.github.com/repos/tabbott/genome/pulls{/number}","milestones_url":"https://api.github.com/repos/tabbott/genome/milestones{/number}","notifications_url":"https://api.github.com/repos/tabbott/genome/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/tabbott/genome/labels{/name}","releases_url":"https://api.github.com/repos/tabbott/genome/releases{/id}","created_at":"2014-12-11T00:53:36Z","updated_at":"2014-12-11T00:53:58Z","pushed_at":"2015-01-13T17:35:24Z","git_url":"git://github.com/tabbott/genome.git","ssh_url":"git@github.com:tabbott/genome.git","clone_url":"https://github.com/tabbott/genome.git","svn_url":"https://github.com/tabbott/genome","homepage":"","size":108348,"stargazers_count":0,"watchers_count":0,"language":"Perl","has_issues":false,"has_downloads":true,"has_wiki":false,"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":"genome:master","ref":"master","sha":"dafe6bf24fb98854866c40fd837923eece9bf841","user":{"login":"genome","id":318108,"avatar_url":"https://avatars.githubusercontent.com/u/318108?v=3","gravatar_id":"","url":"https://api.github.com/users/genome","html_url":"https://github.com/genome","followers_url":"https://api.github.com/users/genome/followers","following_url":"https://api.github.com/users/genome/following{/other_user}","gists_url":"https://api.github.com/users/genome/gists{/gist_id}","starred_url":"https://api.github.com/users/genome/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/genome/subscriptions","organizations_url":"https://api.github.com/users/genome/orgs","repos_url":"https://api.github.com/users/genome/repos","events_url":"https://api.github.com/users/genome/events{/privacy}","received_events_url":"https://api.github.com/users/genome/received_events","type":"Organization","site_admin":false},"repo":{"id":23442737,"name":"genome","full_name":"genome/genome","owner":{"login":"genome","id":318108,"avatar_url":"https://avatars.githubusercontent.com/u/318108?v=3","gravatar_id":"","url":"https://api.github.com/users/genome","html_url":"https://github.com/genome","followers_url":"https://api.github.com/users/genome/followers","following_url":"https://api.github.com/users/genome/following{/other_user}","gists_url":"https://api.github.com/users/genome/gists{/gist_id}","starred_url":"https://api.github.com/users/genome/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/genome/subscriptions","organizations_url":"https://api.github.com/users/genome/orgs","repos_url":"https://api.github.com/users/genome/repos","events_url":"https://api.github.com/users/genome/events{/privacy}","received_events_url":"https://api.github.com/users/genome/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/genome/genome","description":"Core modules used by the GMS","fork":false,"url":"https://api.github.com/repos/genome/genome","forks_url":"https://api.github.com/repos/genome/genome/forks","keys_url":"https://api.github.com/repos/genome/genome/keys{/key_id}","collaborators_url":"https://api.github.com/repos/genome/genome/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/genome/genome/teams","hooks_url":"https://api.github.com/repos/genome/genome/hooks","issue_events_url":"https://api.github.com/repos/genome/genome/issues/events{/number}","events_url":"https://api.github.com/repos/genome/genome/events","assignees_url":"https://api.github.com/repos/genome/genome/assignees{/user}","branches_url":"https://api.github.com/repos/genome/genome/branches{/branch}","tags_url":"https://api.github.com/repos/genome/genome/tags","blobs_url":"https://api.github.com/repos/genome/genome/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/genome/genome/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/genome/genome/git/refs{/sha}","trees_url":"https://api.github.com/repos/genome/genome/git/trees{/sha}","statuses_url":"https://api.github.com/repos/genome/genome/statuses/{sha}","languages_url":"https://api.github.com/repos/genome/genome/languages","stargazers_url":"https://api.github.com/repos/genome/genome/stargazers","contributors_url":"https://api.github.com/repos/genome/genome/contributors","subscribers_url":"https://api.github.com/repos/genome/genome/subscribers","subscription_url":"https://api.github.com/repos/genome/genome/subscription","commits_url":"https://api.github.com/repos/genome/genome/commits{/sha}","git_commits_url":"https://api.github.com/repos/genome/genome/git/commits{/sha}","comments_url":"https://api.github.com/repos/genome/genome/comments{/number}","issue_comment_url":"https://api.github.com/repos/genome/genome/issues/comments/{number}","contents_url":"https://api.github.com/repos/genome/genome/contents/{+path}","compare_url":"https://api.github.com/repos/genome/genome/compare/{base}...{head}","merges_url":"https://api.github.com/repos/genome/genome/merges","archive_url":"https://api.github.com/repos/genome/genome/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/genome/genome/downloads","issues_url":"https://api.github.com/repos/genome/genome/issues{/number}","pulls_url":"https://api.github.com/repos/genome/genome/pulls{/number}","milestones_url":"https://api.github.com/repos/genome/genome/milestones{/number}","notifications_url":"https://api.github.com/repos/genome/genome/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/genome/genome/labels{/name}","releases_url":"https://api.github.com/repos/genome/genome/releases{/id}","created_at":"2014-08-28T20:59:19Z","updated_at":"2015-01-13T17:01:46Z","pushed_at":"2015-01-13T17:39:19Z","git_url":"git://github.com/genome/genome.git","ssh_url":"git@github.com:genome/genome.git","clone_url":"https://github.com/genome/genome.git","svn_url":"https://github.com/genome/genome","homepage":"","size":116931,"stargazers_count":4,"watchers_count":4,"language":"Perl","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":32,"mirror_url":null,"open_issues_count":11,"forks":32,"open_issues":11,"watchers":4,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/genome/genome/pulls/405"},"html":{"href":"https://github.com/genome/genome/pull/405"},"issue":{"href":"https://api.github.com/repos/genome/genome/issues/405"},"comments":{"href":"https://api.github.com/repos/genome/genome/issues/405/comments"},"review_comments":{"href":"https://api.github.com/repos/genome/genome/pulls/405/comments"},"review_comment":{"href":"https://api.github.com/repos/genome/genome/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/genome/genome/pulls/405/commits"},"statuses":{"href":"https://api.github.com/repos/genome/genome/statuses/6806f8e92ad138d921e4002745cd8c21ea04dbda"}}}}