mortar 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +36 -0
 - data/bin/mortar +13 -0
 - data/lib/mortar.rb +23 -0
 - data/lib/mortar/auth.rb +312 -0
 - data/lib/mortar/cli.rb +54 -0
 - data/lib/mortar/command.rb +267 -0
 - data/lib/mortar/command/auth.rb +96 -0
 - data/lib/mortar/command/base.rb +319 -0
 - data/lib/mortar/command/clusters.rb +41 -0
 - data/lib/mortar/command/describe.rb +97 -0
 - data/lib/mortar/command/generate.rb +121 -0
 - data/lib/mortar/command/help.rb +166 -0
 - data/lib/mortar/command/illustrate.rb +97 -0
 - data/lib/mortar/command/jobs.rb +174 -0
 - data/lib/mortar/command/pigscripts.rb +45 -0
 - data/lib/mortar/command/projects.rb +128 -0
 - data/lib/mortar/command/validate.rb +94 -0
 - data/lib/mortar/command/version.rb +42 -0
 - data/lib/mortar/errors.rb +24 -0
 - data/lib/mortar/generators/generator_base.rb +107 -0
 - data/lib/mortar/generators/macro_generator.rb +37 -0
 - data/lib/mortar/generators/pigscript_generator.rb +40 -0
 - data/lib/mortar/generators/project_generator.rb +67 -0
 - data/lib/mortar/generators/udf_generator.rb +28 -0
 - data/lib/mortar/git.rb +233 -0
 - data/lib/mortar/helpers.rb +488 -0
 - data/lib/mortar/project.rb +156 -0
 - data/lib/mortar/snapshot.rb +39 -0
 - data/lib/mortar/templates/macro/macro.pig +14 -0
 - data/lib/mortar/templates/pigscript/pigscript.pig +38 -0
 - data/lib/mortar/templates/pigscript/python_udf.py +13 -0
 - data/lib/mortar/templates/project/Gemfile +3 -0
 - data/lib/mortar/templates/project/README.md +8 -0
 - data/lib/mortar/templates/project/gitignore +4 -0
 - data/lib/mortar/templates/project/macros/gitkeep +0 -0
 - data/lib/mortar/templates/project/pigscripts/pigscript.pig +35 -0
 - data/lib/mortar/templates/project/udfs/python/python_udf.py +13 -0
 - data/lib/mortar/templates/udf/python_udf.py +13 -0
 - data/lib/mortar/version.rb +20 -0
 - data/lib/vendor/mortar/okjson.rb +598 -0
 - data/lib/vendor/mortar/uuid.rb +312 -0
 - data/spec/mortar/auth_spec.rb +156 -0
 - data/spec/mortar/command/auth_spec.rb +46 -0
 - data/spec/mortar/command/base_spec.rb +82 -0
 - data/spec/mortar/command/clusters_spec.rb +61 -0
 - data/spec/mortar/command/describe_spec.rb +135 -0
 - data/spec/mortar/command/generate_spec.rb +139 -0
 - data/spec/mortar/command/illustrate_spec.rb +140 -0
 - data/spec/mortar/command/jobs_spec.rb +364 -0
 - data/spec/mortar/command/pigscripts_spec.rb +70 -0
 - data/spec/mortar/command/projects_spec.rb +165 -0
 - data/spec/mortar/command/validate_spec.rb +119 -0
 - data/spec/mortar/command_spec.rb +122 -0
 - data/spec/mortar/git_spec.rb +278 -0
 - data/spec/mortar/helpers_spec.rb +82 -0
 - data/spec/mortar/project_spec.rb +76 -0
 - data/spec/mortar/snapshot_spec.rb +46 -0
 - data/spec/spec.opts +1 -0
 - data/spec/spec_helper.rb +278 -0
 - data/spec/support/display_message_matcher.rb +68 -0
 - metadata +259 -0
 
| 
         @@ -0,0 +1,70 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #
         
     | 
| 
      
 2 
     | 
    
         
            +
            # Copyright 2012 Mortar Data Inc.
         
     | 
| 
      
 3 
     | 
    
         
            +
            #
         
     | 
| 
      
 4 
     | 
    
         
            +
            # Licensed under the Apache License, Version 2.0 (the "License");
         
     | 
| 
      
 5 
     | 
    
         
            +
            # you may not use this file except in compliance with the License.
         
     | 
| 
      
 6 
     | 
    
         
            +
            # You may obtain a copy of the License at
         
     | 
| 
      
 7 
     | 
    
         
            +
            #
         
     | 
| 
      
 8 
     | 
    
         
            +
            #     http://www.apache.org/licenses/LICENSE-2.0
         
     | 
| 
      
 9 
     | 
    
         
            +
            #
         
     | 
| 
      
 10 
     | 
    
         
            +
            # Unless required by applicable law or agreed to in writing, software
         
     | 
| 
      
 11 
     | 
    
         
            +
            # distributed under the License is distributed on an "AS IS" BASIS,
         
     | 
| 
      
 12 
     | 
    
         
            +
            # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
         
     | 
| 
      
 13 
     | 
    
         
            +
            # See the License for the specific language governing permissions and
         
     | 
| 
      
 14 
     | 
    
         
            +
            # limitations under the License.
         
     | 
| 
      
 15 
     | 
    
         
            +
            #
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 18 
     | 
    
         
            +
            require 'fakefs/spec_helpers'
         
     | 
| 
      
 19 
     | 
    
         
            +
            require 'mortar/project'
         
     | 
| 
      
 20 
     | 
    
         
            +
            require 'mortar/command/pigscripts'
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            module Mortar::Command
         
     | 
