psc 0.0.1
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/.gitignore +13 -0
 - data/.rvmrc +2 -0
 - data/.yardopts +4 -0
 - data/CHANGELOG.md +4 -0
 - data/Gemfile +20 -0
 - data/LICENSE +20 -0
 - data/README.md +163 -0
 - data/Rakefile +69 -0
 - data/cucumber.yml +13 -0
 - data/features/step_definitions/eval_steps.rb +14 -0
 - data/features/step_definitions/setup_steps.rb +7 -0
 - data/features/studies.feature +21 -0
 - data/features/support/env.rb +33 -0
 - data/features/support/int_psc.rb +165 -0
 - data/int-psc/README-int-psc.md +57 -0
 - data/int-psc/hsqldb/baseline.log +197 -0
 - data/int-psc/hsqldb/baseline.properties +17 -0
 - data/int-psc/hsqldb/baseline.script +295 -0
 - data/int-psc/hsqldb/datasource.properties +18 -0
 - data/int-psc/hsqldb/datasource.script +2205 -0
 - data/int-psc/jetty/jetty-runner-7.4.0.v20110414.jar +0 -0
 - data/int-psc/state/ABC 1200.xml +115 -0
 - data/int-psc/state/int-psc-state.xml +64 -0
 - data/lib/psc.rb +47 -0
 - data/lib/psc/client.rb +35 -0
 - data/lib/psc/connection.rb +96 -0
 - data/lib/psc/faraday.rb +11 -0
 - data/lib/psc/faraday/http_basic.rb +35 -0
 - data/lib/psc/faraday/psc_token.rb +42 -0
 - data/lib/psc/faraday/string_is_xml.rb +25 -0
 - data/lib/psc/version.rb +3 -0
 - data/meta.rakefile +30 -0
 - data/psc.gemspec +33 -0
 - data/spec/fixtures/studies-json.http +37 -0
 - data/spec/middleware_helper.rb +18 -0
 - data/spec/psc/client_spec.rb +39 -0
 - data/spec/psc/connection_spec.rb +156 -0
 - data/spec/psc/faraday/http_basic_spec.rb +15 -0
 - data/spec/psc/faraday/psc_token_spec.rb +38 -0
 - data/spec/psc/faraday/string_is_xml_spec.rb +49 -0
 - data/spec/psc/version_spec.rb +11 -0
 - data/spec/psc_spec.rb +16 -0
 - data/spec/spec_helper.rb +15 -0
 - data/tasks/int-psc.rake +84 -0
 - data/tasks/psc/TODO +3 -0
 - data/tasks/psc/state.rb +393 -0
 - metadata +311 -0
 
    
        data/.gitignore
    ADDED
    
    
    
        data/.rvmrc
    ADDED
    
    
    
        data/.yardopts
    ADDED
    
    
    
        data/CHANGELOG.md
    ADDED
    
    
    
        data/Gemfile
    ADDED
    
    | 
         @@ -0,0 +1,20 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            source "http://rubygems.org/"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            gemspec
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            group :development do
         
     | 
| 
      
 6 
     | 
    
         
            +
              # For yard's markdown support
         
     | 
| 
      
 7 
     | 
    
         
            +
              platforms :jruby do
         
     | 
| 
      
 8 
     | 
    
         
            +
                gem 'maruku'
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              platforms :ruby_18, :ruby_19 do
         
     | 
| 
      
 12 
     | 
    
         
            +
                gem 'rdiscount'
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              # To prevent jruby problems in development
         
     | 
| 
      
 16 
     | 
    
         
            +
              platforms :jruby do
         
     | 
| 
      
 17 
     | 
    
         
            +
                gem 'jruby-openssl' # when using webmock
         
     | 
| 
      
 18 
     | 
    
         
            +
                gem 'ffi-ncurses'   # when loading highline
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
            end
         
     | 
    
        data/LICENSE
    ADDED
    
    | 
         @@ -0,0 +1,20 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Copyright (c) 2011 Rhett Sutphin
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person obtaining
         
     | 
| 
      
 4 
     | 
    
         
            +
            a copy of this software and associated documentation files (the
         
     | 
| 
      
 5 
     | 
    
         
            +
            "Software"), to deal in the Software without restriction, including
         
     | 
| 
      
 6 
     | 
    
         
            +
            without limitation the rights to use, copy, modify, merge, publish,
         
     | 