| 
      
 23 
     | 
    
         
            +
              describe PigScripts do
         
     | 
| 
      
 24 
     | 
    
         
            +
                
         
     | 
| 
      
 25 
     | 
    
         
            +
                # use FakeFS file system
         
     | 
| 
      
 26 
     | 
    
         
            +
                include FakeFS::SpecHelpers
         
     | 
| 
      
 27 
     | 
    
         
            +
                
         
     | 
| 
      
 28 
     | 
    
         
            +
                before(:each) do
         
     | 
| 
      
 29 
     | 
    
         
            +
                  stub_core
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
                
         
     | 
| 
      
 32 
     | 
    
         
            +
                context("index") do
         
     | 
| 
      
 33 
     | 
    
         
            +
                  
         
     | 
| 
      
 34 
     | 
    
         
            +
                  it "displays a message when no pigscripts found" do
         
     | 
| 
      
 35 
     | 
    
         
            +
                    with_blank_project do |p|
         
     | 
| 
      
 36 
     | 
    
         
            +
                      stderr, stdout = execute("pigscripts", p)
         
     | 
| 
      
 37 
     | 
    
         
            +
                      stdout.should == <<-STDOUT
         
     | 
| 
      
 38 
     | 
    
         
            +
            You have no pigscripts.
         
     | 
| 
      
 39 
     | 
    
         
            +
            STDOUT
         
     | 
| 
      
 40 
     | 
    
         
            +
                    end
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
                  
         
     | 
| 
      
 43 
     | 
    
         
            +
                  it "displays list of 1 pigscript" do
         
     | 
| 
      
 44 
     | 
    
         
            +
                    with_blank_project do |p|
         
     | 
| 
      
 45 
     | 
    
         
            +
                      write_file(File.join(p.pigscripts_path, "my_script.pig"))
         
     | 
| 
      
 46 
     | 
    
         
            +
                      stderr, stdout = execute("pigscripts", p)
         
     | 
| 
      
 47 
     | 
    
         
            +
                      stdout.should == <<-STDOUT
         
     | 
| 
      
 48 
     | 
    
         
            +
            === pigscripts
         
     | 
| 
      
 49 
     | 
    
         
            +
            my_script
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            STDOUT
         
     | 
| 
      
 52 
     | 
    
         
            +
                    end
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
                  
         
     | 
| 
      
 55 
     | 
    
         
            +
                  it "displays list of multiple pigscripts" do
         
     | 
| 
      
 56 
     | 
    
         
            +
                    with_blank_project do |p|
         
     | 
| 
      
 57 
     | 
    
         
            +
                      write_file(File.join(p.pigscripts_path, "a_script.pig"))
         
     | 
| 
      
 58 
     | 
    
         
            +
                      write_file(File.join(p.pigscripts_path, "b_script.pig"))
         
     | 
| 
      
 59 
     | 
    
         
            +
                      stderr, stdout = execute("pigscripts", p)
         
     | 
| 
      
 60 
     | 
    
         
            +
                      stdout.should == <<-STDOUT
         
     | 
| 
      
 61 
     | 
    
         
            +
            === pigscripts
         
     | 
| 
      
 62 
     | 
    
         
            +
            a_script
         
     | 
| 
      
 63 
     | 
    
         
            +
            b_script
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
            STDOUT
         
     | 
| 
      
 66 
     | 
    
         
            +
                    end
         
     | 
| 
      
 67 
     | 
    
         
            +
                  end      
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
              end
         
     | 
| 
      
 70 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,165 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #
         
     | 
| 
      
 2 
     | 
    
         
            +
            # Copyright 2012 Mortar Data Inc.
         
     | 
| 
      
 3 
     | 
    
         
            +
            #
         
     | 
| 
      
 4 
     | 
    
         
            +
            # Licensed under the Apache License, Version 2.0 (the "License");
         
     | 
| 
      
 5 
     | 
    
         
            +
            # you may not use this file except in compliance with the License.
         
     | 
| 
      
 6 
     | 
    
         
            +
            # You may obtain a copy of the License at
         
     | 
| 
      
 7 
     | 
    
         
            +
            #
         
     | 
| 
      
 8 
     | 
    
         
            +
            #     http://www.apache.org/licenses/LICENSE-2.0
         
     | 
| 
      
 9 
     | 
    
         
            +
            #
         
     | 
| 
      
 10 
     | 
    
         
            +
            # Unless required by applicable law or agreed to in writing, software
         
     | 
| 
      
 11 
     | 
    
         
            +
            # distributed under the License is distributed on an "AS IS" BASIS,
         
     | 
| 
      
 12 
     | 
    
         
            +
            # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
         
     | 
| 
      
 13 
     | 
    
         
            +
            # See the License for the specific language governing permissions and
         
     | 
| 
      
 14 
     | 
    
         
            +
            # limitations under the License.
         
     | 
| 
      
 15 
     | 
    
         
            +
            #
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 18 
     | 
    
         
            +
            require 'fakefs/spec_helpers'
         
     | 
| 
      
 19 
     | 
    
         
            +
            require 'mortar/command/projects'
         
     | 
| 
      
 20 
     | 
    
         
            +
            require 'launchy'
         
     | 
| 
      
 21 
     | 
    
         
            +
            require "mortar/api"
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            module Mortar::Command
         
     | 
| 
      
 25 
     | 
    
         
            +
              describe Projects do
         
     | 
| 
      
 26 
     | 
    
         
            +
                
         
     | 
| 
      
 27 
     | 
    
         
            +
                before(:each) do
         
     | 
| 
      
 28 
     | 
    
         
            +
                  stub_core      
         
     | 
| 
      
 29 
     | 
    
         
            +
                  @git = Mortar::Git::Git.new
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
                
         
     | 
| 
      
 32 
     | 
    
         
            +
                project1 = {'name' => "Project1",
         
     | 
| 
      
 33 
     | 
    
         
            +
                            'status' => Mortar::API::Projects::STATUS_ACTIVE,
         
     | 
| 
      
 34 
     | 
    
         
            +
                            'git_url' => "git@github.com:mortarcode/Project1"}
         
     | 
| 
      
 35 
     | 
    
         
            +
                project2 = {'name' => "Project2",
         
     | 
| 
      
 36 
     | 
    
         
            +
                            'status' => Mortar::API::Projects::STATUS_ACTIVE,
         
     | 
| 
      
 37 
     | 
    
         
            +
                            'git_url' => "git@github.com:mortarcode/Project2"}
         
     | 
| 
      
 38 
     | 
    
         
            +
                    
         
     | 
| 
      
 39 
     | 
    
         
            +
                context("index") do
         
     | 
| 
      
 40 
     | 
    
         
            +
                  
         
     | 
| 
      
 41 
     | 
    
         
            +
                  it "shows appropriate message when user has no projects" do
         
     | 
| 
      
 42 
     | 
    
         
            +
                    mock(Mortar::Auth.api).get_projects().returns(Excon::Response.new(:body => {"projects" => []}))
         
     | 
| 
      
 43 
     | 
    
         
            +
                    
         
     | 
| 
      
 44 
     | 
    
         
            +
                    stderr, stdout = execute("projects")
         
     | 
| 
      
 45 
     | 
    
         
            +
                    stdout.should == <<-STDOUT
         
     | 
| 
      
 46 
     | 
    
         
            +
            You have no projects.
         
     | 
| 
      
 47 
     | 
    
         
            +
            STDOUT
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
      
 49 
     | 
    
         
            +
                  
         
     | 
| 
      
 50 
     | 
    
         
            +
                  it "shows appropriate message when user has multiple projects" do
         
     | 
| 
      
 51 
     | 
    
         
            +
                    mock(Mortar::Auth.api).get_projects().returns(Excon::Response.new(:body => {"projects" => [project1, project2]}))
         
     | 
| 
      
 52 
     | 
    
         
            +
                    
         
     | 
| 
      
 53 
     | 
    
         
            +
                    stderr, stdout = execute("projects")
         
     | 
| 
      
 54 
     | 
    
         
            +
                    stdout.should == <<-STDOUT
         
     | 
| 
      
 55 
     | 
    
         
            +
            === projects
         
     | 
| 
      
 56 
     | 
    
         
            +
            Project1
         
     | 
| 
      
 57 
     | 
    
         
            +
            Project2
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
            STDOUT
         
     | 
| 
      
 60 
     | 
    
         
            +
                  end
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
                
         
     | 
| 
      
 63 
     | 
    
         
            +
                context("create") do
         
     | 
| 
      
 64 
     | 
    
         
            +
                  
         
     | 
| 
      
 65 
     | 
    
         
            +
                  it "show appropriate error message when user doesn't include project name" do
         
     | 
| 
      
 66 
     | 
    
         
            +
                    stderr, stdout = execute("projects:create")
         
     | 
| 
      
 67 
     | 
    
         
            +
                    stderr.should == <<-STDERR
         
     | 
| 
      
 68 
     | 
    
         
            +
             !    Usage: mortar projects:create PROJECT
         
     | 
| 
      
 69 
     | 
    
         
            +
             !    Must specify PROJECT.
         
     | 
| 
      
 70 
     | 
    
         
            +
            STDERR
         
     | 
| 
      
 71 
     | 
    
         
            +
                  end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                  it "try to create project in directory that doesn't have a git repository" do
         
     | 
| 
      
 74 
     | 
    
         
            +
                    with_no_git_directory do
         
     | 
| 
      
 75 
     | 
    
         
            +
                      stderr, stdout = execute("projects:create some_new_project")
         
     | 
| 
      
 76 
     | 
    
         
            +
                      stderr.should == <<-STDERR
         
     | 
| 
      
 77 
     | 
    
         
            +
             !    Can only create a mortar project for an existing git project.  Please run:
         
     | 
| 
      
 78 
     | 
    
         
            +
             !    
         
     | 
| 
      
 79 
     | 
    
         
            +
             !    git init
         
     | 
| 
      
 80 
     | 
    
         
            +
             !    git add .
         
     | 
| 
      
 81 
     | 
    
         
            +
             !    git commit -a -m "first commit"
         
     | 
| 
      
 82 
     | 
    
         
            +
             !    
         
     | 
| 
      
 83 
     | 
    
         
            +
             !    to initialize your project in git.
         
     | 
| 
      
 84 
     | 
    
         
            +
            STDERR
         
     | 
| 
      
 85 
     | 
    
         
            +
                    end
         
     | 
| 
      
 86 
     | 
    
         
            +
                  end
         
     | 
| 
      
 87 
     | 
    
         
            +
                  
         
     | 
| 
      
 88 
     | 
    
         
            +
                  it "show appropriate error message when user tries to create a project inside of an existing project" do
         
     | 
| 
      
 89 
     | 
    
         
            +
                     with_git_initialized_project do |p|           
         
     | 
| 
      
 90 
     | 
    
         
            +
                       stderr, stdout = execute("projects:create some_new_project", nil, @git)
         
     | 
| 
      
 91 
     | 
    
         
            +
                       stderr.should == <<-STDERR
         
     | 