| 
      
 7 
     | 
    
         
            +
            distribute, sublicense, and/or sell copies of the Software, and to
         
     | 
| 
      
 8 
     | 
    
         
            +
            permit persons to whom the Software is furnished to do so, subject to
         
     | 
| 
      
 9 
     | 
    
         
            +
            the following conditions:
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be
         
     | 
| 
      
 12 
     | 
    
         
            +
            included in all copies or substantial portions of the Software.
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
         
     | 
| 
      
 15 
     | 
    
         
            +
            EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
         
     | 
| 
      
 16 
     | 
    
         
            +
            MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
         
     | 
| 
      
 17 
     | 
    
         
            +
            NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
         
     | 
| 
      
 18 
     | 
    
         
            +
            LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
         
     | 
| 
      
 19 
     | 
    
         
            +
            OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
         
     | 
| 
      
 20 
     | 
    
         
            +
            WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
         
     | 
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,163 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            (Beware: [Readme-driven development in
         
     | 
| 
      
 2 
     | 
    
         
            +
            progress](http://tom.preston-werner.com/2010/08/23/readme-driven-development.html). This
         
     | 
| 
      
 3 
     | 
    
         
            +
            is documentation for expected features, not for the current state of
         
     | 
| 
      
 4 
     | 
    
         
            +
            the library.)
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            # psc.rb
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            `psc.rb` is a ruby client for [Patient Study Calendar][psc]'s RESTful
         
     | 
| 
      
 9 
     | 
    
         
            +
            HTTP API. It provides assistance with authentication to PSC's API and
         
     | 
| 
      
 10 
     | 
    
         
            +
            with executing common tasks. It also provides a lower-level interface
         
     | 
| 
      
 11 
     | 
    
         
            +
            (`Psc::Connection`) to allow for making HTTP requests against the
         
     | 
| 
      
 12 
     | 
    
         
            +
            configured PSC's API directly.
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            By design, the client provides a very thin abstraction over the API
         
     | 
| 
      
 15 
     | 
    
         
            +
            itself. Please be familiar with the API (whose documentation is
         
     | 
| 
      
 16 
     | 
    
         
            +
            available in your PSC instance at `api/v1/docs` or [on the demo
         
     | 
| 
      
 17 
     | 
    
         
            +
            site][demo-docs]) before using this library.
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            [psc]: https://code.bioinformatics.northwestern.edu/issues/wiki/psc
         
     | 
| 
      
 20 
     | 
    
         
            +
            [demo-docs]: https://demos.nubic.northwestern.edu/psc/api/v1/docs
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            ## Overview
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                require 'psc'
         
     | 
| 
      
 25 
     | 
    
         
            +
                require 'pp'
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                psc = Psc::Client.new(
         
     | 
| 
      
 28 
     | 
    
         
            +
                  'https://demos.nubic.northwestern.edu/psc',
         
     | 
| 
      
 29 
     | 
    
         
            +
                  :authenticator => { :basic => ['superuser', 'superuser'] }
         
     | 
| 
      
 30 
     | 
    
         
            +
                )
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                pp psc.studies
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            (This code will run if you have the psc gem installed; try it and see.)
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
            ## Installing
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            `psc.rb` is available as a rubygem:
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                $ gem install psc
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
            ## Authentication
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            PSC supports two forms of authentication for API calls: HTTP Basic
         
     | 
| 
      
 45 
     | 
    
         
            +
            (i.e., username & password) and psc_token. (Which forms are supported
         
     | 
| 
      
 46 
     | 
    
         
            +
            in your PSC instance will depend on its authentication system
         
     | 
| 
      
 47 
     | 
    
         
            +
            configuration.)
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
            A particular client instance will only use one authentication
         
     | 
| 
      
 50 
     | 
    
         
            +
            mechanism. There are three options.
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
            ### HTTP Basic
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
            PSC Client allows you to specify a username and password to use for
         
     | 
| 
      
 55 
     | 
    
         
            +
            all requests. Include the `:authenticator` key like so:
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                :authenticator => { :basic => %w(alice password) }
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                => Authorization: Basic YWxpY2U6cGFzc3dvcmQ=
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
            ### Static token
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
            Alternatively, you can provide a token to use in all requests:
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                :authenticator => { :token => 'The raven flies at midnight' }
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                => Authorization: psc_token The raven flies at midnight
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
            ### Dynamic token
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
            Finally, you can provide a callable object which will be invoked for
         
     | 
| 
      
 72 
     | 
    
         
            +
            each request and whose return value will be used for the PSC token:
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                :authenticator => { :token => lambda { cas_client.get_proxy_ticket } }
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                => Authorization: psc_token PT-133-236H522
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
            The callable will be called with no arguments.
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
            ## High-level interface
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
            {Psc::Client} provides a high-level interface to some of PSC's API
         
     | 
| 
      
 83 
     | 
    
         
            +
            capabilities.
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
            ## Low-level interface
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
            `psc.rb` is based on [Faraday][], a modular ruby HTTP
         
     | 
| 
      
 88 
     | 
    
         
            +
            client. {Psc::Connection} is a Faraday connection configured
         
     | 
| 
      
 89 
     | 
    
         
            +
            for access to a particular PSC instance. You can create a
         
     | 
| 
      
 90 
     | 
    
         
            +
            `Psc::Connection` directly:
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                conn = Psc::Connection.new(
         
     | 
| 
      
 93 
     | 
    
         
            +
                  'https://demos.nubic.northwestern.edu/psc',
         
     | 
| 
      
 94 
     | 
    
         
            +
                  :authenticator => { :basic => %w(superuser superuser) })
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
            Or you can get an instance from the {Psc::Client} high-level
         
     | 
| 
      
 97 
     | 
    
         
            +
            interface:
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                client = Psc::Client.new(
         
     | 
| 
      
 100 
     | 
    
         
            +
                  'https://demos.nubic.northwestern.edu/psc',
         
     | 
| 
      
 101 
     | 
    
         
            +
                  :authenticator => { :basic => %w(superuser superuser) })
         
     | 
| 
      
 102 
     | 
    
         
            +
                conn = client.connection
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
            The connection is set up to automatically parse JSON reponses into
         
     | 
| 
      
 105 
     | 
    
         
            +
            appropriate ruby primitives and XML responses into [Nokogiri][]
         
     | 
| 
      
 106 
     | 
    
         
            +
            documents.
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                studies_json = conn.get('studies.json')
         
     | 
| 
      
 109 
     | 
    
         
            +
                first_study_name =
         
     | 
| 
      
 110 
     | 
    
         
            +
                  studies_json.body['studies'].first['assigned_identifier']
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                sites_xml = conn.get('sites.xml')
         
     | 
| 
      
 113 
     | 
    
         
            +
                first_site_name =
         
     | 
| 
      
 114 
     | 
    
         
            +
                  sites_xml.body.xpath('//psc:site', Psc.xml_namespace).first.attr('site-name')
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
            Similarly, for PUT and POST it will encode a `Hash` or
         
     | 
| 
      
 117 
     | 
    
         
            +
            `Array` entity as JSON and will assume that a `String` entity is XML.
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
            [Faraday]: https://github.com/technoweenie/faraday
         
     | 
| 
      
 120 
     | 
    
         
            +
            [Nokogiri]: http://nokogiri.org/
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
            ### URLs
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
            PSC's API resources all start with `api/v1`. To help you DRY things
         
     | 
| 
      
 125 
     | 
    
         
            +
            up, `PSC::Connection` automatically adds this to the base URL on
         
     | 
| 
      
 126 
     | 
    
         
            +
            construction. You don't need to include it when constructing
         
     | 
| 
      
 127 
     | 
    
         
            +
            relative URLs.
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
            ### Middleware
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
            Faraday connections are built up from middleware. `Psc::Connection`
         
     | 
| 
      
 132 
     | 
    
         
            +
            uses a combination of off-the-shelf and custom middleware classes. The
         
     | 
| 
      
 133 
     | 
    
         
            +
            custom classes are in the {Psc::Faraday} module.
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
            ## Project info
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
            * [Source code][github]
         
     | 
| 
      
 138 
     | 
    
         
            +
            * [API Documentation][rubydoc]
         
     | 
| 
      
 139 
     | 
    
         
            +
            * [Bug reports and feature requests][issues]
         
     | 
| 
      
 140 
     | 
    
         
            +
            * [Continuous integration][ci]
         
     | 
| 
      
 141 
     | 
    
         
            +
            * Version policy: [semantic versioning][semver]
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
      
 143 
     | 
    
         
            +
            [rubydoc]: http://rubydoc.info/gems/psc
         
     | 
| 
      
 144 
     | 
    
         
            +
            [issues]: https://github.com/NUBIC/psc.rb/issues
         
     | 
| 
      
 145 
     | 
    
         
            +
            [github]: https://github.com/NUBIC/psc.rb
         
     | 
| 
      
 146 
     | 
    
         
            +
            [ci]: https://ctms-ci.nubic.northwestern.edu/hudson/jobs/psc.rb
         
     | 
| 
      
 147 
     | 
    
         
            +
            [semver]: http://semver.org/
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
            ### Running the tests
         
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
      
 151 
     | 
    
         
            +
            `psc.rb` has an rspec suite for unit tests and a set of cucumber
         
     | 
| 
      
 152 
     | 
    
         
            +
            features for integration tests. Before you can run the cucumber
         
     | 
| 
      
 153 
     | 
    
         
            +
            features you will need to either
         
     | 
| 
      
 154 
     | 
    
         
            +
             
     | 
| 
      
 155 
     | 
    
         
            +
             * Execute `rake int-psc:war` to download a copy of PSC to use
         
     | 
| 
      
 156 
     | 
    
         
            +
             * Copy a PSC war into `int-psc/bin`
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
            ### Patches
         
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
      
 160 
     | 
    
         
            +
            Patches with tests are happily considered. Please use a [pull
         
     | 
| 
      
 161 
     | 
    
         
            +
            request][].
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
      
 163 
     | 
    
         
            +
            [pull request]: http://help.github.com/pull-requests/
         
     | 
    
        data/Rakefile
    ADDED
    
    | 
         @@ -0,0 +1,69 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'bundler'
         
     | 
| 
      
 2 
     | 
    
         
            +
            Bundler::GemHelper.install_tasks
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'rspec/core/rake_task'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'ci/reporter/rake/rspec'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'cucumber/rake/task'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'yard'
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            Dir[File.expand_path('../tasks/*.rake', __FILE__)].each { |f| load f }
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            desc "Run all specs"
         
     | 
| 
      
 12 
     | 
    
         
            +
            RSpec::Core::RakeTask.new('spec') do |t|
         
     | 
| 
      
 13 
     | 
    
         
            +
              t.pattern = 'spec/**/*_spec.rb'
         
     | 
| 
      
 14 
     | 
    
         
            +
              t.verbose = true
         
     | 
| 
      
 15 
     | 
    
         
            +
              t.rspec_opts = ['--format', 'html', '--out', 'reports/spec.html', '--format', 'p']
         
     | 
| 
      
 16 
     | 
    
         
            +
            end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            task :cucumber => 'cucumber:ok'
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            namespace :cucumber do
         
     | 
| 
      
 21 
     | 
    
         
            +
              Cucumber::Rake::Task.new(:ok, "Run features that should pass") do |t|
         
     | 
| 
      
 22 
     | 
    
         
            +
                t.fork = true
         
     | 
| 
      
 23 
     | 
    
         
            +
                t.profile = "default"
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              Cucumber::Rake::Task.new(:wip, "Run features that are being worked on") do |t|
         
     | 
| 
      
 27 
     | 
    
         
            +
                t.fork = true
         
     | 
| 
      
 28 
     | 
    
         
            +
                t.profile = "wip"
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              Cucumber::Rake::Task.new(
         
     | 
| 
      
 32 
     | 
    
         
            +
                :wip_platform, "Run features that are flagged as failing on the current platform"
         
     | 
| 
      
 33 
     | 
    
         
            +
              ) do |t|
         
     | 
| 
      
 34 
     | 
    
         
            +
                t.fork = true
         
     | 
| 
      
 35 
     | 
    
         
            +
                t.profile = "wip_platform"
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
              desc "Run all features"
         
     | 
| 
      
 39 
     | 
    
         
            +
              task :all => [:ok, :wip, :wip_platform]
         
     | 
| 
      
 40 
     | 
    
         
            +
            end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
            task :yard => ['yard:auto']
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            namespace :yard do
         
     | 
| 
      
 45 
     | 
    
         
            +
              desc "Run a server which will rebuild documentation as the source changes"
         
     | 
| 
      
 46 
     | 
    
         
            +
              task :auto do
         
     | 
| 
      
 47 
     | 
    
         
            +
                system("bundle exec yard server --reload")
         
     | 
| 
      
 48 
     | 
    
         
            +
              end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
              desc "Build API documentation with yard"
         
     | 
| 
      
 51 
     | 
    
         
            +
              YARD::Rake::YardocTask.new("once") do |t|
         
     | 
| 
      
 52 
     | 
    
         
            +
                t.options = ["--title", "psc.rb #{Psc::VERSION}"]
         
     | 
| 
      
 53 
     | 
    
         
            +
              end
         
     | 
| 
      
 54 
     | 
    
         
            +
            end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
            namespace :ci do
         
     | 
| 
      
 57 
     | 
    
         
            +
              ENV["CI_REPORTS"] = "reports/spec-xml"
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
              desc "Run specs for CI"
         
     | 
| 
      
 60 
     | 
    
         
            +
              task :spec => ['ci:setup:rspec', 'rake:spec']
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
              Cucumber::Rake::Task.new(:cucumber, 'Run features using the ci profile') do |t|
         
     | 
| 
      
 63 
     | 
    
         
            +
                t.fork = true
         
     | 
| 
      
 64 
     | 
    
         
            +
                t.profile = 'ci'
         
     | 
| 
      
 65 
     | 
    
         
            +
              end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
              # currently bypassing ci_reporter due to https://github.com/nicksieger/ci_reporter/issues/5
         
     | 
| 
      
 68 
     | 
    
         
            +
              task :build => %w(int-psc:war int-psc:clean_logs rake:spec cucumber)
         
     | 
| 
      
 69 
     | 
    
         
            +
            end
         
     | 
    
        data/cucumber.yml
    ADDED
    
    | 
         @@ -0,0 +1,13 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            <% platform =
         
     | 
| 
      
 2 
     | 
    
         
            +
                if RUBY_PLATFORM == 'java'
         
     | 
| 
      
 3 
     | 
    
         
            +
                  'jruby'
         
     | 
| 
      
 4 
     | 
    
         
            +
                elsif RUBY_VERSION =~ /^1.9/
         
     | 
| 
      
 5 
     | 
    
         
            +
                  '19'
         
     | 
| 
      
 6 
     | 
    
         
            +
                else
         
     | 
| 
      
 7 
     | 
    
         
            +
                  '18'
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
            %>
         
     | 
| 
      
 10 
     | 
    
         
            +
            default: --strict --tags ~@wip --tags ~@no_<%= platform %> features
         
     | 
| 
      
 11 
     | 
    
         
            +
            wip: --tags @wip:3 --wip --tags ~@no_<%= platform %> features
         
     | 
| 
      
 12 
     | 
    
         
            +
            ci: --tags ~@wip --tags ~@badci --tags ~@no_<%= platform %> --format html --out reports/cucumber.html --format junit --out reports/cucumber-xml --format progress --strict features
         
     | 
| 
      
 13 
     | 
    
         
            +
            wip_platform: --tags @no_<%= platform %> --wip features
         
     | 
| 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            When /^I evaluate the following code:$/ do |string|
         
     | 
| 
      
 2 
     | 
    
         
            +
              int_psc.wait_for
         
     | 
| 
      
 3 
     | 
    
         
            +
              @captured_out = StringIO.new
         
     | 
| 
      
 4 
     | 
    
         
            +
              begin
         
     | 
| 
      
 5 
     | 
    
         
            +
                $stdout = @captured_out
         
     | 
| 
      
 6 
     | 
    
         
            +
                eval(string)
         
     | 
| 
      
 7 
     | 
    
         
            +
              ensure
         
     | 
| 
      
 8 
     | 
    
         
            +
                $stdout = STDOUT
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
            end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            Then /^I should see this output:$/ do |string|
         
     | 
| 
      
 13 
     | 
    
         
            +
              @captured_out.string.strip.should == string
         
     | 
| 
      
 14 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Feature: List studies
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            In order to understand what templates are available
         
     | 
| 
      
 4 
     | 
    
         
            +
            A developer should be able to use Psc::Client to list the studies in a PSC instance
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            Background:
         
     | 
| 
      
 7 
     | 
    
         
            +
              Given that PSC is deployed
         
     | 
| 
      
 8 
     | 
    
         
            +
                And I have a PSC::Client instance
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            Scenario: List studies
         
     | 
| 
      
 11 
     | 
    
         
            +
               When I evaluate the following code:
         
     | 
| 
      
 12 
     | 
    
         
            +
                """
         
     | 
| 
      
 13 
     | 
    
         
            +
                s = client.studies
         
     | 
| 
      
 14 
     | 
    
         
            +
                puts "Study count: #{s.size}"
         
     | 
| 
      
 15 
     | 
    
         
            +
                puts "First study: #{s.first['assigned_identifier']}"
         
     | 
| 
      
 16 
     | 
    
         
            +
                """
         
     | 
| 
      
 17 
     | 
    
         
            +
               Then I should see this output:
         
     | 
| 
      
 18 
     | 
    
         
            +
                """
         
     | 
| 
      
 19 
     | 
    
         
            +
                Study count: 1
         
     | 
| 
      
 20 
     | 
    
         
            +
                First study: ABC 1200
         
     | 
| 
      
 21 
     | 
    
         
            +
                """
         
     | 
| 
         @@ -0,0 +1,33 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'bundler'
         
     | 
| 
      
 2 
     | 
    
         
            +
            Bundler.setup
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'rspec'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            $LOAD_PATH.unshift File.expand_path("../../../lib", __FILE__)
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            require 'psc'
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            module Psc::Cucumber
         
     | 
| 
      
 11 
     | 
    
         
            +
              include ::RSpec::Matchers
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              class World
         
     | 
| 
      
 14 
     | 
    
         
            +
                def int_psc
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @int_psc ||= IntPsc.new
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                def init_client
         
     | 
| 
      
 19 
     | 
    
         
            +
                  @client = Psc::Client.new(
         
     | 
| 
      
 20 
     | 
    
         
            +
                    File.join(IntPsc.url, 'api/v1'),
         
     | 
| 
      
 21 
     | 
    
         
            +
                    :authenticator => { :basic => [ 'superuser' ] * 2 }
         
     | 
| 
      
 22 
     | 
    
         
            +
                  )
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                def client
         
     | 
| 
      
 26 
     | 
    
         
            +
                  @client
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
            end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            World do
         
     | 
| 
      
 32 
     | 
    
         
            +
              Psc::Cucumber::World.new
         
     | 
| 
      
 33 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,165 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Utilities for starting and stopping a PSC instance for integration testing
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'childprocess'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'open-uri'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'timeout'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'forwardable'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'fileutils'
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            class IntPsc
         
     | 
| 
      
 10 
     | 
    
         
            +
              DEFAULT_CONFIGURATION_NAME='datasource'
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              extend Forwardable
         
     | 
| 
      
 13 
     | 
    
         
            +
              include FileUtils
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              def self.path(*bits)
         
     | 
| 
      
 16 
     | 
    
         
            +
                File.join(File.expand_path('../../..', __FILE__), 'int-psc', *bits)
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
              def_delegator self, :path
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              def self.port
         
     | 
| 
      
 21 
     | 
    
         
            +
                ENV['INT_PSC_PORT'] ||= '7209'
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
              def_delegator self, :port
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              def self.url
         
     | 
| 
      
 26 
     | 
    
         
            +
                "http://localhost:#{port}/"
         
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
              def_delegator self, :url
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              def self.warfile
         
     | 
| 
      
 31 
     | 
    
         
            +
                path('bin', 'psc.war')
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
              def_delegator self, :warfile
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              def self.expanded_war_directory
         
     | 
| 
      
 36 
     | 
    
         
            +
                path('deploy-base', 'webapps', 'ROOT')
         
     | 
| 
      
 37 
     | 
    
         
            +
              end
         
     | 
| 
      
 38 
     | 
    
         
            +
              def_delegator self, :expanded_war_directory
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
              def self.run(configuration=DEFAULT_CONFIGURATION_NAME)
         
     | 
| 
      
 41 
     | 
    
         
            +
                psc = self.new(configuration)
         
     | 
| 
      
 42 
     | 
    
         
            +
                psc.boot
         
     | 
| 
      
 43 
     | 
    
         
            +
                puts "Waiting for PSC's API to become available"
         
     | 
| 
      
 44 
     | 
    
         
            +
                psc.wait_for
         
     | 
| 
      
 45 
     | 
    
         
            +
                yield psc
         
     | 
| 
      
 46 
     | 
    
         
            +
                psc.stop
         
     | 
| 
      
 47 
     | 
    
         
            +
              end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
              attr_reader :configuration_name
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
              def initialize(configuration=DEFAULT_CONFIGURATION_NAME)
         
     | 
| 
      
 52 
     | 
    
         
            +
                @configuration_name = configuration
         
     | 
| 
      
 53 
     | 
    
         
            +
              end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
              def boot
         
     | 
| 
      
 56 
     | 
    
         
            +
                expand_if_necessary
         
     | 
| 
      
 57 
     | 
    
         
            +
                create_hsql_psc_configuration
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                cmd = [
         
     | 
| 
      
 60 
     | 
    
         
            +
                  'java',
         
     | 
| 
      
 61 
     | 
    
         
            +
                  ENV['JAVA_OPTS'],
         
     | 
| 
      
 62 
     | 
    
         
            +
                  "-Dpsc.config.datasource=#{configuration_name}",
         
     | 
| 
      
 63 
     | 
    
         
            +
                  "-Dpsc.config.path=#{path}",
         
     | 
| 
      
 64 
     | 
    
         
            +
                  '-Dpsc.logging.debug=true',
         
     | 
| 
      
 65 
     | 
    
         
            +
                  "-Dcatalina.base=#{path 'deploy-base'}",
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                  '-jar',
         
     | 
| 
      
 68 
     | 
    
         
            +
                  # jetty-runner
         
     | 
| 
      
 69 
     | 
    
         
            +
                  path('jetty', 'jetty-runner-7.4.0.v20110414.jar'),
         
     | 
| 
      
 70 
     | 
    
         
            +
                  "--port", port,
         
     | 
| 
      
 71 
     | 
    
         
            +
                  expanded_war_directory
         
     | 
| 
      
 72 
     | 
    
         
            +
                ].compact
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                @running_psc = ChildProcess.build(*cmd)
         
     | 
| 
      
 75 
     | 
    
         
            +
                @running_psc.duplex = true
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                @output_capture = rolled_log('jetty.out')
         
     | 
| 
      
 78 
     | 
    
         
            +
                @running_psc.io.stdout = @output_capture
         
     | 
| 
      
 79 
     | 
    
         
            +
                @running_psc.io.stderr = @output_capture
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                at_exit { self.stop }
         
     | 
| 
      
 82 
     | 
    
         
            +
                @running_psc.start
         
     | 
| 
      
 83 
     | 
    
         
            +
                @running_psc.io.stdin.close # to turn off ShellTUI for the OSGi layer
         
     | 
| 
      
 84 
     | 
    
         
            +
              end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
              def stop
         
     | 
| 
      
 87 
     | 
    
         
            +
                if @running_psc && @running_psc.alive?
         
     | 
| 
      
 88 
     | 
    
         
            +
                  @running_psc.stop
         
     | 
| 
      
 89 
     | 
    
         
            +
                  @output_capture.close
         
     | 
| 
      
 90 
     | 
    
         
            +
                end
         
     | 
| 
      
 91 
     | 
    
         
            +
              end
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
              def wait_for
         
     | 
| 
      
 94 
     | 
    
         
            +
                Timeout.timeout(90) do
         
     | 
| 
      
 95 
     | 
    
         
            +
                  while true
         
     | 
| 
      
 96 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 97 
     | 
    
         
            +
                      open(File.join(self.url, '/api/v1/docs')) { |f| f.read }
         
     | 
| 
      
 98 
     | 
    
         
            +
                      break
         
     | 
| 
      
 99 
     | 
    
         
            +
                    rescue RuntimeError
         
     | 
| 
      
 100 
     | 
    
         
            +
                      sleep(1)
         
     | 
| 
      
 101 
     | 
    
         
            +
                    rescue
         
     | 
| 
      
 102 
     | 
    
         
            +
                      sleep(1)
         
     | 
| 
      
 103 
     | 
    
         
            +
                    end
         
     | 
| 
      
 104 
     | 
    
         
            +
                  end
         
     | 
| 
      
 105 
     | 
    
         
            +
                end
         
     | 
| 
      
 106 
     | 
    
         
            +
              end
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
              def create_hsql_psc_configuration
         
     | 
| 
      
 109 
     | 
    
         
            +
                File.open(path("#{configuration_name}.properties"), 'w') do |f|
         
     | 
| 
      
 110 
     | 
    
         
            +
                  f.puts [
         
     | 
| 
      
 111 
     | 
    
         
            +
                    "datasource.url=jdbc:hsqldb:file:#{path('hsqldb', configuration_name)};shutdown=true",
         
     | 
| 
      
 112 
     | 
    
         
            +
                    'datasource.username=sa',
         
     | 
| 
      
 113 
     | 
    
         
            +
                    'datasource.password=',
         
     | 
| 
      
 114 
     | 
    
         
            +
                    'datasource.driver=org.hsqldb.jdbcDriver'
         
     | 
| 
      
 115 
     | 
    
         
            +
                  ].join("\n")
         
     | 
| 
      
 116 
     | 
    
         
            +
                end
         
     | 
| 
      
 117 
     | 
    
         
            +
              end
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
              def apply_state_and_mark_readonly
         
     | 
| 
      
 120 
     | 
    
         
            +
                client = Faraday.new(File.join(url, '/api/v1')) do |builder|
         
     | 
| 
      
 121 
     | 
    
         
            +
                  builder.adapter :net_http
         
     | 
| 
      
 122 
     | 
    
         
            +
                end
         
     | 
| 
      
 123 
     | 
    
         
            +
                client.basic_auth('superuser', 'superuser')
         
     | 
| 
      
 124 
     | 
    
         
            +
                Psc::State.from_file(path('state/int-psc-state.xml')).apply(client)
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                File.open(path('hsqldb', "#{configuration_name}.properties"), 'a') do |f|
         
     | 
| 
      
 127 
     | 
    
         
            +
                  f.puts 'hsqldb.files_readonly=true'
         
     | 
| 
      
 128 
     | 
    
         
            +
                end
         
     | 
| 
      
 129 
     | 
    
         
            +
              end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
              private
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
              def expand_if_necessary
         
     | 
| 
      
 134 
     | 
    
         
            +
                dirtime = File.directory?(expanded_war_directory) ?
         
     | 
| 
      
 135 
     | 
    
         
            +
                  File.mtime(expanded_war_directory) :
         
     | 
| 
      
 136 
     | 
    
         
            +
                  Time.at(0)
         
     | 
| 
      
 137 
     | 
    
         
            +
                wartime = File.mtime(warfile)
         
     | 
| 
      
 138 
     | 
    
         
            +
                if wartime > dirtime
         
     | 
| 
      
 139 
     | 
    
         
            +
                  rm_rf expanded_war_directory
         
     | 
| 
      
 140 
     | 
    
         
            +
                  mkdir_p expanded_war_directory
         
     | 
| 
      
 141 
     | 
    
         
            +
                  cd expanded_war_directory do
         
     | 
| 
      
 142 
     | 
    
         
            +
                    system("jar xf '#{warfile}'")
         
     | 
| 
      
 143 
     | 
    
         
            +
                  end
         
     | 
| 
      
 144 
     | 
    
         
            +
                end
         
     | 
| 
      
 145 
     | 
    
         
            +
              end
         
     | 
| 
      
 146 
     | 
    
         
            +
             
     | 
| 
      
 147 
     | 
    
         
            +
              def rolled_log(name)
         
     | 
| 
      
 148 
     | 
    
         
            +
                log = path('deploy-base', 'logs', name)
         
     | 
| 
      
 149 
     | 
    
         
            +
                mkdir_p File.dirname(log)
         
     | 
| 
      
 150 
     | 
    
         
            +
                if File.exist?(log)
         
     | 
| 
      
 151 
     | 
    
         
            +
                  now_s = date_str_from_time(Time.new)
         
     | 
| 
      
 152 
     | 
    
         
            +
                  existing_s = date_str_from_time(File.mtime(log))
         
     | 
| 
      
 153 
     | 
    
         
            +
                  if now_s != existing_s
         
     | 
| 
      
 154 
     | 
    
         
            +
                    rolled_log_name = log.sub(/\.([^\.]+)$/, ".#{existing_s}.\\1")
         
     | 
| 
      
 155 
     | 
    
         
            +
                    mv log, rolled_log_name
         
     | 
| 
      
 156 
     | 
    
         
            +
                    system("gzip -N '#{rolled_log_name}'")
         
     | 
| 
      
 157 
     | 
    
         
            +
                  end
         
     | 
| 
      
 158 
     | 
    
         
            +
                end
         
     | 
| 
      
 159 
     | 
    
         
            +
                File.open(log, 'a')
         
     | 
| 
      
 160 
     | 
    
         
            +
              end
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
      
 162 
     | 
    
         
            +
              def date_str_from_time(t)
         
     | 
| 
      
 163 
     | 
    
         
            +
                t.iso8601.split('T').first
         
     | 
| 
      
 164 
     | 
    
         
            +
              end
         
     | 
| 
      
 165 
     | 
    
         
            +
            end
         
     |