| 
      
 92 
     | 
    
         
            +
             !    Currently in project: myproject.  You can not create a new project inside of an existing mortar project.
         
     | 
| 
      
 93 
     | 
    
         
            +
            STDERR
         
     | 
| 
      
 94 
     | 
    
         
            +
                     end
         
     | 
| 
      
 95 
     | 
    
         
            +
                  end
         
     | 
| 
      
 96 
     | 
    
         
            +
                  
         
     | 
| 
      
 97 
     | 
    
         
            +
                  it "create a new project successfully" do
         
     | 
| 
      
 98 
     | 
    
         
            +
                    project_id = "1234abcd1234abcd1234"
         
     | 
| 
      
 99 
     | 
    
         
            +
                    project_name = "some_new_project"
         
     | 
| 
      
 100 
     | 
    
         
            +
                    project_git_url = "git@github.com:mortarcode/#{project_name}"
         
     | 
| 
      
 101 
     | 
    
         
            +
                    mock(Mortar::Auth.api).post_project("some_new_project") {Excon::Response.new(:body => {"project_id" => project_id})}
         
     | 
| 
      
 102 
     | 
    
         
            +
                    mock(Mortar::Auth.api).get_project(project_id).returns(Excon::Response.new(:body => {"status" => Mortar::API::Projects::STATUS_PENDING})).ordered
         
     | 
| 
      
 103 
     | 
    
         
            +
                    mock(Mortar::Auth.api).get_project(project_id).returns(Excon::Response.new(:body => {"status" => Mortar::API::Projects::STATUS_CREATING})).ordered
         
     | 
| 
      
 104 
     | 
    
         
            +
                    mock(Mortar::Auth.api).get_project(project_id).returns(Excon::Response.new(:body => {"status" => Mortar::API::Projects::STATUS_ACTIVE,
         
     | 
| 
      
 105 
     | 
    
         
            +
                                                                                                         "git_url" => project_git_url})).ordered
         
     | 
| 
      
 106 
     | 
    
         
            +
                    mock(@git).remote_add("mortar", project_git_url)
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                    stderr, stdout = execute("projects:create #{project_name}  --polling_interval 0.05", nil, @git)
         
     | 
| 
      
 109 
     | 
    
         
            +
                    stdout.should == <<-STDOUT
         
     | 
| 
      
 110 
     | 
    
         
            +
            Creating project... started
         
     | 
| 
      
 111 
     | 
    
         
            +
             ... PENDING
         
     | 
| 
      
 112 
     | 
    
         
            +
             ... CREATING
         
     | 
| 
      
 113 
     | 
    
         
            +
             ... ACTIVE
         
     | 
| 
      
 114 
     | 
    
         
            +
            STDOUT
         
     | 
| 
      
 115 
     | 
    
         
            +
                  end
         
     | 
| 
      
 116 
     | 
    
         
            +
                  
         
     | 
| 
      
 117 
     | 
    
         
            +
                end
         
     | 
| 
      
 118 
     | 
    
         
            +
                
         
     | 
| 
      
 119 
     | 
    
         
            +
                
         
     | 
| 
      
 120 
     | 
    
         
            +
                context("clone") do
         
     | 
| 
      
 121 
     | 
    
         
            +
                  
         
     | 
| 
      
 122 
     | 
    
         
            +
                  it "shows appropriate error message when user doesn't include project name" do
         
     | 
| 
      
 123 
     | 
    
         
            +
                    stderr, stdout = execute("projects:clone")
         
     | 
| 
      
 124 
     | 
    
         
            +
                    stderr.should == <<-STDERR
         
     | 
| 
      
 125 
     | 
    
         
            +
             !    Usage: mortar projects:clone PROJECT
         
     | 
| 
      
 126 
     | 
    
         
            +
             !    Must specify PROJECT.
         
     | 
| 
      
 127 
     | 
    
         
            +
            STDERR
         
     | 
| 
      
 128 
     | 
    
         
            +
                  end
         
     | 
| 
      
 129 
     | 
    
         
            +
                  
         
     | 
| 
      
 130 
     | 
    
         
            +
                  it "shows appropriate error message when user tries to clone non-existent project" do
         
     | 
| 
      
 131 
     | 
    
         
            +
                    mock(Mortar::Auth.api).get_projects().returns(Excon::Response.new(:body => {"projects" => [project1, project2]}))
         
     | 
| 
      
 132 
     | 
    
         
            +
                    
         
     | 
| 
      
 133 
     | 
    
         
            +
                    stderr, stdout = execute('projects:clone sillyProjectName')
         
     | 
| 
      
 134 
     | 
    
         
            +
                    stderr.should == <<-STDERR
         
     | 
| 
      
 135 
     | 
    
         
            +
             !    No project named: sillyProjectName exists.  Your valid projects are:
         
     | 
| 
      
 136 
     | 
    
         
            +
             !    Project1
         
     | 
| 
      
 137 
     | 
    
         
            +
             !    Project2
         
     | 
| 
      
 138 
     | 
    
         
            +
            STDERR
         
     | 
| 
      
 139 
     | 
    
         
            +
                  end
         
     | 
| 
      
 140 
     | 
    
         
            +
                  
         
     | 
| 
      
 141 
     | 
    
         
            +
                  it "shows appropriate error message when user tries to clone into existing directory" do
         
     | 
| 
      
 142 
     | 
    
         
            +
                    with_no_git_directory do
         
     | 
| 
      
 143 
     | 
    
         
            +
                      mock(Mortar::Auth.api).get_projects().returns(Excon::Response.new(:body => {"projects" => [project1, project2]}))
         
     | 
| 
      
 144 
     | 
    
         
            +
                      starting_dir = Dir.pwd
         
     | 
| 
      
 145 
     | 
    
         
            +
                      project_dir = File.join(Dir.pwd, project1['name'])
         
     | 
| 
      
 146 
     | 
    
         
            +
                      FileUtils.mkdir_p(project_dir)
         
     | 
| 
      
 147 
     | 
    
         
            +
                      
         
     | 
| 
      
 148 
     | 
    
         
            +
                      stderr, stdout = execute("projects:clone #{project1['name']}")
         
     | 
| 
      
 149 
     | 
    
         
            +
                      stderr.should == <<-STDERR
         
     | 
| 
      
 150 
     | 
    
         
            +
             !    Can't clone project: #{project1['name']} since directory with that name already exists.
         
     | 
| 
      
 151 
     | 
    
         
            +
            STDERR
         
     | 
| 
      
 152 
     | 
    
         
            +
                    end
         
     | 
| 
      
 153 
     | 
    
         
            +
                    
         
     | 
| 
      
 154 
     | 
    
         
            +
                  end
         
     | 
| 
      
 155 
     | 
    
         
            +
                  
         
     | 
| 
      
 156 
     | 
    
         
            +
                  it "calls git clone when existing project is cloned" do
         
     | 
| 
      
 157 
     | 
    
         
            +
                    mock(Mortar::Auth.api).get_projects().returns(Excon::Response.new(:body => {"projects" => [project1, project2]}))
         
     | 
| 
      
 158 
     | 
    
         
            +
                    mock(@git).clone(project1['git_url'], project1['name'])
         
     | 
| 
      
 159 
     | 
    
         
            +
                    
         
     | 
| 
      
 160 
     | 
    
         
            +
                    stderr, stdout = execute('projects:clone Project1', nil, @git)
         
     | 
| 
      
 161 
     | 
    
         
            +
                  end
         
     | 
| 
      
 162 
     | 
    
         
            +
                  
         
     | 
| 
      
 163 
     | 
    
         
            +
                end
         
     | 
| 
      
 164 
     | 
    
         
            +
              end
         
     | 
| 
      
 165 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,119 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #
         
     | 
| 
      
 2 
     | 
    
         
            +
            # Copyright 2012 Mortar Data Inc.
         
     | 
| 
      
 3 
     | 
    
         
            +
            #
         
     | 
| 
      
 4 
     | 
    
         
            +
            # Licensed under the Apache License, Version 2.0 (the "License");
         
     | 
| 
      
 5 
     | 
    
         
            +
            # you may not use this file except in compliance with the License.
         
     | 
| 
      
 6 
     | 
    
         
            +
            # You may obtain a copy of the License at
         
     | 
| 
      
 7 
     | 
    
         
            +
            #
         
     | 
| 
      
 8 
     | 
    
         
            +
            #     http://www.apache.org/licenses/LICENSE-2.0
         
     | 
| 
      
 9 
     | 
    
         
            +
            #
         
     | 
| 
      
 10 
     | 
    
         
            +
            # Unless required by applicable law or agreed to in writing, software
         
     | 
| 
      
 11 
     | 
    
         
            +
            # distributed under the License is distributed on an "AS IS" BASIS,
         
     | 
| 
      
 12 
     | 
    
         
            +
            # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
         
     | 
| 
      
 13 
     | 
    
         
            +
            # See the License for the specific language governing permissions and
         
     | 
| 
      
 14 
     | 
    
         
            +
            # limitations under the License.
         
     | 
| 
      
 15 
     | 
    
         
            +
            #
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 18 
     | 
    
         
            +
            require 'fakefs/spec_helpers'
         
     | 
| 
      
 19 
     | 
    
         
            +
            require 'mortar/command/validate'
         
     | 
| 
      
 20 
     | 
    
         
            +
            require 'mortar/api/validate'
         
     | 
| 
      
 21 
     | 
    
         
            +
            require 'launchy'
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            module Mortar::Command
         
     | 
| 
      
 24 
     | 
    
         
            +
              describe Validate do
         
     | 
| 
      
 25 
     | 
    
         
            +
                
         
     | 
| 
      
 26 
     | 
    
         
            +
                before(:each) do
         
     | 
| 
      
 27 
     | 
    
         
            +
                  stub_core      
         
     | 
| 
      
 28 
     | 
    
         
            +
                  @git = Mortar::Git::Git.new
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
                    
         
     | 
| 
      
 31 
     | 
    
         
            +
                context("index") do
         
     | 
| 
      
 32 
     | 
    
         
            +
                  
         
     | 
| 
      
 33 
     | 
    
         
            +
                  it "errors when no remote exists in the project" do
         
     | 
| 
      
 34 
     | 
    
         
            +
                    with_git_initialized_project do |p|
         
     | 
| 
      
 35 
     | 
    
         
            +
                      @git.git('remote rm mortar')
         
     | 
| 
      
 36 
     | 
    
         
            +
                      p.remote = nil
         
     | 
| 
      
 37 
     | 
    
         
            +
                      write_file(File.join(p.pigscripts_path, "my_script.pig"))
         
     | 
| 
      
 38 
     | 
    
         
            +
                      stderr, stdout = execute("validate my_script", p, @git)
         
     | 
| 
      
 39 
     | 
    
         
            +
                      stderr.should == <<-STDERR
         
     | 
| 
      
 40 
     | 
    
         
            +
             !    Unable to find git remote for project myproject
         
     | 
| 
      
 41 
     | 
    
         
            +
            STDERR
         
     | 
| 
      
 42 
     | 
    
         
            +
                    end
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  it "errors when requested pigscript cannot be found" do
         
     | 
| 
      
 46 
     | 
    
         
            +
                    with_git_initialized_project do |p|
         
     | 
| 
      
 47 
     | 
    
         
            +
                      stderr, stdout = execute("validate does_not_exist", p, @git)
         
     | 
| 
      
 48 
     | 
    
         
            +
                      stderr.should == <<-STDERR
         
     | 
| 
      
 49 
     | 
    
         
            +
             !    Unable to find pigscript does_not_exist
         
     | 
| 
      
 50 
     | 
    
         
            +
             !    No pigscripts found
         
     | 
| 
      
 51 
     | 
    
         
            +
             STDERR
         
     | 
| 
      
 52 
     | 
    
         
            +
                    end
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
                  
         
     | 
| 
      
 55 
     | 
    
         
            +
                  it "requests and reports on a successful validate" do
         
     | 
| 
      
 56 
     | 
    
         
            +
                    with_git_initialized_project do |p|
         
     | 
| 
      
 57 
     | 
    
         
            +
                      # stub api requests
         
     | 
| 
      
 58 
     | 
    
         
            +
                      validate_id = "c571a8c7f76a4fd4a67c103d753e2dd5"
         
     | 
| 
      
 59 
     | 
    
         
            +
                      parameters = ["name"=>"key", "value"=>"value" ]
         
     | 
| 
      
 60 
     | 
    
         
            +
                      
         
     | 
| 
      
 61 
     | 
    
         
            +
                      mock(Mortar::Auth.api).post_validate("myproject", "my_script", is_a(String), :parameters => parameters) {Excon::Response.new(:body => {"validate_id" => validate_id})}
         
     | 
| 
      
 62 
     | 
    
         
            +
                      mock(Mortar::Auth.api).get_validate(validate_id).returns(Excon::Response.new(:body => {"status_code" => Mortar::API::Validate::STATUS_QUEUED, "status_description" => "Pending"})).ordered
         
     | 
| 
      
 63 
     | 
    
         
            +
                      mock(Mortar::Auth.api).get_validate(validate_id).returns(Excon::Response.new(:body => {"status_code" => Mortar::API::Validate::STATUS_GATEWAY_STARTING, "status_description" => "GATEWAY_STARTING"})).ordered
         
     | 
| 
      
 64 
     | 
    
         
            +
                      mock(Mortar::Auth.api).get_validate(validate_id).returns(Excon::Response.new(:body => {"status_code" => Mortar::API::Validate::STATUS_PROGRESS, "status_description" => "Starting"})).ordered
         
     | 
| 
      
 65 
     | 
    
         
            +
                      mock(Mortar::Auth.api).get_validate(validate_id).returns(Excon::Response.new(:body => {"status_code" => Mortar::API::Validate::STATUS_SUCCESS, "status_description" => "Success"})).ordered
         
     | 
| 
      
 66 
     | 
    
         
            +
                                          
         
     | 
| 
      
 67 
     | 
    
         
            +
                      write_file(File.join(p.pigscripts_path, "my_script.pig"))
         
     | 
| 
      
 68 
     | 
    
         
            +
                      stderr, stdout = execute("validate my_script --polling_interval 0.05 -p key=value", p, @git)
         
     | 
| 
      
 69 
     | 
    
         
            +
                      stdout.should == <<-STDOUT
         
     | 
| 
      
 70 
     | 
    
         
            +
            Taking code snapshot... done
         
     | 
| 
      
 71 
     | 
    
         
            +
            Sending code snapshot to Mortar... done
         
     | 
| 
      
 72 
     | 
    
         
            +
            Starting validate... done
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
            \r\e[0KStatus: Pending... /\r\e[0KStatus: GATEWAY_STARTING... -\r\e[0KStatus: Starting... \\\r\e[0KStatus: Success  
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
            Your script is valid.
         
     | 
| 
      
 77 
     | 
    
         
            +
            STDOUT
         
     | 
| 
      
 78 
     | 
    
         
            +
                    end
         
     | 
| 
      
 79 
     | 
    
         
            +
                  end
         
     | 
| 
      
 80 
     | 
    
         
            +
                  
         
     | 
| 
      
 81 
     | 
    
         
            +
                  it "requests and reports on a failed validate" do
         
     | 
| 
      
 82 
     | 
    
         
            +
                    with_git_initialized_project do |p|
         
     | 
| 
      
 83 
     | 
    
         
            +
                      # stub api requests
         
     | 
| 
      
 84 
     | 
    
         
            +
                      validate_id = "c571a8c7f76a4fd4a67c103d753e2dd5"
         
     | 
| 
      
 85 
     | 
    
         
            +
                      
         
     | 
| 
      
 86 
     | 
    
         
            +
                      error_message = "This is my error message\nWith multiple lines."
         
     | 
| 
      
 87 
     | 
    
         
            +
                      line_number = 23
         
     | 
| 
      
 88 
     | 
    
         
            +
                      column_number = 32
         
     | 
| 
      
 89 
     | 
    
         
            +
                      error_type = 'PigError'
         
     | 
| 
      
 90 
     | 
    
         
            +
                      
         
     | 
| 
      
 91 
     | 
    
         
            +
                      mock(Mortar::Auth.api).post_validate("myproject", "my_script", is_a(String), :parameters => []) {Excon::Response.new(:body => {"validate_id" => validate_id})}
         
     | 
| 
      
 92 
     | 
    
         
            +
                      mock(Mortar::Auth.api).get_validate(validate_id).returns(Excon::Response.new(:body => {"status_code" => Mortar::API::Validate::STATUS_QUEUED, "status_description" => "Pending"})).ordered
         
     | 
| 
      
 93 
     | 
    
         
            +
                      mock(Mortar::Auth.api).get_validate(validate_id).returns(Excon::Response.new(:body => {"status_code" => Mortar::API::Validate::STATUS_FAILURE, "status_description" => "Failed",
         
     | 
| 
      
 94 
     | 
    
         
            +
                        "error_message" => error_message,
         
     | 
| 
      
 95 
     | 
    
         
            +
                        "line_number" => line_number,
         
     | 
| 
      
 96 
     | 
    
         
            +
                        "column_number" => column_number,
         
     | 
| 
      
 97 
     | 
    
         
            +
                        "error_type" => error_type})).ordered
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                      write_file(File.join(p.pigscripts_path, "my_script.pig"))
         
     | 
| 
      
 100 
     | 
    
         
            +
                      stderr, stdout = execute("validate my_script --polling_interval 0.05", p, @git)
         
     | 
| 
      
 101 
     | 
    
         
            +
                      stdout.should == <<-STDOUT
         
     | 
| 
      
 102 
     | 
    
         
            +
            Taking code snapshot... done
         
     | 
| 
      
 103 
     | 
    
         
            +
            Sending code snapshot to Mortar... done
         
     | 
| 
      
 104 
     | 
    
         
            +
            Starting validate... done
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
            \r\e[0KStatus: Pending... /\r\e[0KStatus: Failed  
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
            STDOUT
         
     | 
| 
      
 109 
     | 
    
         
            +
                      stderr.should == <<-STDERR
         
     | 
| 
      
 110 
     | 
    
         
            +
             !    Validate failed with PigError at Line 23, Column 32:
         
     | 
| 
      
 111 
     | 
    
         
            +
             !    
         
     | 
| 
      
 112 
     | 
    
         
            +
             !    This is my error message
         
     | 
| 
      
 113 
     | 
    
         
            +
             !    With multiple lines.
         
     | 
| 
      
 114 
     | 
    
         
            +
            STDERR
         
     | 
| 
      
 115 
     | 
    
         
            +
                    end
         
     | 
| 
      
 116 
     | 
    
         
            +
                  end
         
     | 
| 
      
 117 
     | 
    
         
            +
                end
         
     | 
| 
      
 118 
     | 
    
         
            +
              end
         
     | 
| 
      
 119 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,122 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #
         
     | 
| 
      
 2 
     | 
    
         
            +
            # Copyright 2012 Mortar Data Inc.
         
     | 
| 
      
 3 
     | 
    
         
            +
            #
         
     | 
| 
      
 4 
     | 
    
         
            +
            # Licensed under the Apache License, Version 2.0 (the "License");
         
     | 
| 
      
 5 
     | 
    
         
            +
            # you may not use this file except in compliance with the License.
         
     | 
| 
      
 6 
     | 
    
         
            +
            # You may obtain a copy of the License at
         
     | 
| 
      
 7 
     | 
    
         
            +
            #
         
     | 
| 
      
 8 
     | 
    
         
            +
            #     http://www.apache.org/licenses/LICENSE-2.0
         
     | 
| 
      
 9 
     | 
    
         
            +
            #
         
     | 
| 
      
 10 
     | 
    
         
            +
            # Unless required by applicable law or agreed to in writing, software
         
     | 
| 
      
 11 
     | 
    
         
            +
            # distributed under the License is distributed on an "AS IS" BASIS,
         
     | 
| 
      
 12 
     | 
    
         
            +
            # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
         
     | 
| 
      
 13 
     | 
    
         
            +
            # See the License for the specific language governing permissions and
         
     | 
| 
      
 14 
     | 
    
         
            +
            # limitations under the License.
         
     | 
| 
      
 15 
     | 
    
         
            +
            #
         
     | 
| 
      
 16 
     | 
    
         
            +
            # Portions of this code from heroku (https://github.com/heroku/heroku/) Copyright Heroku 2008 - 2012,
         
     | 
| 
      
 17 
     | 
    
         
            +
            # used under an MIT license (https://github.com/heroku/heroku/blob/master/LICENSE).
         
     | 
| 
      
 18 
     | 
    
         
            +
            #
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            require "spec_helper"
         
     | 
| 
      
 21 
     | 
    
         
            +
            require "mortar/command"
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            class FakeResponse
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              attr_accessor :body, :headers
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              def initialize(attributes)
         
     | 
| 
      
 28 
     | 
    
         
            +
                self.body, self.headers = attributes[:body], attributes[:headers]
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              def to_s
         
     | 
| 
      
 32 
     | 
    
         
            +
                body
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
            describe Mortar::Command do
         
     | 
| 
      
 38 
     | 
    
         
            +
              before {
         
     | 
| 
      
 39 
     | 
    
         
            +
                Mortar::Command.load
         
     | 
| 
      
 40 
     | 
    
         
            +
                stub_core # setup fake auth
         
     | 
| 
      
 41 
     | 
    
         
            +
              }
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
              describe "parsing errors" do
         
     | 
| 
      
 44 
     | 
    
         
            +
                it "extracts error messages from response when available in XML" do
         
     | 
| 
      
 45 
     | 
    
         
            +
                  Mortar::Command.extract_error('<errors><error>Invalid app name</error></errors>').should == 'Invalid app name'
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                it "extracts error messages from response when available in JSON" do
         
     | 
| 
      
 49 
     | 
    
         
            +
                  Mortar::Command.extract_error("{\"error\":\"Invalid app name\"}").should == 'Invalid app name'
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                it "extracts error messages from response when available in plain text" do
         
     | 
| 
      
 53 
     | 
    
         
            +
                  response = FakeResponse.new(:body => "Invalid app name", :headers => { :content_type => "text/plain; charset=UTF8" })
         
     | 
| 
      
 54 
     | 
    
         
            +
                  Mortar::Command.extract_error(response).should == 'Invalid app name'
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                it "shows Internal Server Error when the response doesn't contain a XML or JSON" do
         
     | 
| 
      
 58 
     | 
    
         
            +
                  Mortar::Command.extract_error('<h1>HTTP 500</h1>').should == "Internal server error."
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                it "shows Internal Server Error when the response is not plain text" do
         
     | 
| 
      
 62 
     | 
    
         
            +
                  response = FakeResponse.new(:body => "Foobar", :headers => { :content_type => "application/xml" })
         
     | 
| 
      
 63 
     | 
    
         
            +
                  Mortar::Command.extract_error(response).should == "Internal server error."
         
     | 
| 
      
 64 
     | 
    
         
            +
                end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                it "allows a block to redefine the default error" do
         
     | 
| 
      
 67 
     | 
    
         
            +
                  Mortar::Command.extract_error("Foobar") { "Ok!" }.should == 'Ok!'
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                it "doesn't format the response if set to raw" do
         
     | 
| 
      
 71 
     | 
    
         
            +
                  Mortar::Command.extract_error("Foobar", :raw => true) { "Ok!" }.should == 'Ok!'
         
     | 
| 
      
 72 
     | 
    
         
            +
                end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                it "handles a nil body in parse_error_xml" do
         
     | 
| 
      
 75 
     | 
    
         
            +
                  lambda { Mortar::Command.parse_error_xml(nil) }.should_not raise_error
         
     | 
| 
      
 76 
     | 
    
         
            +
                end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                it "handles a nil body in parse_error_json" do
         
     | 
| 
      
 79 
     | 
    
         
            +
                  lambda { Mortar::Command.parse_error_json(nil) }.should_not raise_error
         
     | 
| 
      
 80 
     | 
    
         
            +
                end
         
     | 
| 
      
 81 
     | 
    
         
            +
              end
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
              it "correctly resolves commands" do
         
     | 
| 
      
 84 
     | 
    
         
            +
                class Mortar::Command::Test; end
         
     | 
| 
      
 85 
     | 
    
         
            +
                class Mortar::Command::Test::Multiple; end
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                require "mortar/command/help"
         
     | 
| 
      
 88 
     | 
    
         
            +
                require "mortar/command/illustrate"
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                Mortar::Command.parse("unknown").should be_nil
         
     | 
| 
      
 91 
     | 
    
         
            +
                Mortar::Command.parse("help").should include(:klass => Mortar::Command::Help, :method => :index)
         
     | 
| 
      
 92 
     | 
    
         
            +
                Mortar::Command.parse("illustrate").should include(:klass => Mortar::Command::Illustrate, :method => :index)
         
     | 
| 
      
 93 
     | 
    
         
            +
              end
         
     | 
| 
      
 94 
     | 
    
         
            +
              
         
     | 
| 
      
 95 
     | 
    
         
            +
              context "when no commands match" do
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                it "displays the version if -v or --version is used" do
         
     | 
| 
      
 98 
     | 
    
         
            +
                  mortar("-v").should == <<-STDOUT
         
     | 
| 
      
 99 
     | 
    
         
            +
            #{Mortar::USER_AGENT}
         
     | 
| 
      
 100 
     | 
    
         
            +
            STDOUT
         
     | 
| 
      
 101 
     | 
    
         
            +
                  mortar("--version").should == <<-STDOUT
         
     | 
| 
      
 102 
     | 
    
         
            +
            #{Mortar::USER_AGENT}
         
     | 
| 
      
 103 
     | 
    
         
            +
            STDOUT
         
     | 
| 
      
 104 
     | 
    
         
            +
                end
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                it "does not suggest similar commands if there are none" do
         
     | 
| 
      
 107 
     | 
    
         
            +
                  original_stderr, original_stdout = $stderr, $stdout
         
     | 
| 
      
 108 
     | 
    
         
            +
                  $stderr = captured_stderr = StringIO.new
         
     | 
| 
      
 109 
     | 
    
         
            +
                  $stdout = captured_stdout = StringIO.new
         
     | 
| 
      
 110 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 111 
     | 
    
         
            +
                    execute("sandwich")
         
     | 
| 
      
 112 
     | 
    
         
            +
                  rescue SystemExit
         
     | 
| 
      
 113 
     | 
    
         
            +
                  end
         
     | 
| 
      
 114 
     | 
    
         
            +
                  captured_stderr.string.should == <<-STDERR
         
     | 
| 
      
 115 
     | 
    
         
            +
             !    `sandwich` is not a mortar command.
         
     | 
| 
      
 116 
     | 
    
         
            +
             !    See `mortar help` for a list of available commands.
         
     | 
| 
      
 117 
     | 
    
         
            +
            STDERR
         
     | 
| 
      
 118 
     | 
    
         
            +
                  captured_stdout.string.should == ""
         
     | 
| 
      
 119 
     | 
    
         
            +
                  $stderr, $stdout = original_stderr, original_stdout
         
     | 
| 
      
 120 
     | 
    
         
            +
                end
         
     | 
| 
      
 121 
     | 
    
         
            +
              end
         
     | 
| 
      
 122 
     | 
    
         
            +
            end
         
     |