[
  {
    "path": ".gitignore",
    "content": "pkg/\n"
  },
  {
    "path": "CHANGELOG",
    "content": "\n0.6.24 / 2011-10-05\n==================\n\n  * fix hashify_domain_filter for ruby 1.9.2 (closes issue #29)\n\n0.6.23 / 2011-09-29\n==================\n\n  * Fix incompatibility with latest jeweler (Rakefile error messages) [James Cox (imajes)]\n  * We now use vagrant for integration specs.\n  * Make rsync_changes more robust\n  * Add ERB support to YAML files used in integration specs\n  * add per-domain ssh_options support to config files\n  * Big refactoring of config handling into a filter stream architecture\n\n0.6.22 / 2011-04-10\n==================\n\n  * support branch-switching on deployments\n  * added integration spec for \"branch switching\" behavior\n\n0.6.21 / 2011-04-06\n==================\n\n  * change rsync changes capturing mechanism to be more portable\n  * upgrade integration spec to test rsync/#changed?/config repo\n  * helpers spec now tests root path rsync changes\n  * deploy.yml to test rsync changes w/ config repo\n  * integration spec project and config changes to stored git repos\n\n0.6.20 / 2011-04-06\n==================\n\n  * Output the entire command before running it when debugging.\n  * more anal git checkouts on clones to support older gits\n  * abort instead of raising in wd\n  * Neuter commandline output in wd command spec\n  * Make #changes work on setup\n  * Allow enabling debugger in specs w/ non-empty ENV['debug']\n  * Fix setup #changed? integration specs\n  * Improve example text for deployment #changed? integration specs\n  * Factor out snapshotting of git revision from WD.initialize_git_changes\n  * Fix the direction of the setup #changed? integration spec test\n  * Fixing jump_to_initial_commit spec helper\n  * Helper integration spec should use the correct branch when setting up.\n  * adjust env testing in integration specs\n  * update some specs to work with updated checkout/setup helpers\n  * use branches in integration checks so full checkouts will work\n  * when initializing git changes data, work from deployment path\n  * allow integration spec checkouts to switch to a specific branch\n  * record git changes for later use by #changed?\n  * capture rsync changes for later #changed? analysis\n  * capture initial git HEAD ref for later #changes comparisons\n  * clean out any prior git/rsync changes data before refreshing repos\n  * Add specs for version command-line argument\n  * Change spec helper run_command method set pwd to bin/\n  * integration spec for #changed? in post_setup tasks\n  * adding #changed? helper (and friends) to whiskey_disk/helpers\n  * spec_helper method to rewind a git repo to the beginning\n  * git project scenario changes to support integration testing of #changes helper\n  * refactor:  splitting up WD.summarize method\n  * README updates for #changed? helper functionality\n\n\n0.6.17 / 2011-03-25\n==================\n\n  * updating contributor info in README\n  * updating specs to pass under new --debug regime\n  * deployment status message shouldn't appear in spec run output\n  * Refactoring WhiskeyDisk.reset in whiskey_disk_spec.rb\n  * spec helper should keep debugging on for test runs\n  * Make deployment status message more readable\n  * Only run post deploy|setup script with -x in debug mode\n  * Only rake --trace in debug mode\n  * Suppressing git output unless debug mode\n  * Adding log mesage for rsync configuration\n  * Only show rsync verbose and progress if debug enabled\n  * Print out a log message to indicate which host is currently being deployed\n  * Only run set -x in debug mode, also don't use bash -c\n  * Refactor a spec to use build_command directly\n  * Fix spec description for ENV['debug']\n  * Only run ssh with -v if in debug mode\n  * Refactor run to use a #ssh command\n  * Add WhiskeyDisk::Config.debug?\n  * Add -d, --debug to bin/wd\n  * change raise to abort for cleaner help output when doing `wd -h`\n  * change raise to abort for cleaner help output\n  * add --version option to wd\n  * Add support section to README\n\n\n0.6.16 / 2011-03-08\n==================\n\n  * Turning off shallow clones for 'wd setup'\n  * minor refactoring of new checkout functionality\n  * check out the specified branch on setup\n  * adding integration specs to test setup + deploy at once\n  * tweaking a couple of old path specs\n\n0.6.15 / 2011-03-07\n==================\n\n  * integration specs for \"git checkout #{branch}\" functionality\n  * adding scenario to test git checkout on non-master branches\n  * Adding current_branch integration spec helper method\n  * Ensure specified branch is checked out before applying the refresh\n\n0.6.14 / 2011-02-23\n==================\n\n  * forcing bash as the execution shell\n\n0.6.13 / 2011-02-20\n==================\n\n  * pass rake_env settings to post_* scripts\n  * Finish basic integration specs for post_* scripts\n  * should fail when post_* scripts are specified but missing\n  * basic integration specs for post_* scripts\n  * updating integration spec git repo data\n\n0.6.12 / 2011-02-20\n==================\n\n  * bad Rakefile should cause deployment to fail\n  * post_* rake task specs\n  * new scenarios to use when testing post_* rake hooks\n  * adding a dump_log helper to use when developing integration specs\n\n0.6.11 / 2011-02-18\n==================\n\n  * Generate an error message when we can't find --to proj/env in a config\n  * Fixing typo in an integration spec's example text\n\n0.6.10 / 2011-02-08\n==================\n\n  * reorganizing integration specs\n  * adding a quick README on how to run integration specs\n  * adding a remote deployment integration spec\n  * working around permissioning issues to support \"remote\" integration specs\n  * integration specs for non-matching --only deployment\n  * make sure the integration test is actually testing the local library\n  * fixing 'unit@' --only local deployment WD.remote? bug\n  * Adding initial integration spec suite\n  * save +x chmod state to bin/wd\n  * adding --only support to wd binary\n  * an ENV['only'] domain should deploy locally\n  * adding support for ENV['none'] to WhiskeyDisk, ::Config\n  * WD.fetch now iterates over all domains, local or remote\n  * reorganizing specs\n  * make it an error for a domain to appear more than once in a given project/target\n  * changing internal :domain representation\n  * WhiskeyDisk.remote? now takes a domain argument\n  * can now specify path to deploy.yml info using an URL\n\n0.6.4 / 2011-01-26\n==================\n\n  * bugfix: cd to deploy_to path before running post_{setup,deploy}_script\n\n0.6.3 / 2011-01-13\n==================\n\n  * adding support for config_target in deploy.yml\n\n0.6.2 / 2010-12-23\n==================\n\n  * update multiple deployment example to use roles\n  * new wd_role command for checking membership in a role from shell scripts\n  * adding #role? method in whiskey_disk/helpers for role-based rake tasks\n  * pass domain roles along as env variables when running ssh commands\n  * domain data now includes role information when available\n  * internal representation of 'domain' is now a list of hashes\n  * refactoring of config domain normalization code\n  * adding domain examples for config specs\n  * removing unnecessary describe blocks from config spec\n  * reordering domain config spec setup data structure for readability\n\n\n0.6.0 / 2010-12-22\n==================\n\n  * adding a set of multi-domain examples\n  * adding a local deployment example\n  * updating output summary to be more readable\n  * rake exit statuses reflect overall deployment/setup success\n  * adding WhiskeyDisk.success? method\n  * We now summarize runs, both local and remote.\n  * record results for local runs as well as remote ones\n  * now run SSH commands on multiple domains, serially, synchronously\n  * propagating changes allowed by normalizing 'domain' in config data\n  * normalize 'domain' values pulled from config files\n  * refactor config file writing in config spec\n  * WD.remote? now understands arrays of 'domain' entries in the config\n\n0.5.4\n==================\n\n  * Removing Jeweler warning from Rakefile\n  * eliminating more stubbing specs from config_spec\n  * Removing more stub! calls from config specs\n  * removing YAML.load exception stub\n  * replacing some configuration_data stubs in config spec\n  * Remove CURRENT_FILE from config specs\n  * Removing CURRENT from config specs\n  * Removing more File.exists? stubs from config spec.\n  * Removing File.exists? stubs in config specs\n  * spec refactorings\n  * Removing has_config_repo? stubs from rake specs\n  * Using non-stubbed configuration in rake specs\n  * removing useless stub of :register_configuration\n  * And removing unneeded spec helper\n  * removing whiskey_disk config stubbing\n  * introducing use_config() spec helper\n\n0.5.3\n==================\n\n  * Cosmetic and naming change in new config method\n  * fixing spec example description\n  * Reworking the config to append project name overrides to the env, since everything else is dependent thereupon\n  * tidying up the spec\n  * Allowing a manually specified project name in the bare config hash to be used as the parent project in the absence of one specified from the 'to' env setting\n\n0.5.2\n==================\n\n  * Adding --check flag to wd command-line script\n  * Making shallow clones on initial setup\n\n0.5.0\n==================\n\n  * Make the rake test task do right by bacon\n  * Adding post_setup_script support\n  * Adding post_deploy_script support\n  * Reordering specs for post-setup/deployment tasks\n\n0.4.5\n==================\n\n  * ENV settings now available to rake when searching for tasks\n  * refactoring common code for rake tasks\n  * further refactoring of clone_repository\n  * refactoring update checkout methods\n  * renaming conditional_clone\n  * Refactoring rake task code\n\n0.4.4\n==================\n\n  * README updates\n\n0.4.3\n==================\n\n  * Smarter setups\n\n0.4.2\n==================\n\n  * Taking a different approach to rake task detection\n\n0.4.1\n==================\n\n  * Fixing post_* hook edge case\n\n0.4.0\n==================\n\n  * Make the staleness check actually work with bash.\n  * Adding \"else\" block to provide feedback when not stale\n  * More complete implementation of staleness checks\n  * Removing earlier abortive implementation of staleness checking\n  * Support for staleness checks\n  * Adding first pass at conditional staleness checks\n\n0.3.1\n==================\n\n  * No longer require a Rakefile when --path isn't used\n  * We no longer do per-target config file overrides\n  * Don't run post_{setup,deploy} rake tasks without a deployed Rakefile\n  * encoding < and >\n  * adding a check flag for use with staleness checks\n"
  },
  {
    "path": "Gemfile",
    "content": "source \"https://rubygems.org\"\n\ngroup :test do\n  gem \"rake\", \"~> 12.3\"\n  gem \"extensions\"\n  gem \"facon\", \"~> 0.5.0\"\n  gem \"bacon\", \"~> 1.1.0\"\nend\n"
  },
  {
    "path": "MIT-LICENSE",
    "content": "Copyright (c) 2009, Flawed Logic, OG Consulting, Rick Bradley.\n\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.integration_specs",
    "content": "Running Integration Specs\n-------------------------\n\nTo run the integration spec suite you need to be able to run a Vagrant virtual machine (see: http://vagrantup.com/), which means you will have to have VirtualBox installed.  The Vagrant/VirtualBox setup is currently out of the scope of this document.  By default, I have been using the lucid32 box as my \"base\" box.\n\nOnce you are set up to be able to run Vagrant, you can create and start up an integration environment by running the following rake task:\n\n% rake integration:up\n\nThis will create a vagrant VM, and so may take a few minutes to complete.\n\n\nTo run the integration specs once the integration environment is up:\n\n    % export INTEGRATION=true\n    % rake\n\nTo shut down the integration VM and the integration git-daemon server:\n\n    % rake integration:down\n\nTo completely remove the integration spec VM (which can take up a good bit of space on disk), do:\n\n    % rake integration:destroy\n"
  },
  {
    "path": "README.markdown",
    "content": "## Whiskey Disk -- embarrassingly fast deployments. ##\n\n\nA very opinionated deployment tool, designed to be as fast as technologically possible.  (For more background, read the [WHY.txt](http://github.com/flogic/whiskey_disk/raw/master/WHY.txt) file)  Should work with any project which is git hosted, not just Ruby / Ruby on Rails projects.  Allows for local deploys as well as remote.\n\nYou can right-arrow through a talk on the design process of whiskey_disk, given at the 2011 Madison Ruby Conference (as well as the Ruby Hoedown), entitled \"Free Whiskey\" by going to [http://madisonruby.rickbradley.com](http://madisonruby.rickbradley.com) (slide source available [here](http://github.com/rick/madison_free_whiskey)).\n\nOr... right-arrow through a short whiskey_disk presentation at [http://wd2010.rickbradley.com/](http://wd2010.rickbradley.com) (slide source available [here](http://github.com/rick/whiskey_disk_presentation).), covering the 0.2.*-era functionality.\n\nYou can also right-arrow through a shorter but more up-to-date whiskey_disk \"lightning talk\" presentation (from the 2010 Ruby Hoedown) at [http://wdlightning.rickbradley.com/](http://wdlightning.rickbradley.com) (slide source available [here](http://github.com/rick/whiskey_disk_presentation/tree/lightning).), covering the 0.4.*-era functionality.\n\n### tl;dr ###\n\nFirst:\n\n    % gem install whiskey_disk\n\n\nThen make a deploy.yml file (in config/ if you're doing a Rails project):\n\n    staging:\n      domain: \"deployment_user@staging.mydomain.com\"\n      deploy_to: \"/path/to/where/i/deploy/staging.mydomain.com\"\n      repository: \"https://github.com/username/project.git\"\n      branch: \"staging\"\n      rake_env:\n        RAILS_ENV: 'production'\n\nthen:\n\n    % wd setup --to=staging\n\nthen:\n\n    % wd deploy --to=staging\n\n\n### Selling points ###\n\n  - If you share the same opinions as we do there's almost no code involved, almost no\n    dependencies, and it uses stock *nix tools (ssh, bash, rsync) to get\neverything done.\n\n  - Written completely spec-first for 100% coverage.  We even did that for the\n    rake tasks, the init.rb and the plugin install.rb (if you swing that way).\n\n  - 1 ssh connection per run -- so everything needed to do a full setup\n    is done in one shot.  Everything needed to do a full deployment is done in\none shot.  (Having 8 minute deploys failing because I was on CDMA wireless on a\ntrain in India where the connection won't stay up for more than 2-3 minutes is\nnot where I want to be any more.)\n\n  - Deployment configuration is specified as YAML data, not as code.\n    Operations to perform after setup or deployment are specified as rake\ntasks.\n\n  - You can do *local* deployments, by this I mean you can use whiskey\\_disk to\n    deploy fully running instances of your application to the same machine\nyou're developing on.  This turns out to be surprisingly handy (well, I was\nsurprised).  *NOTE*:  be sure to set your deploy_to to a place other than the\ncurrent local checkout.\n\n  - You can do multi-project deployments, specifying deployment data in a single\n    deploy.yml config file, or keep an entire directory of project deployment config files.\n\n  - You can separate per-deployment application configuration information (e.g., passwords,\n    database configs, hoptoad/AWS/email config data, etc.) in separate repositories from\n    the application, and whiskey\\_disk will merge the correct data onto the deployed\n    application at deployment time.  You can even share sets of configuration files among\n    deployment targets that behave alike.\n\n  - You can have per-developer configurations for targets (especially\n    useful for \"local\" or \"development\" targets).  Use .gitignore, or\n    specify a config_branch and everyone can have their own local setup that just\n    works.\n\n  - There's no before\\_after\\_before_after hooks.  You can use a well-defined rake hook and/or a\n    bash script to run additional tasks.\n\n  - You can enable \"staleness checks\" so that deployments only happen if\n    either the main repo, or the config repo (if you're using one) has\n    changes that are newer than what is currently deployed.\n\n  - Put whiskey\\_disk in a cron, with staleness checks enabled, and you can\n    do hands-free automated deployments whenever code is pushed to your\n    deployment branch of choice!\n\n  - You can deploy to multiple remote targets at once.  Currently this is limited\n    to one-after-the-other synchronous deployments, but we're thinking about\n    doing them in parallel once we're happy with the stability of this feature.\n\n  - Assign hosts to roles (e.g., \"web\", \"db\", \"app\") and vary the shell or rake\n    post-setup/post-deploy actions you run based on those roles.\n\n  - Limit the actions you run after deployment based on whether files of interest\n    *actually changed*.\n\n### Assumptions ###\n\n - your project is managed via git\n - you are deploying over ssh, or deploying locally and have a bash-compatible shell\n - you are comfortable defining (optional) post-setup and post-deployment actions with rake\n - you have an optional second git repository for per-application/per-target configuration files\n - you have an optional Rakefile in the top directory of your project's checkout\n\n### Dependencies ###\n\nOn the server from which the whiskey_disk process will be kicked off:\n\n - ruby\n - rake\n - whiskey\\_disk\n - ssh (if doing a remote deployment).\n\nOn the deployment target server (which may be the same as the first server):\n\n - a bash-compatible shell\n - rsync (only if using a configuration repository)\n - ruby, rake, whiskey\\_disk (only if running post\\_setup or post\\_deploy hooks)\n\nIf you're running on OS X or Linux you probably have all of these installed already.  Note that the deployment target system doesn't even have to have ruby installed unless post\\_* rake hooks are being run.\n\n### Installation ###\n\nAs a gem:\n\n    % gem install whiskey_disk\n\nAs a rails plugin:\n\n    % script/plugin install git://github.com/flogic/whiskey_disk.git\n\n### Configuration ###\n\n - look in the examples/ directory for sample configuration files\n - main configuration is in &lt;app_root&gt;/config/deploy.yml\n - config files are YAML, with a section for each target.\n\nKnown config file settings (if you're familiar with capistrano and vlad these should seem eerily familiar):\n\n    domain:              host or list of hosts on which to deploy (these are ssh connect strings)\n                         can also optionally include role information for each host\n    deploy_to:           path to which to deploy main application\n    repository:          git repo path for main application\n    branch:              git branch to deploy from main application git repo (default: master)\n    deploy_config_to:    where to deploy the configuration repository\n    config_repository:   git repository for configuration files\n    config_branch:       git branch to deploy from configuration git repo (default: master)\n    config_target:       configuration repository target path to use\n    project:             project name (used to compute path in configuration checkout)\n    post_deploy_script:  path to a shell script to run after deployment\n    post_setup_script:   path to a shell script to run after setup\n    rake_env:            hash of environment variables to set when running post_setup and post_deploy rake tasks\n\n\nA simple config/deploy.yml might look like:\n\n    qa:\n      domain: \"ogc@qa.ogtastic.com\"\n      deploy_to: \"/var/www/www.ogtastic.com\"\n      repository: \"git@ogtastic.com:www.ogtastic.com.git\"\n      branch: \"stable\"\n      rake_env:\n        RAILS_ENV: 'production'\n\n - defining a deploy:&lt;target&gt;:post_setup rake task (e.g., in lib/tasks/\n   or in your project's Rakefile) will cause that task to be run at the end\nof deploy:setup\n\n - defining a deploy:&lt;target&gt;:post_deploy rake task (e.g., in\n   lib/tasks/ or in your project's Rakefile) will cause that task to be run\nat the end of deploy:now\n\nIt's easy to specify a local deployment.  The simplest way is to just not specify a \"domain\":\n\n    local:\n      deploy_to: \"/var/www/www.ogtastic.com\"\n      repository: \"git@ogtastic.com:www.ogtastic.com.git\"\n      branch: \"stable\"\n      rake_env:\n        RAILS_ENV: 'production'\n\n\nOr, just specify the string 'local' as the domain:\n\n    local:\n      domain: \"local\"\n      deploy_to: \"/var/www/www.ogtastic.com\"\n      repository: \"git@ogtastic.com:www.ogtastic.com.git\"\n      branch: \"stable\"\n      rake_env:\n        RAILS_ENV: 'production'\n\n\nFor deploying to multiple hosts, the config/deploy.yml might look like:\n\n    qa:\n      domain:\n      - \"ogc@qa1.ogtastic.com\"\n      - \"ogc@qa2.ogtastic.com\"\"\n      deploy_to: \"/var/www/www.ogtastic.com\"\n      repository: \"git@ogtastic.com:www.ogtastic.com.git\"\n      branch: \"stable\"\n      rake_env:\n        RAILS_ENV: 'production'\n\n\nYou can even include a local deployment along with remote deployments, simply use the 'local' name:\n\n    qa:\n      domain:\n      - \"local\"\n      - \"ogc@qa2.ogtastic.com\"\"\n      deploy_to: \"/var/www/www.ogtastic.com\"\n      repository: \"git@ogtastic.com:www.ogtastic.com.git\"\n      branch: \"stable\"\n      rake_env:\n        RAILS_ENV: 'production'\n\n\nIf you need special flags passed to ssh for a given domain, specify an array of `ssh_options` flags:\n\n    qa:\n      domain:\n      - name: \"ogc@qa.ogtastic.com\"\n        ssh_options:\n        - \"-t\"\n        - \"-vv\"\n        - \"-p 443\"\n      deploy_to: \"/var/www/www.ogtastic.com\"\n      repository: \"git@ogtastic.com:www.ogtastic.com.git\"\n\n### Specifying domains, with or without roles ###\n\nThere are a number of ways to specify domains (the ssh connection strings denoting the hosts\nwhere your code will be deployed).  Here are just a few examples:\n\nJust a single domain:\n\n    staging:\n      domain: \"foo@staging.example.com\"\n\nJust a single domain, but specified as a one-item list:\n\n    qa:\n      domain:\n      - \"foo@qa.example.com\"\n\nA list of multiple domains:\n\n    production:\n      domain:\n      - \"foo@appserver1.example.com\"\n      - \"foo@appserver2.example.com\"\n      - \"foo@www.example.com\"\n\nUsing the \"name\" label for the domain names (if using roles, as described below, the \"name\" label is required,\notherwise it's optional and superfluous):\n\n    ci:\n      domain:\n      - name: \"build@ci.example.com\"\n\nIt's also possible to assign various \"roles\" to the domains to which you deploy.  Some common usages would be\n\"www\", which might need a post\\_deploy task which notifies some web server software (apache, nginx, passenger,\nunicorn, etc.) that it should refresh the contents being served; or perhaps \"db\", which might need some set of\npost-deployment database migrations run (and which shouldn't be run from multiple servers).\n\nThe role names are simply strings and you can create whichever roles you wish.  See the section below entitled\n\"Taking actions based on roles\" to see how to use roles to control actions when setting up or deploying to a\ntarget.\n\nRoles are described in the domain: section of the configuration file.  There are, of course, a few different\nvalid ways to specify roles.  Note that the domain name must now be labeled when roles are being specified\nfor the domain.\n\nA single role for a domain can be specified inline:\n\n    production:\n      domain:\n      - name: \"foo@appserver1.example.com\"\n        roles: \"web\"\n\nWhile multiple roles for a domain must be specified as a list:\n\n    production:\n      domain:\n      - name: \"foo@appserver1.example.com\"\n        roles:\n        - \"web\"\n        - \"app\"\n        - \"db\"\n\nBut domains with roles can be specified alongside simple domains as well:\n\n    production:\n      domain:\n      - name: \"bar@demo.example.com\"\n      - \"user@otherhost.domain.com\"\n      - name: \"foo@appserver1.example.com\"\n        roles:\n        - \"web\"\n        - \"app\"\n        - \"db\"\n\n\nAnd, if you need to assign roles for a local deployment, you can do that as well:\n\n    local:\n      domain:\n      - name: \"local\"\n        roles:\n        - \"web\"\n        - \"app\"\n        - \"db\"\n\n\nAll that said, it's often simpler to refrain from carving up hosts into roles.  But who's going to listen to reason?\n\n\n\n### post\\_deploy\\_script and post\\_setup\\_script ###\n\nWhiskey\\_disk provides rake task hooks (deploy:post\\_setup and deploy:post\\_deploy) to allow running custom\ncode after setup or deployment.  There are situations where it is desirable to run some commands prior to\nrunning those rake tasks (e.g., if using bundler and needing to do a 'bundle install' before running rake).\nIt may also be the case that the target system doesn't have rake (and/or ruby) installed, but some post-setup\nor post-deploy operations need to happen.  For these reasons, whiskey\\_disk allows specifying a (bash-compatible)\nshell script to run after setup and/or deployment via the post\\_deploy\\_script and post\\_setup\\_script settings\nin the configuration file.  These scripts, when specified, are run immediately before running the deploy:post\\_setup\nor deploy:post\\_deploy rake tasks, if they are present.\n\nThe paths provided to post\\_deploy\\_script and post\\_setup\\_script can be either absolute or relative.  A path\nstarting with a '/' is an absolute path, and the script specified should be at that exact location on the\ntarget filesystem.  A path which does not start with a '/' is a relative path, and the script specified should\nbe located at the specified path under the deployed application path.  This implies that it's possible to\nmanage post\\_setup and post\\_deploy scripts out of a configuration repository.\n\nA config/deploy.yml using post\\_deploy\\_script and post\\_setup\\_script might look like this:\n\n    production:\n      domain: \"ogc@www.ogtastic.com\"\n      deploy_to: \"/var/www/www.ogtastic.com\"\n      repository: \"git@ogtastic.com:www.ogtastic.com.git\"\n      branch: \"stable\"\n      post_setup_script: \"/home/ogc/horrible_place_for_this/prod-setup.sh\"\n      post_deploy_script: \"bin/post-deploy.sh\"\n      rake_env:\n        RAILS_ENV: 'production'\n\nThe post\\_deploy\\_script will be run from /var/www/www.ogtastic.com/bin/post-deploy.sh on the\ntarget system.\n\n\n### Taking actions based on roles ###\n\n#### When running rake tasks or other ruby scripts ####\n\nWhiskey\\_disk includes a helper library for use in rake tasks and other ruby scripts.  In that library you'll\nfind a ruby function 'role?' which returns true if you're currently being deployed to a domain with the given\nrole.  For example:\n\n    require 'whiskey_disk/helpers'\n\n    namespace :deploy do\n      task :create_rails_directories do\n        if role? :www\n          puts \"creating log/ and tmp/ directories\"\n          Dir.chdir(RAILS_ROOT)\n          system(\"mkdir -p log tmp\")\n        end\n      end\n\n      task :db_migrate_if_necessary do\n        Rake::Task['db:migrate'] if role? :db\n      end\n\n      # whytf is this even necessary?  Come on.  This should be built into ts:restart.\n      task :thinking_sphinx_restart => [:environment] do\n        if role? :app\n          Rake::Task['ts:stop'].invoke rescue nil\n          Rake::Task['ts:index'].invoke\n          Rake::Task['ts:start'].invoke\n        end\n      end\n\n      task :bounce_passenger do\n        if role? :www\n          puts \"restarting Passenger web server\"\n          Dir.chdir(RAILS_ROOT)\n          system(\"touch tmp/restart.txt\")\n        end\n      end\n\n      # etc...\n\n      task :post_setup  => [ :create_rails_directories ]\n      task :post_deploy => [ :db_migrate_if_necessary, :thinking_sphinx_restart, :bounce_passenger ]\n    end\n\n\n#### When working with the shell ####\n\nInstalling the whiskey\\_disk gem also installs another binary, called wd_role.  It's job is really simple,\ngiven a role, determine if we're currently in a deployment that matches that role.  If so, exit with a success\nexit status, otherwise, exit with an error exit status.  This allows programs running in the shell to conditionally\nexecute code based on domain roles.  This is particularly applicable to post\\_setup\\_script and post\\_deploy\\_script\ncode.\n\nHere's an off-the-cuff example of how one might use wd\\_role.  We have the rockhands gem installed (obviously), and\nare in an environment where the 'app' role is active but the 'web' role is not:\n\n\n    $ wd_role web && rock || shocker\n         .-.\n       .-.U|\n       |U| | .-.\n       | | |_|U|\n       | | | | |\n      /|     ` |\n     | |       |\n     |         |\n      \\        /\n      |       |\n      |       |\n\n    $ wd_role app && rock || shocker\n       .-.\n       |U|\n       | |   .-.\n       | |-._|U|\n       | | | | |\n      /|     ` |\n     | |       |\n     |         |\n              /\n      |       |\n      |       |\n\n\n\n\n### Running whiskey\\_disk from the command-line ###\n\n    % wd setup --to=<target>\n    % wd setup --to=<project>:<target>\n    % wd setup --to=foo:qa --path=/etc/whiskey_disk/deploy.yml\n    % wd setup --to=foo:qa --path=https://github.com/username/project/raw/master/path/to/configs/deploy.yml\n    % wd setup --to=foo:qa --only=myhost.example.com\n\n    % wd deploy --to=<target>\n    % wd deploy --to=<project>:<target>\n    % wd deploy --to=foo:qa --path=/etc/whiskey_disk/deploy.yml\n    % wd deploy --to=foo:qa --path=https://github.com/username/project/raw/master/path/to/configs/deploy.yml\n    % wd deploy --to=foo:qa --only=myhost.example.com\n\n    % wd --help\n    % wd --version\n\n\n\nAlso, `--debug` can be used to enable verbose output when running `wd setup` or `wd deploy`.\n\nNote that the wd command (unlike rake, which requires a Rakefile in the current directory) can be run from anywhere, so you can deploy any project, working from any path, and can even specify where to find the deployment YAML configuration file.\n\nThe --path argument can take either a file or a directory.  When given a file it will use that file as the configuration file.  When given a directory it will look in that directory for deploy/&lt;project&gt;/&lt;target&gt;.yml, then deploy/&lt;project&gt;.yml, then deploy/&lt;target&gt;.yml, then &lt;target&gt;.yml, and finally, deploy.yml.\n\nTo make things even better, you can provide an URL as the --path argument and have a central location from which to pull deployment YAML data.  This means that you can centrally administer the definitive deployment information for the various projects and targets you manage.  This could be as simple as keeping them in a text file hosted on a web server, checking them into git and using github or gitweb to serve up the file contents on HEAD, or it could be a programmatically managed configuration management system returning dynamically-generated results.\n\nAll this means you can manage a large number of project deployments (local or remote) and have a single scripted deployment manager that keeps them up to date.  Configurations can live in a centralized location, and developers don't have to be actively involved in ensuring code gets shipped up to a server.  Win.\n\nWhen doing scripted deployments for a group of nodes who appear in the same 'domain' list, it's possible to specify the --only setting so that you can identify which domain entries belong to a specific node.  For example, given this configuration:\n\n\n    production:\n      domain:\n      - foo.example.com\n      - bar.example.com\n      repository: git@github.com:foo.git\n\n\nWe would like to be able to set up the following scripted runs on foo.example.com and bar.example.com:\n\n\n    foo% wd deploy --to=app:production --path=http://automation.example.com/wd/deploy.yml\n    bar% wd deploy --to=app:production --path=http://automation.example.com/wd/deploy.yml\n\n\nBut without specifying --only we end up with undesired results.  When foo.example.com runs it will see that it needs to make sure deployment happens on 'foo.example.com' and 'bar.example.com'.  So, wd will ssh from foo.example.com to foo.example.com (less than ideal), deploy, and then ... it will ssh from foo.example.com to bar.example.com and do a deployment.  When bar.example.com runs, however, it will also ssh to bar.example.com, and also to foo.example.com.  So each host will be deployed twice.\n\nThe --only setting is used to tell a node what its name is, and to tell it not to bother trying to deploy other nodes that it finds in the target's \"domain\" listing.  In other words, deployment is being managed from afar, and it's best to just manage ourselves and forego managing other nodes.\n\n\n### A note about post\\_{setup,deploy} Rake tasks\n\nIf you want actions to run on the deployment target after you do a whiskey\\_disk setup or whiskey\\_disk deploy,\nyou will need to make sure that whiskey\\_disk is available on the target system (either by gem installation,\nas a rails plugin in the Rails application to be deployed, or as a vendored library in the application to be\ndeployed).  Whiskey\\_disk provides the basic deploy:post\\_setup and deploy:post\\_deploy hooks which get called.\nYou can also define these tasks yourself if you want to eliminate the dependency on whiskey\\_disk on the\ndeployment target system.\n\n\n### Doing things when files of interest change ###\n\nDo you want to run database migrations when no migrations have been added?  Why bother compressing front-end assets when none of them have changed?  Why restart your application server if only the project README changed?  Whiskey\\_disk provides a `changed?` ruby helper method to allow you to decide whether to run expensive post deployment tasks, based on what files changed in the deployment.  Typically this would happen in your rake tasks, but it could happen from regular ruby code as well.\n\n\n    require 'whiskey_disk/helpers'\n\n    namespace :deploy do\n\n      task :run_migrations do\n        if role?(:db) and changed?('db/migrate')\n          puts \"Running database migrations...\"\n          Rake::Task['db:migrate'].invoke\n        end\n      end\n\n      task :compress_assets do\n        if changed?('public/stylesheets') or changed?('public/javascripts')\n          puts \"Getting my asset munge on...\"\n          # do some expensive asset compression stuff\n        end\n      end\n\n      task :post_deploy => [ :run_migrations, :compress_assets ]\n    end\n\n\n\n### Running via rake ###\n\nYou can use rake tasks to do everything possible with whiskey\\_disk (the `wd` command is just a front-end to the whiskey\\_disk rake tasks).  In your Rakefile:\n\n    require 'whiskey_disk/rake'\n\n  Then, from the command-line:\n\n    % rake deploy:setup to=<target>   (e.g., \"qa\", \"staging\", \"production\", etc.)\n    % rake deploy:now   to=<target>\n\n  or, specifying the project name:\n\n    % rake deploy:setup to=<project>:<target>   (e.g., \"foo:qa\", \"bar:production\", etc.)\n    % rake deploy:now   to=<project>:<target>\n\n  enabling staleness checking (see below):\n\n    % rake deploy:setup to=<project>:<target> check=yes\n    % rake deploy:now   to=<project>:<target> check=yes\n\n  maybe even specifying the path to the configuration file:\n\n    % rake deploy:setup to=<project>:<target> path=/etc/deploy.yml\n    % rake deploy:now   to=<project>:<target> path=/etc/deploy.yml\n\n  how about specifying the configuration file via URL:\n\n    % rake deploy:setup to=<project>:<target> path=https://github.com/username/project/raw/master/path/to/configs/deploy.yml\n    % rake deploy:now   to=<project>:<target> path=https://github.com/username/project/raw/master/path/to/configs/deploy.yml\n\n  Finally, it's also possible to specify the 'only' variable to limit 'domain' entries of interest:\n\n    % rake deploy:setup to=<project>:<target> only=myhost.example.com\n    % rake deploy:now to=<project>:<target> only=myhost.example.com\n\n  (see the discussion of --only above in \"Running whiskey\\_disk from the command-line\" for more information)\n\n\n### Staleness checks ###\n\nEnabling staleness checking will cause whiskey\\_disk to check whether the deployed checkout of the repository\nis out of date (\"stale\") with respect to the upstream version in git.  If there is a configuration repository\nin use, whiskey\\_disk will check the deployed checkout of the configuration repository for staleness as well.\nIf the checkouts are already up-to-date the deployment process will print an up-to-date message and stop rather\nthan proceeding with any of the deployment actions.  This makes it easy to simply run whiskey\\_disk out of cron\nso that it will automatically perform a deployment whenever changes are pushed to the upstream git repositories.\n\nTo turn on staleness checking, simply specify the '--check' flag when deploying (or the shorter '-c')\n\n    wd deploy --check --to=foobar:production\n\nIf running whiskey\\_disk purely via rake, you can also enable staleness checking.  This works by setting the 'check'\nenvironment variable to the string 'true' or 'yes':\n\n    % check='true' to='whiskey_disk:testing' rake deploy:now\n\n\n### Configuration Repository ###\n\n#### What's all this about a second repository for configuration stuff? ####\n\nThis is completely optional, but we really are digging this, so maybe\nyou should try it.  Basically it goes like this...\n\nWe have a number of web applications that we manage.  Usually there's a\ncustomer, there might be third-party developers, or the customer might have\naccess to the git repo, or their designer might, etc.  We also tend to run a\nfew instances of any given app, for any given customer.  So, we'll run a\n\"production\" site, which is the public- facing, world-accessible main site.\nWe'll usually also run a \"staging\" site, which is roughly the same code, maybe\nthe same data, running on a different URL, which the customer can look at to\nsee if the functionality there is suitable for deploying out to production.  We\nsometimes run a \"development\" site which is even less likely to be the same\ncode as production, etc., but gives visibility into what might end up in\nproduction one day soon.\n\nSo we'll store the code for all of these versions of a site in the same git\nrepo, typically using a different remote branch for each target\n(\"qa\", \"production\", \"staging\", \"development\").\n\nOne thing that comes up pretty quickly is that there are various files\nassociated with the application which have more to do with configuration of a\nrunning instance than they have to do with the application in general.  In the\nrails world these files are probably in config, or config/initializers/.  Think\ndatabase connection information, search engine settings, exception notification\nplugin data, email configuration, Amazon S3 credentials, e-commerce back-end\nconfiguration, etc.\n\nWe don't want the production site using the same database as the\ndevelopment site.  We don't want staging using (and re-indexing, re-starting,\netc.) production's search engine server.  We don't want any site other than\nproduction to send account reset emails, or to push orders out to fulfillment,\netc.\n\nFor some reason, the answer to this with cap and/or vlad has been to have\nrecipes which reference various files up in a shared area on the server, do\ncopying or symlinking, etc.  Where did those files come from?  How did they get\nthere?  How are they managed over time?  If they got there via a configuration\ntool, why (a) are they not in the right place, or (b) do we have to do work to\nget them into the right place?\n\nSo, we decided that we'd change how we deal with the issue.  Instead of\nmoving files around or symlinking every time we deploy, we will manage the\nconfiguration data just like we manage other files required by our projects --\nwith git.\n\nSo, each project we deploy is associated with a config repo in our git\nrepository.  Usually many projects are in the same repo, because we're the only\npeople to see the data and there's no confidentiality issue.  But, if a\ncustomer has access to their git information then we'll make a separate config\nrepo for all that customers' projects.  (This is easier to manage than it\nsounds if you're using gitosis, btw.)\n\nAnyway, a config repo is just a git repo.  In it are directories for every\nproject whose configuration information is managed in that repo.  For example,\nthere's a \"larry\" directory in our main config repo, because we're deploying\nthe [larry project](http://github.com/flogic/larry) to manage our high-level\nconfiguration data.\n\nNote, if you set the 'project' setting in deploy.yml, that determines the\nname of the top-level project directory whiskey\\_disk will hunt for in your\nconfig repo.  If you don't it uses the 'repository' setting (i.e., the git URL)\nto try to guess what the project name might be.  So if the URL ends in\nfoo/bar.git, or foo:bar.git, or /bar, or :bar, whiskey\\_disk is going to guess\n\"bar\".  If it's all bitched up, just set 'project' manually in deploy.yml.\n\nInside the project directory is a directory named for each target we\nmight deploy to.  Frankly, we've been using \"production\", \"staging\",\n\"development\", and \"local\" on just about everything.\n\nInside the target directory is a tree of files.  So, e.g., there's\nconfig/, which has initializers/ and database.yml in it.\n\nLong story short, load up whatever configuration files you're using into\nthe repo as described, and come deployment time exactly those files will be\noverlaid on top of the most recent checkout of the project.  Snap.\n\n    project-config/\n      |\n      +---larry/\n            |\n            +---production/\n            |     |\n            |     +---config/\n            |           |\n            |           +---initializers/\n            |           |\n            |           +---database.yml\n            |\n            +---staging/\n            |     |\n            |     |\n            |     +---config/\n            |           |\n            |           ....\n            |\n            +---development/\n            |     |\n            |     +---config/\n            |           |\n            |           ....\n            |\n            +---local/\n                  |\n                  +---config/\n                        |\n                        ....\n\n\n#### Sharing a set of configuration files among multiple targets ####\n\nDevelopers on applications with many deployment targets can find that configuration repositories can become a burden to maintain, especially when a number of environments share essentially the same configurations.  For example, for an application where deployments for user acceptance testing, QA, staging, and feature branch demoing are all essentially the same (though differing from production configurations and developer configurations), it's probably easiest to store a configuration for development, a configuration for production, a configuration for staging and then use the staging configuration for all the other environments: user acceptance testing, QA, staging, demo1, demo2, etc.  Using the config\\_target setting, a deploy.yml might look like this:\n\n\n    production:\n      domain: \"www.ogtastic.com\"\n      deploy_to: \"/var/www/www.ogtastic.com\"\n      repository: \"git@ogtastic.com:www.ogtastic.com.git\"\n      branch: \"production\"\n      config_repository: \"git@ogtastic.com:ogc-production-config.git\"\n    development:\n      deploy_to: '/var/www/devel.ogtastic.com'\n      repository: \"git@ogtastic.com:www.ogtastic.com.git\"\n      branch: \"develop\"\n      config_repository: \"git@ogtastic.com:ogc-config.git\"\n    staging:\n      [...]\n      config_repository: \"git@ogtastic.com:ogc-config.git\"\n    uat:\n      [....]\n      config_repository: \"git@ogtastic.com:ogc-config.git\"\n      config_target: \"staging\"\n    qa:\n      [....]\n      config_repository: \"git@ogtastic.com:ogc-config.git\"\n      config_target: \"staging\"\n\n\nSo here we have the 'staging', 'uat', and 'qa' deployment targets all sharing the 'staging' configuration repo information.  The non-production configuration repo can then look like:\n\n\n    project-config/\n      |\n      +---ogtastic/\n            |\n            +---staging/\n            |     |\n            |     |\n            |     +---config/\n            |           |\n            |           ....\n            |\n            +---development/\n                  |\n                  +---config/\n                        |\n                        ....\n\n\nNotice that there are no separate trees for 'uat' and 'qa' targets.\n\n### More Examples: ###\n\n - We are using whiskey\\_disk to manage larry.  See [https://github.com/flogic/larry/blob/master/config/deploy-local.yml.example](https://github.com/flogic/larry/blob/master/config/deploy-local.yml.example) and [http://github.com/flogic/larry/blob/master/lib/tasks/deploy.rake](http://github.com/flogic/larry/blob/master/lib/tasks/deploy.rake)\n\n - Here is a sample of a lib/tasks/deploy.rake from a Rails application we deployed once upon a time:\n\n\n\n        RAILS_ENV=ENV['RAILS_ENV'] if ENV['RAILS_ENV'] and '' != ENV['RAILS_ENV']\n        Rake::Task['environment'].invoke\n\n        require 'asset_cache_sweeper'\n\n        namespace :deploy do\n          task :create_rails_directories do\n            puts \"creating log/ and tmp/ directories\"\n            Dir.chdir(RAILS_ROOT)\n            system(\"mkdir -p log tmp\")\n          end\n\n          # note that the plpgsql language needs to be installed by the db admin at initial database creation :-/\n          task :setup_postgres_for_thinking_sphinx => [ :environment ] do\n            ThinkingSphinx::PostgreSQLAdapter.new(Product).setup\n          end\n\n          # whytf is this even necessary?  Come on.  This should be built into ts:restart.\n          task :thinking_sphinx_restart => [:environment] do\n            Rake::Task['ts:stop'].invoke rescue nil\n            Rake::Task['ts:index'].invoke\n            Rake::Task['ts:start'].invoke\n          end\n\n          task :bounce_passenger do\n            puts \"restarting Passenger web server\"\n            Dir.chdir(RAILS_ROOT)\n            system(\"touch tmp/restart.txt\")\n          end\n\n          task :clear_asset_cache => [:environment] do\n            STDERR.puts \"Expiring cached Assets for domains [#{AssetCacheSweeper.domains.join(\", \")}]\"\n            AssetCacheSweeper.expire\n          end\n\n          task :post_setup => [ :create_rails_directories, :setup_postgres_for_thinking_sphinx ]\n          task :post_deploy => [ 'db:migrate', 'ts:config', :thinking_sphinx_restart, :bounce_passenger, :clear_asset_cache ]\n        end\n\n### Future Directions ###\n\nCheck out the [Pivotal Tracker project](https://www.pivotaltracker.com/projects/202125)\nto see what we have in mind for the near future.\n\n### Resources ###\n\n - [http://github.com/blog/470-deployment-script-spring-cleaning](http://github.com/blog/470-deployment-script-spring-cleaning)\n - [http://github.com/mislav/git-deploy](http://github.com/mislav/git-deploy)\n - [http://toroid.org/ams/git-website-howto](http://toroid.org/ams/git-website-howto)\n\n### Support ###\n\nThe [bug tracker](https://github.com/flogic/whiskey_disk/issues)\nis available here:\n\n  -  [https://github.com/flogic/whiskey_disk/issues](https://github.com/flogic/whiskey_disk/issues)\n\nThe IRC channel is #whiskey_disk on freenode.\n\n### Contributors ###\n\n - [Rick Bradley](https://github.com/rick): author\n - [James Cox](https://github.com/imajes): bugfixes, prototyping, design help, code, feedback\n - [Rein Henrichs](https://github.com/reinh): design help, code\n - [Jeremy Holland](https://github.com/awebneck): code\n - [Kevin Barnes](https://github.com/vinbarnes): design help, code\n - [Alex Sharp](https://github.com/ajsharp): issues, real-world usage cases, design help\n - [Yossef Mendelssohn](https://github.com/ymendel): design help, proofreading\n - [Aaron Kalin](https://github.com/martinisoft) - bug hunting\n - [Brandon Valentine](https://github.com/brandonvalentine) - help with bug fixing\n - [Josh Moore](https://github.com/joshsmoore): bug hunting\n\n - Documentation/feedback: [Cristi Balan](https://github.com/evilchelu), [Hedgehog](http://github.com/hedgehog)\n"
  },
  {
    "path": "Rakefile",
    "content": "require 'rake'\nrequire 'rake/testtask'\n\ndesc 'Default: run unit tests.'\ntask :default => :test\n\ndesc 'Test whiskey_disk'\ntask :test do\n  files = Dir['spec/**/*_spec.rb'].join(\" \")\n  system(\"bacon #{files}\")\nend\n\nnamespace :integration do\n  def say(mesg)\n    STDERR.puts mesg\n  end\n\n  def vagrant_path\n    File.expand_path(File.join(File.dirname(__FILE__), 'scenarios', 'setup', 'vagrant'))\n  end\n\n  def root_path\n    File.expand_path(File.dirname(__FILE__))\n  end\n\n  def pidfile\n    File.join(vagrant_path, 'pids', 'git-daemon.pid')\n  end\n\n  def start_git_daemon\n    stop_git_daemon\n    say \"Starting git daemon...\"\n    run(root_path, \"git daemon --base-path=#{root_path}/scenarios/git_repositories/ --reuseaddr --verbose --detach --pid-file=#{pidfile}\")\n  end\n\n  def stop_git_daemon\n    return unless File.exists?(pidfile)\n    pid = File.read(pidfile).chomp\n    return if pid == ''\n    say \"Stopping git daemon...\"\n    run(root_path, \"kill #{pid}\")\n  end\n\n  def start_vm\n    say \"Bringing up vagrant vm...\"\n    run(vagrant_path, 'vagrant up')\n    copy_ssh_config\n  end\n\n  def stop_vm\n    say \"Shutting down vagrant vm...\"\n    run(vagrant_path, 'vagrant halt')\n  end\n\n  def copy_ssh_config\n    say \"Capturing vagrant ssh_config data...\"\n    run(vagrant_path, \"vagrant ssh_config > #{vagrant_path}/ssh_config\")\n  end\n\n  def run(path, cmd)\n    Dir.chdir(path)\n    say \"running: #{cmd} [cwd: #{Dir.pwd}]\"\n    system(cmd)\n  end\n\n  desc 'Start a vagrant VM and git-daemon server to support running integration specs'\n  task :up do\n    start_vm\n    start_git_daemon\n  end\n\n  desc 'Shut down integration vagrant VM and git-daemon server'\n  task :down do\n    stop_git_daemon\n    stop_vm\n  end\n\n  desc 'Completely remove the vagrant VM files used by the integration spec suite'\n  task :destroy do\n    stop_git_daemon\n    stop_vm\n    run(vagrant_path, 'vagrant destroy')\n  end\nend\n\nbegin\n  require 'jeweler'\n  Jeweler::Tasks.new do |gemspec|\n    gemspec.name = \"whiskey_disk\"\n    gemspec.summary = \"embarrassingly fast deployments.\"\n    gemspec.description = \"Opinionated gem for doing fast git-based server deployments.\"\n    gemspec.email = \"rick@rickbradley.com\"\n    gemspec.homepage = \"http://github.com/flogic/whiskey_disk\"\n    gemspec.authors = [\"Rick Bradley\"]\n    gemspec.add_dependency('rake')\n\n    # I've decided that the integration spec shizzle shouldn't go into the gem\n    rejected = %w(scenarios spec/integration)\n    gemspec.files.reject {|f| rejected.include?(f) }\n    gemspec.test_files.reject {|f| rejected.include?(f) }\n  end\n  Jeweler::GemcutterTasks.new\nrescue LoadError\n  # if you get here, you need Jeweler installed to do packaging and gem installation, yo.\nend\n\n"
  },
  {
    "path": "VERSION",
    "content": "0.6.24\n"
  },
  {
    "path": "WHY.txt",
    "content": "\nWhy?\n----\n\nThe idea here is inspired by github's cleaned up deployment scripts, and mislav's git-deploy project.  Only, we gave up on capistrano a long time ago, and after a few years of doing deployments on a few dozen projects, we realized that we really have very little variation on how we do things.  That is, we can afford to have a very opinionated tool to do our deployments.\n\nHere are the features/constraints we're envisioning:\n\n - We need some sort of very basic \"run this on a remote server\" functionality.  We've been using vlad for years now and this would suffice:  it does what we're looking for and is much much smaller than capistrano.  If we don't load the included recipes it's basically a fancy ruby ssh wrapper.\n \n - Setup should mostly just do a very fast remote git checkout in the right place.  Deployment should very quickly update that checkout.\n \n - We have been considering a move towards tracking configuration data across our projects as a separate concern.  So, if we can have a private repo that stores per-project and per-environment (here I mean staging vs. production, etc.) configuration files, and have our deployments overlay those files quickly, that would be ideal.  I'm talking about hoptoad configs, database.yml files, AWS cert files, GeoKit API keys, etc., etc., etc.\n\n - We should be able to use the same \"setup == clone\" + \"deploy == reset\" technique to manage the per-project/per-environment config files.\n \n - Using rsync on the remote to those overlay config files on the deployed project would be a fast way to get them in place.\n \n - Get rid of a bunch of annoying symlinks and symlink-hoops-to-jump-through.\n \n - Get rid of a bunch of space (yeah yeah disk is cheap, but copying isn't) on the disk devoted to umpteen \"releases\".\n \n - Obviously reduce deployment time by doing less, ssh-ing less, and taking less time to do whatever.\n \n - should be rake based, and should provide a bare minimum of tasks -- like deploy:setup, deploy:now, and maybe a deploy:refresh_config_files.\n \n - While a very basic task or few would run after setup or after deployment (e.g., rake db:migrate if migrations were changed, or touch tmp/restart.txt if the web server needs a restart; see git-deploy for more examples), we should be able to declare optional rake tasks (e.g., \"deploy:staging:post_deploy\") and have them run on this project if they are declared.\n \n - Should work with projects that aren't remotely ruby.\n \n - Should be loadable as a gem, meaning that it doesn't need to live in your project's space.  (see also non-ruby projects)\n \n - Should be able to use a non-ruby config, preferably yaml, for information for all environments.  That could be stored in <project>/config/deploy.yml and saved with the project.  Even if this is just shoved into vlad 'set' commands, it's still an improvement:  we don't need ruby in the config file because we're opinionated.\n \n - should be able to override settings for an environment locally by declaring a <project>/config/deploy-<environment>.yml.  Ideal for testing out deployments to different servers (or deploying locally).  This also makes it possible to .gitignore your local settings, so everyone can have their config repos in different places.\n \n - should make it easier to do local development (e.g., on a laptop) by being able to overlay config files using the same rake tasks as used for remote deployments, just not running the functionality remotely.\n \n - dropping in a project Rakefile can add post-deploy / post-setup hooks transparently.\n \n - actually have meaningful error messages, unlike anything that ever seems to happen with cap or vlad.  :-/\n\n - build this spec-first (whenever possible) so that there's a useful test suite.\n \n - M$ windows hasn't been a priority for me for over a decade, not starting now.\n"
  },
  {
    "path": "bin/wd",
    "content": "#!/usr/bin/env ruby \n\nrequire 'optparse'\nrequire 'whiskey_disk/rake'\n\n$0 = \"#{$0} setup|deploy\"  # jesus, this is a hack.\n\noptions = {}\nop = OptionParser.new do |opts|\n  opts.on('-t=TARGET', '--to=TARGET', \"deployment target\") do |target| \n    options[:target] = target\n  end\n  \n  opts.on('-p=TARGET', '--path=TARGET', \"configuration path\") do |path|\n    options[:path] = path\n  end\n    \n  opts.on('-o=DOMAIN', '--only=DOMAIN', \"limit deployment to this domain\") do |domain|\n    options[:only] = domain\n  end\n    \n  opts.on('-c', '--check', \"do a staleness check before deploying\") do |path|\n    options[:check] = 'true'\n  end\n\n  opts.on('-d', '--debug', \"turn on debug mode (ssh -v and rake --trace)\") do\n    options[:debug] = 'true'\n  end\n    \n  opts.on('--version', 'show current version') do\n    puts File.read(File.expand_path(File.join(File.dirname(__FILE__), '..', 'VERSION')))\n    exit 0\n  end\n  \n  opts.on_tail('-h', '--help', 'show this message') do\n    abort opts.to_s\n  end\nend\n\nbegin\n  rest = op.parse(ARGV) \nrescue \n  abort op.to_s \nend\n\nabort op.to_s unless options[:target]\nabort op.to_s unless rest and rest.size == 1\ncommand = rest.first\nabort op.to_s unless ['deploy', 'setup'].include?(command)\n\nENV['to'] = options[:target]\nENV['path'] = options[:path]\nENV['only'] = options[:only]\nENV['check'] = options[:check]\nENV['debug'] = options[:debug]\n\nif command == 'deploy'\n  Rake::Task['deploy:now'].invoke\nelse\n  Rake::Task['deploy:setup'].invoke\nend\n"
  },
  {
    "path": "bin/wd_role",
    "content": "#!/usr/bin/env ruby \nrequire 'whiskey_disk/helpers'\n\n# simple command-line script to detect whether this deployment target\n# is in a specified whiskey_disk role.  sets exit status appropriately\n#\n# useful for conditionalizing shell scripting based on roles.\n\nrole = ARGV.shift\nexit(1) unless role?(role)\n\n__END__\n\n( this example session presumes you `gem install rockhands` first... )\n\n$ export WD_ROLES='app:db'\n$ wd_role web && rock || shocker\n     .-.     \n   .-.U|     \n   |U| | .-. \n   | | |_|U| \n   | | | | | \n  /|     ` |\n | |       | \n |         | \n  \\        / \n  |       |  \n  |       |  \n             \n$ wd_role app && rock || shocker\n   .-.       \n   |U|       \n   | |   .-. \n   | |-._|U| \n   | | | | | \n  /|     ` | \n | |       | \n |         | \n          / \n  |       |  \n  |       |  \n\n"
  },
  {
    "path": "examples/deploy-configs.yml",
    "content": "production:\n  domain: \"ogc@hoenir.websages.com\"\n  deploy_to: \"/tmp/test-deployment\"\n  deploy_config_to: \"/tmp/test-config\"\n  repository: \"git@git.ogtastic.com:whiskey_disk.git\"\n  config_repository: \"git@git.ogtastic.com:ogc-config.git\"\nstaging:\n  domain: \"ogc@hoenir.websages.com\"\n  deploy_to: \"/tmp/test-deployment\"\n  deploy_config_to: \"/tmp/test-config\"\n  repository: \"git@git.ogtastic.com:whiskey_disk.git\"\n  config_repository: \"git@git.ogtastic.com:ogc-config.git\"\n  config_target: \"local\"\n"
  },
  {
    "path": "examples/deploy-local.yml",
    "content": "local:\n  deploy_to: \"/Users/rick/deploy/whiskey_disk/local\"\n  repository: \"/Users/rick/git/whiskey_disk\"\n  branch: \"develop\"\n"
  },
  {
    "path": "examples/deploy-multiple-remotes.yml",
    "content": "multi:\n  domain:\n  - \"ogc@hoenir.websages.com\"\n  - \"ogc@nerthus.websages.com\"\n  deploy_to: \"/tmp/test-deployment/\"\n  repository: \"git@git.ogtastic.com:whiskey_disk.git\"\n  branch: \"develop\"\nroles:\n  domain:\n  - name: \"ogc@hoenir.websages.com\"\n    roles:\n    - web\n    - app\n  - name: \"ogc@nerthus.websages.com\"\n    roles: db \n  deploy_to: \"/tmp/test-deployment/\"\n  repository: \"git@git.ogtastic.com:whiskey_disk.git\"\n  branch: \"feature/support-domain-roles\"\n  post_deploy_script: \"/tmp/role-checker.sh\"\nbadmulti:\n  domain:\n  - \"ogc@hoenir.websages.com\"\n  - \"ogc@bogus.example.com\"\n  deploy_to: \"/tmp/test-deployment/\"\n  repository: \"git@git.ogtastic.com:whiskey_disk.git\"\n  branch: \"develop\"\n"
  },
  {
    "path": "examples/deploy-staging.yml",
    "content": "staging:\n  domain: \"user@www.example.com\"\n  deploy_to: \"/var/www/suparsite.com/\"\n  repository: \"git://github.com/clarkkent/suparsite.git\"\n  config_repository: \"git@github.com:clarkkent/suparconfig.git\"\n  deploy_config_to: \"/var/cache/git/suparconfig\"\n  rake_env:\n    RAILS_ENV: 'development'\n"
  },
  {
    "path": "examples/deploy.rake",
    "content": "namespace :deploy do\n  namespace :staging do\n    task :post_setup do\n      puts \"This is my local post_setup hook.\"\n    end\n\n    task :post_deploy do\n      puts \"This is my local post_deploy hook.\"\n    end\n  end\nend\n"
  },
  {
    "path": "examples/deploy.yml",
    "content": "staging:\n  domain: \"user@www.example.com\"\n  deploy_to: \"/var/www/suparsite.com/\"\n  repository: \"git://github.com/clarkkent/suparsite.git\"\n  config_repository: \"git@github.com:clarkkent/suparconfig.git\"\n  deploy_config_to: \"/var/cache/git/suparconfig\"\n  branch: \"production\"\n  rake_env:\n    RAILS_ENV: \"production\"\nlocal:\n  repository: \"git://github.com/clarkkent/suparsite.git\"\n  config_repository: \"git@github.com:clarkkent/suparconfig.git\"\n  deploy_to: \"/Users/clark/git/suparsite\"\n  deploy_config_to: \"/Users/clark/git/suparconfig\"\n  rake_env:\n    RAILS_ENV: \"production\"\n"
  },
  {
    "path": "init.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), 'lib', 'whiskey_disk'))\n"
  },
  {
    "path": "install.rb",
    "content": "def readme_contents\n  IO.read(File.expand_path(File.join(File.dirname(__FILE__), 'README.markdown')))\nend\n\nputs readme_contents\n"
  },
  {
    "path": "lib/whiskey_disk/config/abstract_filter.rb",
    "content": "class WhiskeyDisk\n  class Config\n    class AbstractFilter\n      attr_reader :config\n  \n      def initialize(config)\n        @config = config\n      end\n  \n      def project_name\n        config.project_name\n      end\n  \n      def environment_name\n        config.environment_name\n      end\n    end\n  end\nend"
  },
  {
    "path": "lib/whiskey_disk/config/filter.rb",
    "content": "require 'whiskey_disk/config/filters/stringify_hash_keys_filter'\nrequire 'whiskey_disk/config/filters/environment_scope_filter'\nrequire 'whiskey_disk/config/filters/project_scope_filter'\nrequire 'whiskey_disk/config/filters/select_project_and_environment_filter'\nrequire 'whiskey_disk/config/filters/add_environment_name_filter'\nrequire 'whiskey_disk/config/filters/add_project_name_filter'\nrequire 'whiskey_disk/config/filters/default_config_target_filter'\nrequire 'whiskey_disk/config/filters/default_domain_filter'\nrequire 'whiskey_disk/config/filters/hashify_domain_entries_filter'\nrequire 'whiskey_disk/config/filters/localize_domains_filter'\nrequire 'whiskey_disk/config/filters/check_for_duplicate_domains_filter'\nrequire 'whiskey_disk/config/filters/convert_role_strings_to_list_filter'\nrequire 'whiskey_disk/config/filters/drop_empty_domain_roles_filter'\nrequire 'whiskey_disk/config/filters/normalize_ssh_options_filter'\n\nclass WhiskeyDisk\n  class Config\n    class Filter\n      attr_reader :config, :filters\n  \n      def initialize(config)\n        @config = config\n        @filters = [\n          StringifyHashKeysFilter,\n          EnvironmentScopeFilter,\n          ProjectScopeFilter,\n          SelectProjectAndEnvironmentFilter,\n          AddEnvironmentNameFilter,\n          AddProjectNameFilter,\n          DefaultConfigTargetFilter,\n          DefaultDomainFilter,\n          HashifyDomainEntriesFilter,\n          LocalizeDomainsFilter,\n          CheckForDuplicateDomainsFilter,\n          ConvertRoleStringsToListFilter,\n          DropEmptyDomainRolesFilter,\n          NormalizeSshOptionsFilter\n        ]\n      end\n  \n      def filter_data(data)\n        filters.inject(data.clone) do |result, filter|\n          result = filter.new(config).filter(result)\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/whiskey_disk/config/filters/add_environment_name_filter.rb",
    "content": "require 'whiskey_disk/config/abstract_filter'\n\nclass WhiskeyDisk\n  class Config\n    class AddEnvironmentNameFilter < AbstractFilter\n      def filter(data)\n        data.merge( { 'environment' => environment_name } )\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/whiskey_disk/config/filters/add_project_name_filter.rb",
    "content": "require 'whiskey_disk/config/abstract_filter'\n\nclass WhiskeyDisk\n  class Config\n    class AddProjectNameFilter < AbstractFilter\n      def filter(data)\n        data.merge( { 'project' => project_name } )\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/whiskey_disk/config/filters/check_for_duplicate_domains_filter.rb",
    "content": "require 'whiskey_disk/config/abstract_filter'\n\nclass WhiskeyDisk\n  class Config\n    class CheckForDuplicateDomainsFilter < AbstractFilter\n      def check_domains(domain_list)\n        seen = {}\n        domain_list.each do |domain|\n          raise \"duplicate domain [#{domain['name']}] in configuration file for project [#{environment_name}], target [#{environment_name}]\" if seen[domain['name']]\n          seen[domain['name']] = true\n        end\n      end\n      \n      def filter(data)\n        check_domains(data['domain'])\n        data\n      end\n    end\n  end\nend\n\n"
  },
  {
    "path": "lib/whiskey_disk/config/filters/convert_role_strings_to_list_filter.rb",
    "content": "require 'whiskey_disk/config/abstract_filter'\n\nclass WhiskeyDisk\n  class Config\n    class ConvertRoleStringsToListFilter < AbstractFilter\n      def convert_roles_for_domain(domain)\n        return domain unless domain['roles']\n        domain.merge('roles' => [ domain['roles'] ].flatten)\n      end\n      \n      def convert_all_roles(domains_list)\n        domains_list.collect {|domain| convert_roles_for_domain(domain) }\n      end\n      \n      def filter(data)\n        data.merge('domain' => convert_all_roles(data['domain']))\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/whiskey_disk/config/filters/default_config_target_filter.rb",
    "content": "require 'whiskey_disk/config/abstract_filter'\n\nclass WhiskeyDisk\n  class Config\n    class DefaultConfigTargetFilter < AbstractFilter\n      def filter(data)\n        return data if data['config_target']\n        data.merge( { 'config_target' => environment_name })\n      end\n    end\n  end\nend"
  },
  {
    "path": "lib/whiskey_disk/config/filters/default_domain_filter.rb",
    "content": "require 'whiskey_disk/config/abstract_filter'\n\nclass WhiskeyDisk\n  class Config\n    class DefaultDomainFilter < AbstractFilter\n      def filter(data)\n        data.has_key?('domain') ? data : data.merge('domain' => [ { 'name' => 'local' } ] )\n      end\n    end\n  end\nend\n\n"
  },
  {
    "path": "lib/whiskey_disk/config/filters/drop_empty_domain_roles_filter.rb",
    "content": "require 'whiskey_disk/config/abstract_filter'\n\nclass WhiskeyDisk\n  class Config\n    class DropEmptyDomainRolesFilter < AbstractFilter\n      def has_empty_role?(domain)\n        return true unless domain.has_key?('roles')\n        return true if domain['roles'].nil?\n\n        roles = domain['roles'].uniq.compact\n        return true if roles == [ '' ]\n        return true if roles == []\n        \n        false\n      end\n      \n      def drop_empty_roles_for_domain(domain)\n        return domain unless has_empty_role?(domain)\n        domain.reject {|key, value| key == 'roles' }\n      end\n      \n      def drop_empty_domain_roles(domains_list)\n        domains_list.collect { |domain| drop_empty_roles_for_domain(domain) }\n      end\n      \n      def filter(data)\n        data.merge('domain' => drop_empty_domain_roles(data['domain']))\n      end\n    end\n  end\nend\n\n"
  },
  {
    "path": "lib/whiskey_disk/config/filters/environment_scope_filter.rb",
    "content": "require 'whiskey_disk/config/abstract_filter'\nrequire 'whiskey_disk/config/filters/modules/scope_helper'\n\nclass WhiskeyDisk\n  class Config\n    class EnvironmentScopeFilter < AbstractFilter      \n      include ScopeHelper\n\n      # is this data hash a bottom-level data hash without an environment name?\n      def needs_environment_scoping?(data)\n        repository_depth(data) == 0\n      end\n  \n      def filter(data)\n        return data unless needs_environment_scoping?(data)\n        { environment_name => data }\n      end\n    end\n  end\nend"
  },
  {
    "path": "lib/whiskey_disk/config/filters/hashify_domain_entries_filter.rb",
    "content": "require 'whiskey_disk/config/abstract_filter'\n\nclass WhiskeyDisk\n  class Config\n    class HashifyDomainEntriesFilter < AbstractFilter\n      def needs_hashing?(domain)\n        ! domain.respond_to?(:keys)\n      end\n\n      def hashify_domain(domain)\n        needs_hashing?(domain) ? { 'name' => domain } : domain\n      end\n\n      def new_domain\n        { 'name' => '' }\n      end\n\n      def hashify_domains(domain_list)\n        return new_domain unless domain_list\n        [ domain_list ].flatten.collect {|domain| hashify_domain(domain) }\n      end\n\n      def filter(data)\n        data.merge('domain' => hashify_domains(data['domain']))\n      end\n    end\n  end\nend\n\n"
  },
  {
    "path": "lib/whiskey_disk/config/filters/localize_domains_filter.rb",
    "content": "require 'whiskey_disk/config/abstract_filter'\n\nclass WhiskeyDisk\n  class Config\n    class LocalizeDomainsFilter < AbstractFilter\n      def is_local?(name)\n        name.nil? or name == ''\n      end\n      \n      def localize(name)\n        is_local?(name) ? 'local' : name\n      end\n      \n      def localize_domains(domain_list)\n        domain_list.collect {|domain| domain.merge('name' => localize(domain['name'])) }\n      end\n\n      def filter(data)\n        data.merge('domain' => localize_domains(data['domain']))\n      end\n    end\n  end\nend\n\n"
  },
  {
    "path": "lib/whiskey_disk/config/filters/modules/scope_helper.rb",
    "content": "class WhiskeyDisk\n  class Config\n    module ScopeHelper\n      def repository_depth(data, depth = 0)\n        raise 'no repository found' unless data.respond_to?(:has_key?)\n        return depth if data.has_key?('repository')\n        repository_depth(data.values.first, depth + 1)\n      end\n    end\n  end\nend"
  },
  {
    "path": "lib/whiskey_disk/config/filters/normalize_ssh_options_filter.rb",
    "content": "require 'whiskey_disk/config/abstract_filter'\n\nclass WhiskeyDisk\n  class Config\n    class NormalizeSshOptionsFilter < AbstractFilter\n      def drop_empties(options_list)\n        options_list.select {|option| option and option != '' }\n      end\n      \n      def drop_empty_ssh_options_for_domain(domain)\n        result = drop_empties([ domain['ssh_options'] ].flatten)\n        if result and result != []\n          domain.merge('ssh_options' => result)\n        else\n          domain.reject {|k,v| k == 'ssh_options' }\n        end\n      end\n      \n      def normalize_ssh_options(domains_list)\n        domains_list.collect { |domain| drop_empty_ssh_options_for_domain(domain) }\n      end\n      \n      def filter(data)\n        data.merge('domain' => normalize_ssh_options(data['domain']))\n      end\n    end\n  end\nend\n\n"
  },
  {
    "path": "lib/whiskey_disk/config/filters/project_scope_filter.rb",
    "content": "require 'whiskey_disk/config/abstract_filter'\nrequire 'whiskey_disk/config/filters/modules/scope_helper'\n\nclass WhiskeyDisk\n  class Config\n    class ProjectScopeFilter < AbstractFilter\n      include ScopeHelper\n\n      def repository_depth(data, depth = 0)\n        raise 'no repository found' unless data.respond_to?(:has_key?)\n        return depth if data.has_key?('repository')\n        repository_depth(data.values.first, depth + 1)\n      end\n  \n      # is this data hash an environment data hash without a project name?\n      def needs_project_scoping?(data)\n        repository_depth(data) == 1\n      end\n\n      # TODO: why do we continue to need override_project_name! ?\n      # TODO: this is invasive into Config's implementation\n      def override_project_name!(data)\n        return if ENV['to'] && ENV['to'] =~ /:/\n        ENV['to'] = data[environment_name]['project'] + ':' + ENV['to'] if data[environment_name]['project']\n      end\n\n      def filter(data)\n        return data unless needs_project_scoping?(data)\n        override_project_name!(data)\n        { project_name => data }\n      end\n    end\n  end\nend"
  },
  {
    "path": "lib/whiskey_disk/config/filters/select_project_and_environment_filter.rb",
    "content": "require 'whiskey_disk/config/abstract_filter'\n\nclass WhiskeyDisk\n  class Config\n    class SelectProjectAndEnvironmentFilter < AbstractFilter\n      def filter(data)\n        raise \"No configuration file defined data for project `#{project_name}`, environment `#{environment_name}`\" unless data and data[project_name] and data[project_name][environment_name]\n        data[project_name][environment_name]\n      end\n    end\n  end\nend"
  },
  {
    "path": "lib/whiskey_disk/config/filters/stringify_hash_keys_filter.rb",
    "content": "require 'whiskey_disk/config/abstract_filter'\n\nclass WhiskeyDisk\n  class Config\n    class StringifyHashKeysFilter < AbstractFilter\n      def stringify_hash(data)\n        result = {}\n        data.each_pair do |key, value|\n          result[key.to_s] = stringify(value)\n        end\n        result\n      end\n\n      def stringify(structure)\n        return structure.clone unless structure.respond_to? :keys\n        stringify_hash(structure)\n      end\n      \n      def filter(data)\n        stringify(data)\n      end\n    end\n  end\nend\n\n"
  },
  {
    "path": "lib/whiskey_disk/config.rb",
    "content": "require 'yaml'\nrequire 'uri'\nrequire 'open-uri'\nrequire 'whiskey_disk/config/filter'\n\nclass WhiskeyDisk\n  class Config\n    def fetch\n      raise \"Cannot determine current environment -- try rake ... to=staging, for example.\" unless environment_name\n      filter_data(load_data)\n    end\n\n    def debug?\n      env_flag_is_true?('debug')\n    end\n    \n    def domain_limit\n      env_key_or_false?('only')\n    end\n    \n    def check_staleness?\n      env_flag_is_true?('check')\n    end\n    \n    def configuration_file\n      return path if valid_path?(path)\n      \n      files = []\n\n      files += [\n        File.join(base_path, 'deploy', specified_project_name, \"#{environment_name}.yml\"),  # /deploy/foo/staging.yml\n        File.join(base_path, 'deploy', \"#{specified_project_name}.yml\") # /deploy/foo.yml\n      ] if specified_project_name\n\n      files += [\n        File.join(base_path, 'deploy', \"#{environment_name}.yml\"),  # /deploy/staging.yml\n        File.join(base_path, \"#{environment_name}.yml\"), # /staging.yml\n        File.join(base_path, 'deploy.yml') # /deploy.yml\n      ]\n\n      files.each { |file|  return file if File.exists?(file) }\n\n      raise \"Could not locate configuration file in path [#{base_path}]\"\n    end\n\n    def environment_name\n      return false unless env_has_key?('to')\n      return ENV['to'] unless ENV['to'] =~ /:/\n      ENV['to'].split(/:/)[1]\n    end\n\n    def specified_project_name\n      return false unless env_has_key?('to')\n      return false unless ENV['to'] =~ /:/\n      ENV['to'].split(/:/).first\n    end\n    \n    def contains_rakefile?(path)\n      File.exists?(File.expand_path(File.join(path, 'Rakefile')))\n    end\n\n    def find_rakefile_from_current_path\n      original_path = Dir.pwd\n      while (!contains_rakefile?(Dir.pwd))\n        return File.join(original_path, 'config') if Dir.pwd == '/'\n        Dir.chdir('..')\n      end\n      File.join(Dir.pwd, 'config')\n    ensure\n      Dir.chdir(original_path)\n    end\n\n    def base_path\n      path || find_rakefile_from_current_path\n    end\n\n    def valid_path?(path)\n      return false unless path\n      uri = URI.parse(path)\n      return path if uri.scheme\n      return path if File.file?(path)\n    end\n\n    def project_name\n      specified_project_name || 'unnamed_project'\n    end\n\n    # called only by #load_data\n    def configuration_data\n      open(configuration_file) {|f| f.read }\n    end\n\n    # called only by #fetch\n    def load_data\n      YAML.load(configuration_data)\n    rescue Exception => e\n      raise %Q{Error reading configuration file [#{configuration_file}]: \"#{e}\"}\n    end\n    \n    def filter\n      @filter ||= WhiskeyDisk::Config::Filter.new(self)\n    end\n    \n    # called only by #fetch\n    def filter_data(data)\n      filter.filter_data(data)\n    end\n\n  private\n\n    def path\n      env_key_or_false?('path')\n    end\n\n    def env_has_key?(key)\n      ENV[key] && ENV[key] != ''\n    end\n\n    def env_flag_is_true?(key)\n      !!(env_has_key?(key) && ENV[key] =~ /^(?:t(?:rue)?|y(?:es)?|1)$/)\n    end\n\n    def env_key_or_false?(key)\n      env_has_key?(key) ? ENV[key] : false\n    end  \n  end\nend\n"
  },
  {
    "path": "lib/whiskey_disk/helpers.rb",
    "content": "\n# is the current deployment domain in the specified role?\ndef role?(role)\n  return false unless ENV['WD_ROLES'] and ENV['WD_ROLES'] != ''\n  ENV['WD_ROLES'].split(':').include?(role.to_s)\nend\n\n# have files of interest changed on this deployment?\ndef changed?(path)\n  return true unless gc = git_changes\n  cleaned = Regexp.escape(path.sub(%r{/+$}, ''))\n  [ gc, rsync_changes ].flatten.compact.any? { |p| p =~ %r<^#{cleaned}(?:$|/)> }\nend\n\n# list of changed paths, according to git\ndef git_changes\n  changes = read_git_changes_file.split(\"\\n\").uniq\nrescue Exception\n  nil\nend\n\ndef rsync_changes\n  changes = read_rsync_changes_file.split(\"\\n\")\n  changes.map {|c| c.sub(/^[^ ]* [^ ]* [^ ]* /, '') }.\n          grep(/^[^ ]{9,} /).map {|c| c.sub(/^[^ ]{9,} /, '') }.\n          map {|s| s.sub(%r{/$}, '') } - ['.']\nrescue Exception\n  nil\nend\n\ndef read_git_changes_file\n  File.read(git_changes_path)\nend\n\ndef read_rsync_changes_file\n  File.read(rsync_changes_path)\nend\n\ndef changes_file_root\n  path = IO.popen(\"git rev-parse --show-toplevel\").read\n  path == '' ? Dir.pwd : path.chomp\nend\n\ndef git_changes_path\n  File.join(changes_file_root, '.whiskey_disk_git_changes')\nend\n\ndef rsync_changes_path\n  File.join(changes_file_root, '.whiskey_disk_rsync_changes')\nend"
  },
  {
    "path": "lib/whiskey_disk/rake.rb",
    "content": "require 'rake'\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', 'whiskey_disk'))\n\nnamespace :deploy do\n  desc \"Perform initial setup for deployment\"\n  task :setup do\n    @whiskey_disk = WhiskeyDisk.new\n    @whiskey_disk.ensure_main_parent_path_is_present\n    @whiskey_disk.ensure_config_parent_path_is_present      if @whiskey_disk.has_config_repo?\n    @whiskey_disk.checkout_main_repository\n    @whiskey_disk.checkout_configuration_repository         if @whiskey_disk.has_config_repo?\n    @whiskey_disk.update_main_repository_checkout\n    @whiskey_disk.update_configuration_repository_checkout  if @whiskey_disk.has_config_repo?\n    @whiskey_disk.refresh_configuration                     if @whiskey_disk.has_config_repo?\n    @whiskey_disk.initialize_all_changes\n    @whiskey_disk.run_post_setup_hooks\n    @whiskey_disk.flush\n    @whiskey_disk.summarize\n\n    exit(1) unless @whiskey_disk.success?\n  end\n  \n  desc \"Deploy now.\"\n  task :now do\n    @whiskey_disk = WhiskeyDisk.new(:staleness_checks => true)\n    @whiskey_disk.update_main_repository_checkout\n    @whiskey_disk.update_configuration_repository_checkout  if @whiskey_disk.has_config_repo?\n    @whiskey_disk.refresh_configuration                     if @whiskey_disk.has_config_repo?\n    @whiskey_disk.run_post_deploy_hooks\n    @whiskey_disk.flush\n    @whiskey_disk.summarize\n\n    exit(1) unless @whiskey_disk.success?\n  end\n  \n  task :post_setup do\n    @whiskey_disk = WhiskeyDisk.new\n    env = @whiskey_disk.setting(:environment)\n    Rake::Task[\"deploy:#{env}:post_setup\"].invoke if Rake::Task.task_defined? \"deploy:#{env}:post_setup\"      \n  end\n\n  task :post_deploy do\n    @whiskey_disk = WhiskeyDisk.new\n    env = @whiskey_disk.setting(:environment)\n    Rake::Task[\"deploy:#{env}:post_deploy\"].invoke if Rake::Task.task_defined? \"deploy:#{env}:post_deploy\"      \n  end\nend\n"
  },
  {
    "path": "lib/whiskey_disk.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), 'whiskey_disk', 'config'))\n\nclass WhiskeyDisk\n  attr_writer :configuration, :config\n  attr_reader :results\n  \n  def initialize(options = {})\n    @staleness_checks = true if options[:staleness_checks]\n  end\n  \n  def buffer\n    @buffer ||= []\n  end\n  \n  def config\n    @config ||= WhiskeyDisk::Config.new\n  end\n  \n  def configuration\n    @configuration ||= config.fetch\n  end\n  \n  def debugging?\n    config.debug?\n  end\n  \n  def setting(key)\n    configuration[key.to_s]\n  end\n  \n  def check_staleness?\n    config.check_staleness?\n  end\n  \n  def staleness_checks_enabled?\n    !!@staleness_checks\n  end    \n\n  def enqueue(command)\n    buffer << command\n  end\n  \n  def remote?(domain)\n    return false unless domain\n    return false if domain == 'local'\n    limit = config.domain_limit \n    return false if limit and domain_limit_match?(domain, limit)\n\n    true\n  end\n  \n  def has_config_repo?\n    ! (setting(:config_repository).nil? or setting(:config_repository) == '')\n  end\n  \n  def project_name_specified?\n    setting(:project) != 'unnamed_project'\n  end\n\n  def branch\n    (setting(:branch) and setting(:branch) != '') ? setting(:branch) : 'master'\n  end\n  \n  def config_branch\n    (setting(:config_branch) and setting(:config_branch) != '') ? setting(:config_branch) : 'master'\n  end\n  \n  def env_vars\n    return '' unless setting(:rake_env)\n    setting(:rake_env).keys.inject('') do |buffer,k| \n      buffer += \"#{k}='#{setting(:rake_env)[k]}' \"\n      buffer\n    end\n  end\n  \n  def parent_path(path)\n    File.split(path).first\n  end\n  \n  def tail_path(path)\n    File.split(path).last\n  end\n  \n  def needs(*keys)\n    keys.each do |key|\n      raise \"No value for '#{key}' declared in configuration files [#{config.configuration_file}]\" unless setting(key)\n    end\n  end\n\n  def apply_staleness_check(commands)\n    needs(:deploy_to, :repository)\n    \n    check = \"cd #{setting(:deploy_to)}; \" +\n            \"ml=\\`git log -1 --pretty=format:%H\\`; \" +\n            \"mr=\\`git ls-remote #{setting(:repository)} refs/heads/#{branch}\\`; \"\n    \n    if setting(:deploy_config_to)\n      check += \"cd #{setting(:deploy_config_to)}; \" +\n               \"cl=\\`git log -1 --pretty=format:%H\\`; \" +\n               \"cr=\\`git ls-remote #{setting(:config_repository)} refs/heads/#{config_branch}\\`; \"\n    end\n    \n    check += \"if [[ $ml != ${mr%%\\t*} ]] \" +\n             (setting(:deploy_config_to) ? \"|| [[ $cl != ${cr%%\\t*} ]]\" : '') +\n             \"; then #{commands}; else echo \\\"No changes to deploy.\\\"; fi\"\n  end\n  \n  def join_commands\n    buffer.collect {|c| \"{ #{c} ; }\"}.join(' && ')\n  end\n  \n  def bundle\n    return '' if buffer.empty?\n    (staleness_checks_enabled? and check_staleness?) ? apply_staleness_check(join_commands) : join_commands\n  end\n\n  def domain_limit_match?(domain, limit)\n    domain.sub(%r{^.*@}, '') == limit\n  end\n  \n  def domain_of_interest?(domain)\n    return true unless limit = config.domain_limit\n    domain_limit_match?(domain, limit)\n  end\n  \n  def encode_roles(roles)\n    return '' unless roles and !roles.empty?\n    \"export WD_ROLES='#{roles.join(':')}'; \"\n  end\n\n  def build_command(domain, cmd)\n    \"#{'set -x; ' if debugging?}\" + encode_roles(domain['roles']) + cmd\n  end\n  \n  def run(domain, cmd)\n    ssh(domain, cmd)\n  end\n\n  def ssh(domain, cmd)\n    args = []\n    args << domain['name']\n    args << '-v' if debugging?\n    args += domain['ssh_options'] if domain['ssh_options']\n    args << build_command(domain, cmd)\n\n    puts \"Running: ssh #{args.join(' ')}\" if debugging?\n    system('ssh', *args)\n  end\n  \n  def shell(domain, cmd)\n    puts \"Running command locally: [#{cmd}]\" if debugging?\n    system('bash', '-c', build_command(domain, cmd))\n  end\n  \n  def flush\n    needs(:domain)\n    setting(:domain).each do |domain|\n      next unless domain_of_interest?(domain['name'])\n      puts \"Deploying #{domain['name']}...\"\n      status = remote?(domain['name']) ? run(domain, bundle) : shell(domain, bundle)\n      record_result(domain['name'], status)\n    end\n  end\n  \n  def record_result(domain, status)\n    @results ||= []\n    @results << { 'domain' => domain, 'status' => status }\n  end\n\n  def summarize_results(results)\n    successes = failures = 0\n    results.each do |result|\n      puts \"#{result['domain']} => #{result['status'] ? 'succeeded' : 'failed'}.\"\n      if result['status']\n        successes += 1 \n      else\n        failures += 1\n      end\n    end\n    [successes + failures, successes, failures]\n  end\n  \n  def summarize\n    puts \"\\nResults:\"\n    if results and not results.empty?\n      total, successes, failures = summarize_results(results)\n      puts \"Total: #{total} deployment#{total == 1 ? '' : 's'}, \" +\n        \"#{successes} success#{successes == 1 ? '' : 'es'}, \" +\n        \"#{failures} failure#{failures == 1 ? '' : 's'}.\"\n    else\n      puts \"No deployments to report.\"\n    end       \n  end\n  \n  def success?\n    return true if !results or results.empty?\n    results.all? {|result| result['status'] }\n  end\n  \n  def if_file_present(path, cmd)\n    \"if [ -e #{path} ]; then #{cmd}; fi\"\n  end\n  \n  def if_task_defined(task, cmd)\n    %Q(rakep=`#{env_vars} rake -P` && if [[ `echo \"${rakep}\" | grep #{task}` != \"\" ]]; then #{cmd}; fi )\n  end\n  \n  def safe_branch_checkout(path, my_branch)\n    %Q(cd #{path} && git checkout -b #{my_branch} origin/#{my_branch} || git checkout #{my_branch} origin/#{my_branch} || git checkout #{my_branch})\n  end\n  \n  def clone_repository(repo, path, my_branch)\n    enqueue \"cd #{parent_path(path)}\"\n    enqueue(\"if [ -e #{path} ]; then echo 'Repository already cloned to [#{path}].  Skipping.'; \" +\n            \"else git clone #{repo} #{tail_path(path)} && #{safe_branch_checkout(path, my_branch)}; fi\")\n  end\n \n  def refresh_checkout(path, repo_branch)\n    enqueue \"cd #{path}\"\n    enqueue \"git fetch origin +refs/heads/#{repo_branch}:refs/remotes/origin/#{repo_branch} #{'&>/dev/null' unless debugging?}\"\n    enqueue \"git checkout #{repo_branch} #{'&>/dev/null' unless debugging?}\"\n    enqueue \"git reset --hard origin/#{repo_branch} #{'&>/dev/null' unless debugging?}\"\n  end\n\n  def run_rake_task(path, task_name)\n    enqueue \"echo Running rake #{task_name}...\"\n    enqueue \"cd #{path}\"\n    enqueue(if_file_present(\"#{setting(:deploy_to)}/Rakefile\", \n      if_task_defined(task_name, \"#{env_vars} rake #{'--trace' if debugging?} #{task_name} to=#{setting(:environment)}\")))\n  end\n  \n  def build_path(path)\n    return path if path =~ %r{^/}\n    File.join(setting(:deploy_to), path)\n  end\n\n  def run_script(script)\n    return unless script\n    enqueue(%Q<cd #{setting(:deploy_to)}; echo \"Running post script...\"; #{env_vars} bash #{'-x' if debugging?} #{build_path(script)}>)\n  end\n\n  def ensure_main_parent_path_is_present\n    needs(:deploy_to)\n    enqueue \"mkdir -p #{parent_path(setting(:deploy_to))}\"\n  end\n  \n  def ensure_config_parent_path_is_present\n    needs(:deploy_config_to)\n    enqueue \"mkdir -p #{parent_path(setting(:deploy_config_to))}\"\n  end\n\n  def checkout_main_repository\n    needs(:deploy_to, :repository)\n    clone_repository(setting(:repository), setting(:deploy_to), branch)\n  end\n  \n  def checkout_configuration_repository\n    needs(:deploy_config_to, :config_repository)\n    clone_repository(setting(:config_repository), setting(:deploy_config_to), config_branch)\n  end\n  \n  def snapshot_git_revision\n    needs(:deploy_to)\n    enqueue \"cd #{setting(:deploy_to)}\"\n    enqueue %Q{ml=\\`git log -1 --pretty=format:%H\\`}\n  end\n  \n  def initialize_git_changes\n    needs(:deploy_to)\n    enqueue \"rm -f #{setting(:deploy_to)}/.whiskey_disk_git_changes\"\n    snapshot_git_revision\n  end\n  \n  def initialize_rsync_changes\n    needs(:deploy_to)\n    enqueue \"rm -f #{setting(:deploy_to)}/.whiskey_disk_rsync_changes\"\n  end\n  \n  def initialize_all_changes\n    needs(:deploy_to)\n    initialize_git_changes\n    initialize_rsync_changes\n  end\n  \n  def capture_git_changes\n    needs(:deploy_to)\n    enqueue \"git diff --name-only ${ml}..HEAD > #{setting(:deploy_to)}/.whiskey_disk_git_changes\"\n  end\n  \n  def update_main_repository_checkout\n    needs(:deploy_to)\n    initialize_git_changes\n    refresh_checkout(setting(:deploy_to), branch)\n    capture_git_changes\n  end\n  \n  def update_configuration_repository_checkout\n    needs(:deploy_config_to)\n    initialize_rsync_changes\n    refresh_checkout(setting(:deploy_config_to), config_branch)\n  end\n  \n  def refresh_configuration\n    needs(:deploy_to, :deploy_config_to)\n    raise \"Must specify project name when using a configuration repository.\" unless project_name_specified?\n    enqueue \"echo Rsyncing configuration...\"\n    enqueue(\"rsync -a#{'v --progress' if debugging?} \" + '--log-format=\"%t [%p] %i %n\" ' +\n            \"#{setting(:deploy_config_to)}/#{setting(:project)}/#{setting(:config_target)}/ #{setting(:deploy_to)}/ \" + \n            \"> #{setting(:deploy_to)}/.whiskey_disk_rsync_changes\")\n  end\n  \n  def run_post_setup_hooks\n    needs(:deploy_to)\n    run_script(setting(:post_setup_script))\n    run_rake_task(setting(:deploy_to), \"deploy:post_setup\")\n  end\n  \n  def run_post_deploy_hooks\n    needs(:deploy_to)\n    run_script(setting(:post_deploy_script))\n    run_rake_task(setting(:deploy_to), \"deploy:post_deploy\")\n  end\nend\n"
  },
  {
    "path": "scenarios/git_repositories/config.git/HEAD",
    "content": "ref: refs/heads/master\n"
  },
  {
    "path": "scenarios/git_repositories/config.git/config",
    "content": "[core]\n\trepositoryformatversion = 0\n\tfilemode = true\n\tbare = true\n\tignorecase = true\n"
  },
  {
    "path": "scenarios/git_repositories/config.git/description",
    "content": "Unnamed repository; edit this file 'description' to name the repository.\n"
  },
  {
    "path": "scenarios/git_repositories/config.git/git-daemon-export-ok",
    "content": ""
  },
  {
    "path": "scenarios/git_repositories/config.git/hooks/applypatch-msg.sample",
    "content": "#!/bin/sh\n#\n# An example hook script to check the commit log message taken by\n# applypatch from an e-mail message.\n#\n# The hook should exit with non-zero status after issuing an\n# appropriate message if it wants to stop the commit.  The hook is\n# allowed to edit the commit message file.\n#\n# To enable this hook, rename this file to \"applypatch-msg\".\n\n. git-sh-setup\ntest -x \"$GIT_DIR/hooks/commit-msg\" &&\n\texec \"$GIT_DIR/hooks/commit-msg\" ${1+\"$@\"}\n:\n"
  },
  {
    "path": "scenarios/git_repositories/config.git/hooks/commit-msg.sample",
    "content": "#!/bin/sh\n#\n# An example hook script to check the commit log message.\n# Called by git-commit with one argument, the name of the file\n# that has the commit message.  The hook should exit with non-zero\n# status after issuing an appropriate message if it wants to stop the\n# commit.  The hook is allowed to edit the commit message file.\n#\n# To enable this hook, rename this file to \"commit-msg\".\n\n# Uncomment the below to add a Signed-off-by line to the message.\n# Doing this in a hook is a bad idea in general, but the prepare-commit-msg\n# hook is more suited to it.\n#\n# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\\(.*>\\).*$/Signed-off-by: \\1/p')\n# grep -qs \"^$SOB\" \"$1\" || echo \"$SOB\" >> \"$1\"\n\n# This example catches duplicate Signed-off-by lines.\n\ntest \"\" = \"$(grep '^Signed-off-by: ' \"$1\" |\n\t sort | uniq -c | sed -e '/^[ \t]*1[ \t]/d')\" || {\n\techo >&2 Duplicate Signed-off-by lines.\n\texit 1\n}\n"
  },
  {
    "path": "scenarios/git_repositories/config.git/hooks/post-commit.sample",
    "content": "#!/bin/sh\n#\n# An example hook script that is called after a successful\n# commit is made.\n#\n# To enable this hook, rename this file to \"post-commit\".\n\n: Nothing\n"
  },
  {
    "path": "scenarios/git_repositories/config.git/hooks/post-receive.sample",
    "content": "#!/bin/sh\n#\n# An example hook script for the \"post-receive\" event.\n#\n# The \"post-receive\" script is run after receive-pack has accepted a pack\n# and the repository has been updated.  It is passed arguments in through\n# stdin in the form\n#  <oldrev> <newrev> <refname>\n# For example:\n#  aa453216d1b3e49e7f6f98441fa56946ddcd6a20 68f7abf4e6f922807889f52bc043ecd31b79f814 refs/heads/master\n#\n# see contrib/hooks/ for a sample, or uncomment the next line and\n# rename the file to \"post-receive\".\n\n#. /usr/share/doc/git-core/contrib/hooks/post-receive-email\n"
  },
  {
    "path": "scenarios/git_repositories/config.git/hooks/post-update.sample",
    "content": "#!/bin/sh\n#\n# An example hook script to prepare a packed repository for use over\n# dumb transports.\n#\n# To enable this hook, rename this file to \"post-update\".\n\nexec git-update-server-info\n"
  },
  {
    "path": "scenarios/git_repositories/config.git/hooks/pre-applypatch.sample",
    "content": "#!/bin/sh\n#\n# An example hook script to verify what is about to be committed\n# by applypatch from an e-mail message.\n#\n# The hook should exit with non-zero status after issuing an\n# appropriate message if it wants to stop the commit.\n#\n# To enable this hook, rename this file to \"pre-applypatch\".\n\n. git-sh-setup\ntest -x \"$GIT_DIR/hooks/pre-commit\" &&\n\texec \"$GIT_DIR/hooks/pre-commit\" ${1+\"$@\"}\n:\n"
  },
  {
    "path": "scenarios/git_repositories/config.git/hooks/pre-commit.sample",
    "content": "#!/bin/sh\n#\n# An example hook script to verify what is about to be committed.\n# Called by git-commit with no arguments.  The hook should\n# exit with non-zero status after issuing an appropriate message if\n# it wants to stop the commit.\n#\n# To enable this hook, rename this file to \"pre-commit\".\n\nif git-rev-parse --verify HEAD >/dev/null 2>&1\nthen\n\tagainst=HEAD\nelse\n\t# Initial commit: diff against an empty tree object\n\tagainst=4b825dc642cb6eb9a060e54bf8d69288fbee4904\nfi\n\n# If you want to allow non-ascii filenames set this variable to true.\nallownonascii=$(git config hooks.allownonascii)\n\n# Cross platform projects tend to avoid non-ascii filenames; prevent\n# them from being added to the repository. We exploit the fact that the\n# printable range starts at the space character and ends with tilde.\nif [ \"$allownonascii\" != \"true\" ] &&\n\t# Note that the use of brackets around a tr range is ok here, (it's\n\t# even required, for portability to Solaris 10's /usr/bin/tr), since\n\t# the square bracket bytes happen to fall in the designated range.\n\ttest \"$(git diff --cached --name-only --diff-filter=A -z $against |\n\t  LC_ALL=C tr -d '[ -~]\\0')\"\nthen\n\techo \"Error: Attempt to add a non-ascii file name.\"\n\techo\n\techo \"This can cause problems if you want to work\"\n\techo \"with people on other platforms.\"\n\techo\n\techo \"To be portable it is advisable to rename the file ...\"\n\techo\n\techo \"If you know what you are doing you can disable this\"\n\techo \"check using:\"\n\techo\n\techo \"  git config hooks.allownonascii true\"\n\techo\n\texit 1\nfi\n\nexec git diff-index --check --cached $against --\n"
  },
  {
    "path": "scenarios/git_repositories/config.git/hooks/pre-rebase.sample",
    "content": "#!/bin/sh\n#\n# Copyright (c) 2006, 2008 Junio C Hamano\n#\n# The \"pre-rebase\" hook is run just before \"git-rebase\" starts doing\n# its job, and can prevent the command from running by exiting with\n# non-zero status.\n#\n# The hook is called with the following parameters:\n#\n# $1 -- the upstream the series was forked from.\n# $2 -- the branch being rebased (or empty when rebasing the current branch).\n#\n# This sample shows how to prevent topic branches that are already\n# merged to 'next' branch from getting rebased, because allowing it\n# would result in rebasing already published history.\n\npublish=next\nbasebranch=\"$1\"\nif test \"$#\" = 2\nthen\n\ttopic=\"refs/heads/$2\"\nelse\n\ttopic=`git symbolic-ref HEAD` ||\n\texit 0 ;# we do not interrupt rebasing detached HEAD\nfi\n\ncase \"$topic\" in\nrefs/heads/??/*)\n\t;;\n*)\n\texit 0 ;# we do not interrupt others.\n\t;;\nesac\n\n# Now we are dealing with a topic branch being rebased\n# on top of master.  Is it OK to rebase it?\n\n# Does the topic really exist?\ngit show-ref -q \"$topic\" || {\n\techo >&2 \"No such branch $topic\"\n\texit 1\n}\n\n# Is topic fully merged to master?\nnot_in_master=`git-rev-list --pretty=oneline ^master \"$topic\"`\nif test -z \"$not_in_master\"\nthen\n\techo >&2 \"$topic is fully merged to master; better remove it.\"\n\texit 1 ;# we could allow it, but there is no point.\nfi\n\n# Is topic ever merged to next?  If so you should not be rebasing it.\nonly_next_1=`git-rev-list ^master \"^$topic\" ${publish} | sort`\nonly_next_2=`git-rev-list ^master           ${publish} | sort`\nif test \"$only_next_1\" = \"$only_next_2\"\nthen\n\tnot_in_topic=`git-rev-list \"^$topic\" master`\n\tif test -z \"$not_in_topic\"\n\tthen\n\t\techo >&2 \"$topic is already up-to-date with master\"\n\t\texit 1 ;# we could allow it, but there is no point.\n\telse\n\t\texit 0\n\tfi\nelse\n\tnot_in_next=`git-rev-list --pretty=oneline ^${publish} \"$topic\"`\n\tperl -e '\n\t\tmy $topic = $ARGV[0];\n\t\tmy $msg = \"* $topic has commits already merged to public branch:\\n\";\n\t\tmy (%not_in_next) = map {\n\t\t\t/^([0-9a-f]+) /;\n\t\t\t($1 => 1);\n\t\t} split(/\\n/, $ARGV[1]);\n\t\tfor my $elem (map {\n\t\t\t\t/^([0-9a-f]+) (.*)$/;\n\t\t\t\t[$1 => $2];\n\t\t\t} split(/\\n/, $ARGV[2])) {\n\t\t\tif (!exists $not_in_next{$elem->[0]}) {\n\t\t\t\tif ($msg) {\n\t\t\t\t\tprint STDERR $msg;\n\t\t\t\t\tundef $msg;\n\t\t\t\t}\n\t\t\t\tprint STDERR \" $elem->[1]\\n\";\n\t\t\t}\n\t\t}\n\t' \"$topic\" \"$not_in_next\" \"$not_in_master\"\n\texit 1\nfi\n\nexit 0\n\n################################################################\n\nThis sample hook safeguards topic branches that have been\npublished from being rewound.\n\nThe workflow assumed here is:\n\n * Once a topic branch forks from \"master\", \"master\" is never\n   merged into it again (either directly or indirectly).\n\n * Once a topic branch is fully cooked and merged into \"master\",\n   it is deleted.  If you need to build on top of it to correct\n   earlier mistakes, a new topic branch is created by forking at\n   the tip of the \"master\".  This is not strictly necessary, but\n   it makes it easier to keep your history simple.\n\n * Whenever you need to test or publish your changes to topic\n   branches, merge them into \"next\" branch.\n\nThe script, being an example, hardcodes the publish branch name\nto be \"next\", but it is trivial to make it configurable via\n$GIT_DIR/config mechanism.\n\nWith this workflow, you would want to know:\n\n(1) ... if a topic branch has ever been merged to \"next\".  Young\n    topic branches can have stupid mistakes you would rather\n    clean up before publishing, and things that have not been\n    merged into other branches can be easily rebased without\n    affecting other people.  But once it is published, you would\n    not want to rewind it.\n\n(2) ... if a topic branch has been fully merged to \"master\".\n    Then you can delete it.  More importantly, you should not\n    build on top of it -- other people may already want to\n    change things related to the topic as patches against your\n    \"master\", so if you need further changes, it is better to\n    fork the topic (perhaps with the same name) afresh from the\n    tip of \"master\".\n\nLet's look at this example:\n\n\t\t   o---o---o---o---o---o---o---o---o---o \"next\"\n\t\t  /       /           /           /\n\t\t /   a---a---b A     /           /\n\t\t/   /               /           /\n\t       /   /   c---c---c---c B         /\n\t      /   /   /             \\         /\n\t     /   /   /   b---b C     \\       /\n\t    /   /   /   /             \\     /\n    ---o---o---o---o---o---o---o---o---o---o---o \"master\"\n\n\nA, B and C are topic branches.\n\n * A has one fix since it was merged up to \"next\".\n\n * B has finished.  It has been fully merged up to \"master\" and \"next\",\n   and is ready to be deleted.\n\n * C has not merged to \"next\" at all.\n\nWe would want to allow C to be rebased, refuse A, and encourage\nB to be deleted.\n\nTo compute (1):\n\n\tgit-rev-list ^master ^topic next\n\tgit-rev-list ^master        next\n\n\tif these match, topic has not merged in next at all.\n\nTo compute (2):\n\n\tgit-rev-list master..topic\n\n\tif this is empty, it is fully merged to \"master\".\n"
  },
  {
    "path": "scenarios/git_repositories/config.git/hooks/prepare-commit-msg.sample",
    "content": "#!/bin/sh\n#\n# An example hook script to prepare the commit log message.\n# Called by git-commit with the name of the file that has the\n# commit message, followed by the description of the commit\n# message's source.  The hook's purpose is to edit the commit\n# message file.  If the hook fails with a non-zero status,\n# the commit is aborted.\n#\n# To enable this hook, rename this file to \"prepare-commit-msg\".\n\n# This hook includes three examples.  The first comments out the\n# \"Conflicts:\" part of a merge commit.\n#\n# The second includes the output of \"git diff --name-status -r\"\n# into the message, just before the \"git status\" output.  It is\n# commented because it doesn't cope with --amend or with squashed\n# commits.\n#\n# The third example adds a Signed-off-by line to the message, that can\n# still be edited.  This is rarely a good idea.\n\ncase \"$2,$3\" in\n  merge,)\n    perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' \"$1\" ;;\n\n# ,|template,)\n#   perl -i.bak -pe '\n#      print \"\\n\" . `git diff --cached --name-status -r`\n#\t if /^#/ && $first++ == 0' \"$1\" ;;\n\n  *) ;;\nesac\n\n# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\\(.*>\\).*$/Signed-off-by: \\1/p')\n# grep -qs \"^$SOB\" \"$1\" || echo \"$SOB\" >> \"$1\"\n"
  },
  {
    "path": "scenarios/git_repositories/config.git/hooks/update.sample",
    "content": "#!/bin/sh\n#\n# An example hook script to blocks unannotated tags from entering.\n# Called by git-receive-pack with arguments: refname sha1-old sha1-new\n#\n# To enable this hook, rename this file to \"update\".\n#\n# Config\n# ------\n# hooks.allowunannotated\n#   This boolean sets whether unannotated tags will be allowed into the\n#   repository.  By default they won't be.\n# hooks.allowdeletetag\n#   This boolean sets whether deleting tags will be allowed in the\n#   repository.  By default they won't be.\n# hooks.allowmodifytag\n#   This boolean sets whether a tag may be modified after creation. By default\n#   it won't be.\n# hooks.allowdeletebranch\n#   This boolean sets whether deleting branches will be allowed in the\n#   repository.  By default they won't be.\n# hooks.denycreatebranch\n#   This boolean sets whether remotely creating branches will be denied\n#   in the repository.  By default this is allowed.\n#\n\n# --- Command line\nrefname=\"$1\"\noldrev=\"$2\"\nnewrev=\"$3\"\n\n# --- Safety check\nif [ -z \"$GIT_DIR\" ]; then\n\techo \"Don't run this script from the command line.\" >&2\n\techo \" (if you want, you could supply GIT_DIR then run\" >&2\n\techo \"  $0 <ref> <oldrev> <newrev>)\" >&2\n\texit 1\nfi\n\nif [ -z \"$refname\" -o -z \"$oldrev\" -o -z \"$newrev\" ]; then\n\techo \"Usage: $0 <ref> <oldrev> <newrev>\" >&2\n\texit 1\nfi\n\n# --- Config\nallowunannotated=$(git config --bool hooks.allowunannotated)\nallowdeletebranch=$(git config --bool hooks.allowdeletebranch)\ndenycreatebranch=$(git config --bool hooks.denycreatebranch)\nallowdeletetag=$(git config --bool hooks.allowdeletetag)\nallowmodifytag=$(git config --bool hooks.allowmodifytag)\n\n# check for no description\nprojectdesc=$(sed -e '1q' \"$GIT_DIR/description\")\ncase \"$projectdesc\" in\n\"Unnamed repository\"* | \"\")\n\techo \"*** Project description file hasn't been set\" >&2\n\texit 1\n\t;;\nesac\n\n# --- Check types\n# if $newrev is 0000...0000, it's a commit to delete a ref.\nzero=\"0000000000000000000000000000000000000000\"\nif [ \"$newrev\" = \"$zero\" ]; then\n\tnewrev_type=delete\nelse\n\tnewrev_type=$(git-cat-file -t $newrev)\nfi\n\ncase \"$refname\",\"$newrev_type\" in\n\trefs/tags/*,commit)\n\t\t# un-annotated tag\n\t\tshort_refname=${refname##refs/tags/}\n\t\tif [ \"$allowunannotated\" != \"true\" ]; then\n\t\t\techo \"*** The un-annotated tag, $short_refname, is not allowed in this repository\" >&2\n\t\t\techo \"*** Use 'git tag [ -a | -s ]' for tags you want to propagate.\" >&2\n\t\t\texit 1\n\t\tfi\n\t\t;;\n\trefs/tags/*,delete)\n\t\t# delete tag\n\t\tif [ \"$allowdeletetag\" != \"true\" ]; then\n\t\t\techo \"*** Deleting a tag is not allowed in this repository\" >&2\n\t\t\texit 1\n\t\tfi\n\t\t;;\n\trefs/tags/*,tag)\n\t\t# annotated tag\n\t\tif [ \"$allowmodifytag\" != \"true\" ] && git rev-parse $refname > /dev/null 2>&1\n\t\tthen\n\t\t\techo \"*** Tag '$refname' already exists.\" >&2\n\t\t\techo \"*** Modifying a tag is not allowed in this repository.\" >&2\n\t\t\texit 1\n\t\tfi\n\t\t;;\n\trefs/heads/*,commit)\n\t\t# branch\n\t\tif [ \"$oldrev\" = \"$zero\" -a \"$denycreatebranch\" = \"true\" ]; then\n\t\t\techo \"*** Creating a branch is not allowed in this repository\" >&2\n\t\t\texit 1\n\t\tfi\n\t\t;;\n\trefs/heads/*,delete)\n\t\t# delete branch\n\t\tif [ \"$allowdeletebranch\" != \"true\" ]; then\n\t\t\techo \"*** Deleting a branch is not allowed in this repository\" >&2\n\t\t\texit 1\n\t\tfi\n\t\t;;\n\trefs/remotes/*,commit)\n\t\t# tracking branch\n\t\t;;\n\trefs/remotes/*,delete)\n\t\t# delete tracking branch\n\t\tif [ \"$allowdeletebranch\" != \"true\" ]; then\n\t\t\techo \"*** Deleting a tracking branch is not allowed in this repository\" >&2\n\t\t\texit 1\n\t\tfi\n\t\t;;\n\t*)\n\t\t# Anything else (is there anything else?)\n\t\techo \"*** Update hook: unknown type of update to ref $refname of type $newrev_type\" >&2\n\t\texit 1\n\t\t;;\nesac\n\n# --- Finished\nexit 0\n"
  },
  {
    "path": "scenarios/git_repositories/config.git/info/exclude",
    "content": "# git-ls-files --others --exclude-from=.git/info/exclude\n# Lines that start with '#' are comments.\n# For a project mostly in C, the following would be a good set of\n# exclude patterns (uncomment them if you want to use them):\n# *.[oa]\n# *~\n"
  },
  {
    "path": "scenarios/git_repositories/config.git/objects/0e/e781f5ce80d64db32a74a7aae7b5248dafe112",
    "content": "x\u0001[\n0\u0014D*\u0006<n\u0004D%<n&%\u001fݽ\u0011w\f́\u0019&e\u001aH-\u000e\u0012A4x\u0017)\u000eA\u0005h5\u001d49\u0007dd\u001b\u0018\u0014c\u0014\u0014\u00027RKAKw,9`ݞ}\n/U\u0017g\\{~)\u0002Bq٥\u00105~џuikP=\u0007\bO\u001f\u0014!M3ZJu\u0007Q\u0001"
  },
  {
    "path": "scenarios/git_repositories/config.git/objects/71/eb5df52676e8e6efba471050b46978173af110",
    "content": "x\u0001\t\u00021\u0010DN\u0015ۀ\u001c%An`r\u0010?u<x3RK\u001d\u0018\u0001'$&I8\u0005\f(m\u0010ͳ\u0010\u0012y\u000eɜutʿ6xdy\u000f\\h_,;9I-W@3[äQ;ՠ?uܳ_aQ_&<"
  },
  {
    "path": "scenarios/git_repositories/config.git/objects/84/17d2fe3e8fcc0825249c517b29b0f9ea8b8b31",
    "content": "x\u0001QJ0\u0010})\u0002J6I\u0004D#xoM$Ez{#\u0019c\u0006q\u0013l\u000fgW5\u0019藅\u0016CrL9Q9z(^]a\u001c}dH~E\t}@u~l\b%vfA#\u0013}[^\u0003:ɮ\u0017<^%'n\u000b3\u0016m\n\u0001Ls>H7 Xˮ\u0015ހB\u0005Y[\u0017Ѯ\u0002Q\r\u0017Uy\u0001F+Y"
  },
  {
    "path": "scenarios/git_repositories/config.git/refs/heads/master",
    "content": "bb59da633ba74296b0c2f9ff70784ac155ddb599\n"
  },
  {
    "path": "scenarios/git_repositories/project.git/HEAD",
    "content": "ref: refs/heads/master\n"
  },
  {
    "path": "scenarios/git_repositories/project.git/config",
    "content": "[core]\n\trepositoryformatversion = 0\n\tfilemode = true\n\tbare = true\n\tignorecase = true\n"
  },
  {
    "path": "scenarios/git_repositories/project.git/description",
    "content": "Unnamed repository; edit this file 'description' to name the repository.\n"
  },
  {
    "path": "scenarios/git_repositories/project.git/git-daemon-export-ok",
    "content": ""
  },
  {
    "path": "scenarios/git_repositories/project.git/hooks/applypatch-msg.sample",
    "content": "#!/bin/sh\n#\n# An example hook script to check the commit log message taken by\n# applypatch from an e-mail message.\n#\n# The hook should exit with non-zero status after issuing an\n# appropriate message if it wants to stop the commit.  The hook is\n# allowed to edit the commit message file.\n#\n# To enable this hook, rename this file to \"applypatch-msg\".\n\n. git-sh-setup\ntest -x \"$GIT_DIR/hooks/commit-msg\" &&\n\texec \"$GIT_DIR/hooks/commit-msg\" ${1+\"$@\"}\n:\n"
  },
  {
    "path": "scenarios/git_repositories/project.git/hooks/commit-msg.sample",
    "content": "#!/bin/sh\n#\n# An example hook script to check the commit log message.\n# Called by git-commit with one argument, the name of the file\n# that has the commit message.  The hook should exit with non-zero\n# status after issuing an appropriate message if it wants to stop the\n# commit.  The hook is allowed to edit the commit message file.\n#\n# To enable this hook, rename this file to \"commit-msg\".\n\n# Uncomment the below to add a Signed-off-by line to the message.\n# Doing this in a hook is a bad idea in general, but the prepare-commit-msg\n# hook is more suited to it.\n#\n# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\\(.*>\\).*$/Signed-off-by: \\1/p')\n# grep -qs \"^$SOB\" \"$1\" || echo \"$SOB\" >> \"$1\"\n\n# This example catches duplicate Signed-off-by lines.\n\ntest \"\" = \"$(grep '^Signed-off-by: ' \"$1\" |\n\t sort | uniq -c | sed -e '/^[ \t]*1[ \t]/d')\" || {\n\techo >&2 Duplicate Signed-off-by lines.\n\texit 1\n}\n"
  },
  {
    "path": "scenarios/git_repositories/project.git/hooks/post-commit.sample",
    "content": "#!/bin/sh\n#\n# An example hook script that is called after a successful\n# commit is made.\n#\n# To enable this hook, rename this file to \"post-commit\".\n\n: Nothing\n"
  },
  {
    "path": "scenarios/git_repositories/project.git/hooks/post-receive.sample",
    "content": "#!/bin/sh\n#\n# An example hook script for the \"post-receive\" event.\n#\n# The \"post-receive\" script is run after receive-pack has accepted a pack\n# and the repository has been updated.  It is passed arguments in through\n# stdin in the form\n#  <oldrev> <newrev> <refname>\n# For example:\n#  aa453216d1b3e49e7f6f98441fa56946ddcd6a20 68f7abf4e6f922807889f52bc043ecd31b79f814 refs/heads/master\n#\n# see contrib/hooks/ for a sample, or uncomment the next line and\n# rename the file to \"post-receive\".\n\n#. /usr/share/doc/git-core/contrib/hooks/post-receive-email\n"
  },
  {
    "path": "scenarios/git_repositories/project.git/hooks/post-update.sample",
    "content": "#!/bin/sh\n#\n# An example hook script to prepare a packed repository for use over\n# dumb transports.\n#\n# To enable this hook, rename this file to \"post-update\".\n\nexec git-update-server-info\n"
  },
  {
    "path": "scenarios/git_repositories/project.git/hooks/pre-applypatch.sample",
    "content": "#!/bin/sh\n#\n# An example hook script to verify what is about to be committed\n# by applypatch from an e-mail message.\n#\n# The hook should exit with non-zero status after issuing an\n# appropriate message if it wants to stop the commit.\n#\n# To enable this hook, rename this file to \"pre-applypatch\".\n\n. git-sh-setup\ntest -x \"$GIT_DIR/hooks/pre-commit\" &&\n\texec \"$GIT_DIR/hooks/pre-commit\" ${1+\"$@\"}\n:\n"
  },
  {
    "path": "scenarios/git_repositories/project.git/hooks/pre-commit.sample",
    "content": "#!/bin/sh\n#\n# An example hook script to verify what is about to be committed.\n# Called by git-commit with no arguments.  The hook should\n# exit with non-zero status after issuing an appropriate message if\n# it wants to stop the commit.\n#\n# To enable this hook, rename this file to \"pre-commit\".\n\nif git-rev-parse --verify HEAD >/dev/null 2>&1\nthen\n\tagainst=HEAD\nelse\n\t# Initial commit: diff against an empty tree object\n\tagainst=4b825dc642cb6eb9a060e54bf8d69288fbee4904\nfi\n\n# If you want to allow non-ascii filenames set this variable to true.\nallownonascii=$(git config hooks.allownonascii)\n\n# Cross platform projects tend to avoid non-ascii filenames; prevent\n# them from being added to the repository. We exploit the fact that the\n# printable range starts at the space character and ends with tilde.\nif [ \"$allownonascii\" != \"true\" ] &&\n\t# Note that the use of brackets around a tr range is ok here, (it's\n\t# even required, for portability to Solaris 10's /usr/bin/tr), since\n\t# the square bracket bytes happen to fall in the designated range.\n\ttest \"$(git diff --cached --name-only --diff-filter=A -z $against |\n\t  LC_ALL=C tr -d '[ -~]\\0')\"\nthen\n\techo \"Error: Attempt to add a non-ascii file name.\"\n\techo\n\techo \"This can cause problems if you want to work\"\n\techo \"with people on other platforms.\"\n\techo\n\techo \"To be portable it is advisable to rename the file ...\"\n\techo\n\techo \"If you know what you are doing you can disable this\"\n\techo \"check using:\"\n\techo\n\techo \"  git config hooks.allownonascii true\"\n\techo\n\texit 1\nfi\n\nexec git diff-index --check --cached $against --\n"
  },
  {
    "path": "scenarios/git_repositories/project.git/hooks/pre-rebase.sample",
    "content": "#!/bin/sh\n#\n# Copyright (c) 2006, 2008 Junio C Hamano\n#\n# The \"pre-rebase\" hook is run just before \"git-rebase\" starts doing\n# its job, and can prevent the command from running by exiting with\n# non-zero status.\n#\n# The hook is called with the following parameters:\n#\n# $1 -- the upstream the series was forked from.\n# $2 -- the branch being rebased (or empty when rebasing the current branch).\n#\n# This sample shows how to prevent topic branches that are already\n# merged to 'next' branch from getting rebased, because allowing it\n# would result in rebasing already published history.\n\npublish=next\nbasebranch=\"$1\"\nif test \"$#\" = 2\nthen\n\ttopic=\"refs/heads/$2\"\nelse\n\ttopic=`git symbolic-ref HEAD` ||\n\texit 0 ;# we do not interrupt rebasing detached HEAD\nfi\n\ncase \"$topic\" in\nrefs/heads/??/*)\n\t;;\n*)\n\texit 0 ;# we do not interrupt others.\n\t;;\nesac\n\n# Now we are dealing with a topic branch being rebased\n# on top of master.  Is it OK to rebase it?\n\n# Does the topic really exist?\ngit show-ref -q \"$topic\" || {\n\techo >&2 \"No such branch $topic\"\n\texit 1\n}\n\n# Is topic fully merged to master?\nnot_in_master=`git-rev-list --pretty=oneline ^master \"$topic\"`\nif test -z \"$not_in_master\"\nthen\n\techo >&2 \"$topic is fully merged to master; better remove it.\"\n\texit 1 ;# we could allow it, but there is no point.\nfi\n\n# Is topic ever merged to next?  If so you should not be rebasing it.\nonly_next_1=`git-rev-list ^master \"^$topic\" ${publish} | sort`\nonly_next_2=`git-rev-list ^master           ${publish} | sort`\nif test \"$only_next_1\" = \"$only_next_2\"\nthen\n\tnot_in_topic=`git-rev-list \"^$topic\" master`\n\tif test -z \"$not_in_topic\"\n\tthen\n\t\techo >&2 \"$topic is already up-to-date with master\"\n\t\texit 1 ;# we could allow it, but there is no point.\n\telse\n\t\texit 0\n\tfi\nelse\n\tnot_in_next=`git-rev-list --pretty=oneline ^${publish} \"$topic\"`\n\tperl -e '\n\t\tmy $topic = $ARGV[0];\n\t\tmy $msg = \"* $topic has commits already merged to public branch:\\n\";\n\t\tmy (%not_in_next) = map {\n\t\t\t/^([0-9a-f]+) /;\n\t\t\t($1 => 1);\n\t\t} split(/\\n/, $ARGV[1]);\n\t\tfor my $elem (map {\n\t\t\t\t/^([0-9a-f]+) (.*)$/;\n\t\t\t\t[$1 => $2];\n\t\t\t} split(/\\n/, $ARGV[2])) {\n\t\t\tif (!exists $not_in_next{$elem->[0]}) {\n\t\t\t\tif ($msg) {\n\t\t\t\t\tprint STDERR $msg;\n\t\t\t\t\tundef $msg;\n\t\t\t\t}\n\t\t\t\tprint STDERR \" $elem->[1]\\n\";\n\t\t\t}\n\t\t}\n\t' \"$topic\" \"$not_in_next\" \"$not_in_master\"\n\texit 1\nfi\n\nexit 0\n\n################################################################\n\nThis sample hook safeguards topic branches that have been\npublished from being rewound.\n\nThe workflow assumed here is:\n\n * Once a topic branch forks from \"master\", \"master\" is never\n   merged into it again (either directly or indirectly).\n\n * Once a topic branch is fully cooked and merged into \"master\",\n   it is deleted.  If you need to build on top of it to correct\n   earlier mistakes, a new topic branch is created by forking at\n   the tip of the \"master\".  This is not strictly necessary, but\n   it makes it easier to keep your history simple.\n\n * Whenever you need to test or publish your changes to topic\n   branches, merge them into \"next\" branch.\n\nThe script, being an example, hardcodes the publish branch name\nto be \"next\", but it is trivial to make it configurable via\n$GIT_DIR/config mechanism.\n\nWith this workflow, you would want to know:\n\n(1) ... if a topic branch has ever been merged to \"next\".  Young\n    topic branches can have stupid mistakes you would rather\n    clean up before publishing, and things that have not been\n    merged into other branches can be easily rebased without\n    affecting other people.  But once it is published, you would\n    not want to rewind it.\n\n(2) ... if a topic branch has been fully merged to \"master\".\n    Then you can delete it.  More importantly, you should not\n    build on top of it -- other people may already want to\n    change things related to the topic as patches against your\n    \"master\", so if you need further changes, it is better to\n    fork the topic (perhaps with the same name) afresh from the\n    tip of \"master\".\n\nLet's look at this example:\n\n\t\t   o---o---o---o---o---o---o---o---o---o \"next\"\n\t\t  /       /           /           /\n\t\t /   a---a---b A     /           /\n\t\t/   /               /           /\n\t       /   /   c---c---c---c B         /\n\t      /   /   /             \\         /\n\t     /   /   /   b---b C     \\       /\n\t    /   /   /   /             \\     /\n    ---o---o---o---o---o---o---o---o---o---o---o \"master\"\n\n\nA, B and C are topic branches.\n\n * A has one fix since it was merged up to \"next\".\n\n * B has finished.  It has been fully merged up to \"master\" and \"next\",\n   and is ready to be deleted.\n\n * C has not merged to \"next\" at all.\n\nWe would want to allow C to be rebased, refuse A, and encourage\nB to be deleted.\n\nTo compute (1):\n\n\tgit-rev-list ^master ^topic next\n\tgit-rev-list ^master        next\n\n\tif these match, topic has not merged in next at all.\n\nTo compute (2):\n\n\tgit-rev-list master..topic\n\n\tif this is empty, it is fully merged to \"master\".\n"
  },
  {
    "path": "scenarios/git_repositories/project.git/hooks/prepare-commit-msg.sample",
    "content": "#!/bin/sh\n#\n# An example hook script to prepare the commit log message.\n# Called by git-commit with the name of the file that has the\n# commit message, followed by the description of the commit\n# message's source.  The hook's purpose is to edit the commit\n# message file.  If the hook fails with a non-zero status,\n# the commit is aborted.\n#\n# To enable this hook, rename this file to \"prepare-commit-msg\".\n\n# This hook includes three examples.  The first comments out the\n# \"Conflicts:\" part of a merge commit.\n#\n# The second includes the output of \"git diff --name-status -r\"\n# into the message, just before the \"git status\" output.  It is\n# commented because it doesn't cope with --amend or with squashed\n# commits.\n#\n# The third example adds a Signed-off-by line to the message, that can\n# still be edited.  This is rarely a good idea.\n\ncase \"$2,$3\" in\n  merge,)\n    perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' \"$1\" ;;\n\n# ,|template,)\n#   perl -i.bak -pe '\n#      print \"\\n\" . `git diff --cached --name-status -r`\n#\t if /^#/ && $first++ == 0' \"$1\" ;;\n\n  *) ;;\nesac\n\n# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\\(.*>\\).*$/Signed-off-by: \\1/p')\n# grep -qs \"^$SOB\" \"$1\" || echo \"$SOB\" >> \"$1\"\n"
  },
  {
    "path": "scenarios/git_repositories/project.git/hooks/update.sample",
    "content": "#!/bin/sh\n#\n# An example hook script to blocks unannotated tags from entering.\n# Called by git-receive-pack with arguments: refname sha1-old sha1-new\n#\n# To enable this hook, rename this file to \"update\".\n#\n# Config\n# ------\n# hooks.allowunannotated\n#   This boolean sets whether unannotated tags will be allowed into the\n#   repository.  By default they won't be.\n# hooks.allowdeletetag\n#   This boolean sets whether deleting tags will be allowed in the\n#   repository.  By default they won't be.\n# hooks.allowmodifytag\n#   This boolean sets whether a tag may be modified after creation. By default\n#   it won't be.\n# hooks.allowdeletebranch\n#   This boolean sets whether deleting branches will be allowed in the\n#   repository.  By default they won't be.\n# hooks.denycreatebranch\n#   This boolean sets whether remotely creating branches will be denied\n#   in the repository.  By default this is allowed.\n#\n\n# --- Command line\nrefname=\"$1\"\noldrev=\"$2\"\nnewrev=\"$3\"\n\n# --- Safety check\nif [ -z \"$GIT_DIR\" ]; then\n\techo \"Don't run this script from the command line.\" >&2\n\techo \" (if you want, you could supply GIT_DIR then run\" >&2\n\techo \"  $0 <ref> <oldrev> <newrev>)\" >&2\n\texit 1\nfi\n\nif [ -z \"$refname\" -o -z \"$oldrev\" -o -z \"$newrev\" ]; then\n\techo \"Usage: $0 <ref> <oldrev> <newrev>\" >&2\n\texit 1\nfi\n\n# --- Config\nallowunannotated=$(git config --bool hooks.allowunannotated)\nallowdeletebranch=$(git config --bool hooks.allowdeletebranch)\ndenycreatebranch=$(git config --bool hooks.denycreatebranch)\nallowdeletetag=$(git config --bool hooks.allowdeletetag)\nallowmodifytag=$(git config --bool hooks.allowmodifytag)\n\n# check for no description\nprojectdesc=$(sed -e '1q' \"$GIT_DIR/description\")\ncase \"$projectdesc\" in\n\"Unnamed repository\"* | \"\")\n\techo \"*** Project description file hasn't been set\" >&2\n\texit 1\n\t;;\nesac\n\n# --- Check types\n# if $newrev is 0000...0000, it's a commit to delete a ref.\nzero=\"0000000000000000000000000000000000000000\"\nif [ \"$newrev\" = \"$zero\" ]; then\n\tnewrev_type=delete\nelse\n\tnewrev_type=$(git-cat-file -t $newrev)\nfi\n\ncase \"$refname\",\"$newrev_type\" in\n\trefs/tags/*,commit)\n\t\t# un-annotated tag\n\t\tshort_refname=${refname##refs/tags/}\n\t\tif [ \"$allowunannotated\" != \"true\" ]; then\n\t\t\techo \"*** The un-annotated tag, $short_refname, is not allowed in this repository\" >&2\n\t\t\techo \"*** Use 'git tag [ -a | -s ]' for tags you want to propagate.\" >&2\n\t\t\texit 1\n\t\tfi\n\t\t;;\n\trefs/tags/*,delete)\n\t\t# delete tag\n\t\tif [ \"$allowdeletetag\" != \"true\" ]; then\n\t\t\techo \"*** Deleting a tag is not allowed in this repository\" >&2\n\t\t\texit 1\n\t\tfi\n\t\t;;\n\trefs/tags/*,tag)\n\t\t# annotated tag\n\t\tif [ \"$allowmodifytag\" != \"true\" ] && git rev-parse $refname > /dev/null 2>&1\n\t\tthen\n\t\t\techo \"*** Tag '$refname' already exists.\" >&2\n\t\t\techo \"*** Modifying a tag is not allowed in this repository.\" >&2\n\t\t\texit 1\n\t\tfi\n\t\t;;\n\trefs/heads/*,commit)\n\t\t# branch\n\t\tif [ \"$oldrev\" = \"$zero\" -a \"$denycreatebranch\" = \"true\" ]; then\n\t\t\techo \"*** Creating a branch is not allowed in this repository\" >&2\n\t\t\texit 1\n\t\tfi\n\t\t;;\n\trefs/heads/*,delete)\n\t\t# delete branch\n\t\tif [ \"$allowdeletebranch\" != \"true\" ]; then\n\t\t\techo \"*** Deleting a branch is not allowed in this repository\" >&2\n\t\t\texit 1\n\t\tfi\n\t\t;;\n\trefs/remotes/*,commit)\n\t\t# tracking branch\n\t\t;;\n\trefs/remotes/*,delete)\n\t\t# delete tracking branch\n\t\tif [ \"$allowdeletebranch\" != \"true\" ]; then\n\t\t\techo \"*** Deleting a tracking branch is not allowed in this repository\" >&2\n\t\t\texit 1\n\t\tfi\n\t\t;;\n\t*)\n\t\t# Anything else (is there anything else?)\n\t\techo \"*** Update hook: unknown type of update to ref $refname of type $newrev_type\" >&2\n\t\texit 1\n\t\t;;\nesac\n\n# --- Finished\nexit 0\n"
  },
  {
    "path": "scenarios/git_repositories/project.git/info/exclude",
    "content": "# git-ls-files --others --exclude-from=.git/info/exclude\n# Lines that start with '#' are comments.\n# For a project mostly in C, the following would be a good set of\n# exclude patterns (uncomment them if you want to use them):\n# *.[oa]\n# *~\n"
  },
  {
    "path": "scenarios/git_repositories/project.git/objects/04/f4de85eaf72ef1631dc6d7424045c0a749b757",
    "content": "x\u0001IjC1\u0010D)z\u001dH<@\b!G\u0005#:>27Uԃ\u00075\u0002\u000b\rD@R\u0010aH\"pQ\u000båA1y\u0015uPEɐ\u001c;\"lBm+hRHFT<\u001b\u0015Y>\u0015G,7=҃}2\u000b\u0003or\u0016]'\tY,\u0017}IWy&u턗\u0011\u001dy?*W"
  },
  {
    "path": "scenarios/git_repositories/project.git/objects/20/1c7641c2e42b0b904e5c1f793489d8b858e4da",
    "content": "x\u0001\t\u00021\u0010DN\u0015ۀ%q\u0017D\u0012 ar\u0010?u<x3;hrD@\u0016\u0013mrh68sZğ\u0003\u0007\bD\u00137»?kG/VvżS\nڰ7nbpDBT.*o¾\u001c<t"
  },
  {
    "path": "scenarios/git_repositories/project.git/objects/27/a3fff2c4c45ab5513a405f694c0a042cb5d417",
    "content": "x\u0001NAj\u00031\u0010ٯsevg!'\u0003ab\u001bl:\u000eA/B\u0012\u0012R\\4 GoB\u001eq +C΄ѻ)\u000eN,\u000b[\"c`R`\u0011J8Z\t9'#s#s`.kc3\u001cv\u0011\u0013\u0006oYdxGhO6gHJ\rG5³\u000b׭vd7\u000bP"
  },
  {
    "path": "scenarios/git_repositories/project.git/objects/2c/0c33cfba8e1af15df88522c0db2b10a6a94138",
    "content": "x\u0001Kj\u00031\u0010D)\u0002\tR3#\bI\u0011|\u0001jC2\u001f\"\u0018zmYf\u0005LM\u0004\u0002ŁJ\u0012$`≳x\u0010G\\(HdUȑsTsq\u0004\u001em.\rw6N\u000fU\u0014C7n\rN3w+ގu o-\u001f0gLC\n\u001e^m\u001c8nmW:\u0017ط\u0007+\u0017wn\u0001(V}"
  },
  {
    "path": "scenarios/git_repositories/project.git/objects/5b/a96acf9cc9b87babe37c032676f53bf1ba9ae7",
    "content": "x\u0001aj \u0010\u000bQ\u0017Rz@\t\u001bb\f4ޠx<t g/@\u000eWmf&Dɧ3\u001bN\u00188ɜOlu&82m`\u001fl(&\u0004&+z\u000fj1\u00179F|Zzw\u0007h'D\rU'~n\f[v\u0019y)\u0002\u001e%\u000f86p?b)'w\u0007'\nU6"
  },
  {
    "path": "scenarios/git_repositories/project.git/objects/86/d1ef0976be4567de562224e1b51fbf9820c53a",
    "content": "x\u0001AJ\u00041\u0010E]\u0014\u001ePJ:\u0001\u0011\b^@J\u00184Ifx\u00037\u001f\u0007뾗\u0001a4\u00110Iт.bF7B\fiN4[u&\u0014Ցa\u0014¤S$Ͷ|>yrT>>k7xk17<^''\u000b\u0018\f\u001e\u001avZIg*\\+\u000btn\u001c\u001dS!\u0016G\u0007S\u001f\\T"
  },
  {
    "path": "scenarios/git_repositories/project.git/objects/95/c9d5ad9b1c90e4c805516783105fc2037dedeb",
    "content": "x\u0001Kn \f\u0014U\u001a# TUUw\rx8\tj\brB\u0006`\u0007;ۭ}\b\u0013̈́6VˡP NڪiBh٦\u0012\u0006\u0002cSQ;-\u0011pHa\rAP4gj%&v\u0007+\u001eJY\u000fT&\u000f\u0010r\u001cV#7qΊZL\u0012Q:\\\"H\u00154(c0gW\u0018\u0016>\u00122X\\\u0011C$T>S-\u001a7_?a*2\u001d',*hq\u0019:\\PA\u001a|D[x֣l\u001d\fR\u0004\u0005\nM\u0017\bŐ\u000f|&z"
  },
  {
    "path": "scenarios/git_repositories/project.git/objects/95/d82d043af35a80eabfd56c0d705abfa3488787",
    "content": "x\u0001Qn\u00021\fDS\u0002Evd\u0013\tU\u0015G\u0006I@.B7\u001b3yғ&oZ;XG\u001f\u001c\u0014$:\u0014+\u0013iy)ZJ=6\r\u0011)ώ)[e0\u0005dg*s\u0007ｲD\u0013ekp\n\u0016e?8^d\u000b\u0006<3|C4]M\u00143D(.vW-uQ(R\u0007RR"
  },
  {
    "path": "scenarios/git_repositories/project.git/objects/a3/860106dc1d148c7831cd45ae38829b4ed47702",
    "content": "x\u0001]\n0\u0010})\u00026ɚ\u0004D#xlh\u0012\"ۛ\r|\u0019o`bTk\u0019t4CJ\u0012񙍳V[4\u0012#m$):sјH\u0006>\u0004T\u0006-e<0HI\u000e¿ۣT\tӋW8.[\u001f92aP(\u000eH~g֥/!H"
  },
  {
    "path": "scenarios/git_repositories/project.git/objects/ae/3900de54aff557c61c81146d00f9d38e55a265",
    "content": "x\u0001Aj\u0004!\u0010E\u0014\u001eH(R[\u0018B\u0011\u0002\u001e\u0007I!7{৶u4zJ\"\u0018d\r\u0015\\bAˎ|rs&=_\u000bRLV\u0016\u00178 \u0014+yuԴ{yp\u0007N3/Mq>hxF\u000e{\u001cp5eck[\u0013,w\u0003P"
  },
  {
    "path": "scenarios/git_repositories/project.git/objects/bf/5e3740d52b80abb0378b3f85f93a53b1294521",
    "content": "x\u0001Qj0\u0010\u0005S\u0005\u0012vX #\u0006*\u0011\"\u0005߾*A~\u001ee\u0006vB&ls\u001e}\b\u0003a8{\"B.Oαc\u00115t8'%qPBC.=]d\u0013!{grv_\u001a|Uyq~\u000e˜d>\u001cZ1\u0004G\u001c\u0010Mos\rX\u001b>37]2u\u0001'S9"
  },
  {
    "path": "scenarios/git_repositories/project.git/objects/cc/5ac0afb24e727d5de344cc26a425f4fb7fd17d",
    "content": "x\u0001A\n0\u0014D]\u0014C\u000fB\u0017BAWzNJIG6?𓅷$\bY7o\u0018yf])g&\u0012on֒\u001f\r\n\bF^hBDt\u0012\u0001 htt.e\u0006%y\u0017CΪVfS~?Zvwΰҭl:l?k]"
  },
  {
    "path": "scenarios/git_repositories/project.git/objects/db/d1b9667f1b26b13331ac0c321dced8be1aeab0",
    "content": "x\u0001Kj0\u0010\u0005)\u0002\t-Y\u001f\u000b$\b@hZc3cbn\u001f \u0007nԛ\b\u0014T&RpL`0\u000b\u001cOgtT\u00075ه\u0018h*\u0018l\u001d%D\u0016]2\u0012Ze\u0006+Q\u0003.mI\nyv:Zgj\u0011基\nG=W^\u001fz;Wrv7dTf\u0003ݺV"
  },
  {
    "path": "scenarios/git_repositories/project.git/refs/heads/bad_rakefile",
    "content": "95d82d043af35a80eabfd56c0d705abfa3488787\n"
  },
  {
    "path": "scenarios/git_repositories/project.git/refs/heads/hook_with_changed",
    "content": "5ba96acf9cc9b87babe37c032676f53bf1ba9ae7\n"
  },
  {
    "path": "scenarios/git_repositories/project.git/refs/heads/master",
    "content": "04f4de85eaf72ef1631dc6d7424045c0a749b757\n"
  },
  {
    "path": "scenarios/git_repositories/project.git/refs/heads/no_rake_hooks",
    "content": "ae3900de54aff557c61c81146d00f9d38e55a265\n"
  },
  {
    "path": "scenarios/git_repositories/project.git/refs/heads/post_rake_tasks",
    "content": "27a3fff2c4c45ab5513a405f694c0a042cb5d417\n"
  },
  {
    "path": "scenarios/invalid/deploy.yml",
    "content": "}\n"
  },
  {
    "path": "scenarios/local/deploy.yml.erb",
    "content": "<% root = File.expand_path(File.join(File.dirname(__FILE__), 'scenarios', 'setup', 'vagrant', 'deployed', 'target')) %>\nproject:\n  \"local-default\":\n    deploy_to: \"<%= root %>/project\"\n    repository: \"git://localhost/project.git\"\n  \"local-keyword\":\n    domain: \"local\"\n    deploy_to: \"<%= root %>/project\"\n    repository: \"git://localhost/project.git\"\n  \"local-user-domain\":\n    domain: \"user@localhost\"\n    deploy_to: \"<%= root %>/project\"\n    repository: \"git://localhost/project.git\"\n  \"local-domain\":\n    domain: \"localhost\"\n    deploy_to: \"<%= root %>/project\"\n    repository: \"git://localhost/project.git\"\n"
  },
  {
    "path": "scenarios/remote/deploy.yml",
    "content": "project:\n  \"remote\":\n    domain:\n    - name: \"vagrant@vagrant\"\n      ssh_options:\n      - \"-F\"\n      - \"scenarios/setup/vagrant/ssh_config\"\n    deploy_to: \"/opt/deploy/target/project\"\n    repository: \"git://wd-git.example.com/project.git\"\n  \"remote-on-other-branch\":\n    domain:\n    - name: \"vagrant@vagrant\"\n      ssh_options:\n      - \"-F\"\n      - \"scenarios/setup/vagrant/ssh_config\"\n    deploy_to: \"/opt/deploy/target/project\"\n    repository: \"git://wd-git.example.com/project.git\"\n    branch: \"no_rake_hooks\"\n  \"no_rakefile\":\n    domain:\n    - name: \"vagrant@vagrant\"\n      ssh_options:\n      - \"-F\"\n      - \"scenarios/setup/vagrant/ssh_config\"\n    deploy_to: \"/opt/deploy/target/project\"\n    repository: \"git://wd-git.example.com/project.git\"\n  \"bad_rakefile\":\n    domain:\n    - name: \"vagrant@vagrant\"\n      ssh_options:\n      - \"-F\"\n      - \"scenarios/setup/vagrant/ssh_config\"\n    deploy_to: \"/opt/deploy/target/project\"\n    repository: \"git://wd-git.example.com/project.git\"\n    branch: \"bad_rakefile\"\n  \"no_rake_hooks\":\n    domain:\n    - name: \"vagrant@vagrant\"\n      ssh_options:\n      - \"-F\"\n      - \"scenarios/setup/vagrant/ssh_config\"\n    deploy_to: \"/opt/deploy/target/project\"\n    repository: \"git://wd-git.example.com/project.git\"\n    branch: \"no_rake_hooks\"\n  \"with_rake_hooks\":\n    domain:\n    - name: \"vagrant@vagrant\"\n      ssh_options:\n      - \"-F\"\n      - \"scenarios/setup/vagrant/ssh_config\"\n    deploy_to: \"/opt/deploy/target/project\"\n    repository: \"git://wd-git.example.com/project.git\"\n    branch: \"post_rake_tasks\"\n  \"no_post_scripts\":\n    domain:\n    - name: \"vagrant@vagrant\"\n      ssh_options:\n      - \"-F\"\n      - \"scenarios/setup/vagrant/ssh_config\"\n    deploy_to: \"/opt/deploy/target/project\"\n    repository: \"git://wd-git.example.com/project.git\"\n  \"missing_post_scripts\":\n    domain:\n    - name: \"vagrant@vagrant\"\n      ssh_options:\n      - \"-F\"\n      - \"scenarios/setup/vagrant/ssh_config\"\n    deploy_to: \"/opt/deploy/target/project\"\n    repository: \"git://wd-git.example.com/project.git\"\n    post_setup_script: \"bin/missing.sh\"\n    post_deploy_script: \"bin/missing.sh\"\n    rake_env:\n      FOO: \"BAR\"\n  \"with_post_scripts\":\n    domain:\n    - name: \"vagrant@vagrant\"\n      ssh_options:\n      - \"-F\"\n      - \"scenarios/setup/vagrant/ssh_config\"\n    deploy_to: \"/opt/deploy/target/project\"\n    repository: \"git://wd-git.example.com/project.git\"\n    post_setup_script: \"bin/post_setup_script.sh\"\n    post_deploy_script: \"bin/post_deploy_script.sh\"\n    rake_env:\n      FOO: \"BAR\"\n  \"with_failing_post_scripts\":\n    domain:\n    - name: \"vagrant@vagrant\"\n      ssh_options:\n      - \"-F\"\n      - \"scenarios/setup/vagrant/ssh_config\"\n    deploy_to: \"/opt/deploy/target/project\"\n    repository: \"git://wd-git.example.com/project.git\"\n    post_setup_script: \"bin/failing_post_setup_script.sh\"\n    post_deploy_script: \"bin/failing_post_deploy_script.sh\"\n    rake_env:\n      FOO: \"BAR\"\n  \"hook_with_changed\":\n    domain:\n    - name: \"vagrant@vagrant\"\n      ssh_options:\n      - \"-F\"\n      - \"scenarios/setup/vagrant/ssh_config\"\n    deploy_to: \"/opt/deploy/target/project\"\n    repository: \"git://wd-git.example.com/project.git\"\n    deploy_config_to: \"/opt/deploy/target/config\"\n    config_repository: \"git://wd-git.example.com/config.git\"\n    branch: \"hook_with_changed\"\n  \"with_ssh_options\":\n    domain:\n    - name: \"vagrant@vagrant\"\n      ssh_options:\n      - \"-F\"\n      - \"scenarios/setup/vagrant/ssh_config\"\n      - \"-t\"\n      - \"-v\"\n    deploy_to: \"/tmp/wd-integration-target/destination/project\"\n    repository: \"git://wd-git.example.com/project.git\"\n\n"
  },
  {
    "path": "scenarios/setup/vagrant/.gitignore",
    "content": "ssh_config\n.vagrant\ndeployed\n"
  },
  {
    "path": "scenarios/setup/vagrant/Vagrantfile",
    "content": "Vagrant::Config.run do |config|\n  config.vm.box = \"base\"\n  config.vm.share_folder \"deployment\", \"/opt/deploy\", \"deployed\"\n  config.vm.share_folder \"wd_lib\", \"/opt/lib\", \"../../../lib\"\n\n  config.vm.provision :puppet do |puppet|\n    puppet.manifests_path = \"manifests\"\n    puppet.manifest_file = \"integration.pp\"\n  end\nend\n"
  },
  {
    "path": "scenarios/setup/vagrant/manifests/integration.pp",
    "content": "file { '/etc/motd':\n  content => \"Welcome to your Vagrant-built virtual machine! Managed by Puppet.\\n\"\n}\n\nfile { '/opt/deploy/target':\n  ensure => directory,\n  owner => 'vagrant',\n  group => 'vagrant',\n  mode => '775'\n}\n\nfile { '/home/vagrant/.bashrc':\n  ensure => 'present',\n  owner => 'vagrant',\n  group => 'vagrant',\n  mode => '755',\n  content => 'RUBYLIB=\"/opt/lib\"; export RUBYLIB'\n}\n\nhost {'host':\n  ensure       => 'present',\n  host_aliases => 'wd-git.example.com',\n  ip           => '10.0.2.2',\n}\n\npackage {'git-core':\n  ensure       => 'latest'\n}\n\npackage {'rake':\n  ensure       => 'latest'\n}\n"
  },
  {
    "path": "scenarios/setup/vagrant/pids/.gitignore",
    "content": "*.pid\n"
  },
  {
    "path": "spec/.bacon",
    "content": ""
  },
  {
    "path": "spec/init_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper.rb'))\nrequire 'rake'\n\ndescribe 'when the init.rb plugin loader has been included' do\n  it 'loads the main library' do\n    require(File.expand_path(File.join(File.dirname(__FILE__), '..', 'init')))\n    $\".should.include(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'whiskey_disk.rb')))\n  end\nend\n"
  },
  {
    "path": "spec/install_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))\n\ndef do_install\n  eval File.read(File.join(File.dirname(__FILE__), *%w[.. install.rb ]))\nend\n\ndescribe 'the plugin install.rb script' do\n  before do\n    self.stub!(:puts).and_return(true)\n  end\n  \n  it 'displays the content of the plugin README file' do\n    self.stub!(:readme_contents).and_return('README CONTENTS')\n    self.should.receive(:puts).with('README CONTENTS')\n    do_install\n  end\n  \n  describe 'readme_contents' do\n    it 'works without arguments' do\n      do_install\n      lambda { readme_contents }.should.not.raise(ArgumentError)\n    end\n    \n    it 'accepts no arguments' do\n      do_install\n      lambda { readme_contents(:foo) }.should.raise(ArgumentError)\n    end\n    \n    it 'reads the plugin README file' do\n      do_install\n      File.stub!(:join).and_return('/path/to/README')\n      IO.should.receive(:read).with('/path/to/README')\n      readme_contents\n    end\n    \n    it 'returns the contents of the plugin README file' do\n      do_install\n      File.stub!(:join).and_return('/path/to/README')\n      IO.stub!(:read).with('/path/to/README').and_return('README CONTENTS')\n      readme_contents.should == 'README CONTENTS'\n    end\n  end\nend"
  },
  {
    "path": "spec/integration/branch_switching_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper.rb'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'whiskey_disk'))\n\nintegration_spec do\n  describe 'when configured for a remote deployment' do\n    before do\n      setup_deployment_area\n    end\n  \n    describe 'and deploying on a different branch than originally deployed' do\n      before do\n        @config = scenario_config('remote/deploy.yml')\n        @args = \"--path=#{@config} --to=project:remote\"\n        run_setup(@args)\n        run_deploy(@args)\n\n        @args = \"--path=#{@config} --to=project:remote-on-other-branch\"\n        File.unlink(deployed_file('project/README'))  # modify the deployed checkout\n      end\n      \n      it 'updates the checkout of the repository on the target path' do\n        run_deploy(@args)\n        File.exists?(deployed_file('project/README')).should == true\n      end    \n\n      it 'has the working copy set to the new branch' do\n        run_deploy(@args)\n        current_branch('project').should == 'no_rake_hooks'\n      end\n\n      it 'reports the remote deployment as successful' do\n        run_deploy(@args)\n        File.read(integration_log).should =~ /vagrant => succeeded/\n      end\n\n      it 'exits with a true status' do\n        run_deploy(@args).should == true\n      end\n    end\n  end\nend"
  },
  {
    "path": "spec/integration/deployment_failures_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper.rb'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'whiskey_disk'))\n\nintegration_spec do  \n  describe 'when specified project cannot be found in the configuration' do\n    before do\n      setup_deployment_area\n      \n      @config = scenario_config('remote/deploy.yml')\n      @args = \"--path=#{@config} --to=bogus:remote\"\n    end\n\n    describe 'and performing a setup' do\n      it 'does not checkout a repository for the project to the target path' do\n        run_setup(@args)\n        File.exists?(deployed_file('bogus')).should == false\n      end\n      \n      it 'does not checkout a repository for any project in the configuration file to the target path' do\n        run_setup(@args)\n        File.exists?(deployed_file('project')).should == false\n      end\n      \n      it 'includes a helpful error message' do\n        run_setup(@args)\n        File.read(integration_log).should =~ /No configuration file defined data for project `bogus`/\n      end\n      \n      it 'exits with a false status' do\n        run_setup(@args).should == false\n      end\n    end\n\n    describe 'and performing a deployment' do\n      before do\n        checkout_repo('project')\n        File.unlink(deployed_file('project/README'))  # modify the deployed checkout\n      end        \n\n      it 'does not checkout a repository for the project to the target path' do\n        run_deploy(@args)\n        File.exists?(deployed_file('bogus')).should == false\n      end\n      \n      it 'does not update the repository for any project in the configuration file to the target path' do\n        run_deploy(@args)\n        File.exists?(deployed_file('project/README')).should == false\n      end\n      \n      it 'includes a helpful error message' do\n        run_deploy(@args)\n        File.read(integration_log).should =~ /No configuration file defined data for project `bogus`/\n      end\n      \n      it 'exits with a false status' do\n        run_deploy(@args).should == false\n      end\n    end\n  end\n  \n  describe 'when specified environment cannot be found in the configuration' do\n    before do\n      setup_deployment_area\n      \n      @config = scenario_config('remote/deploy.yml')\n      @args = \"--path=#{@config} --to=project:bogus\"\n    end\n\n    describe 'and performing a setup' do\n      it 'does not checkout a repository for the project to the target path' do\n        run_setup(@args)\n        File.exists?(deployed_file('project')).should == false\n      end\n      \n      it 'includes a helpful error message' do\n        run_setup(@args)\n        File.read(integration_log).should =~ /No configuration file defined data for project `project`, environment `bogus`/\n      end\n      \n      it 'exits with a false status' do\n        run_setup(@args).should == false\n      end\n    end\n\n    describe 'and performing a deployment' do\n      before do\n        checkout_repo('project')\n        File.unlink(deployed_file('project/README'))  # modify the deployed checkout\n      end        \n\n      it 'does not update the repository for the project to the target path' do\n        run_deploy(@args)\n        File.exists?(deployed_file('project/README')).should == false\n      end\n      \n      it 'includes a helpful error message' do\n        run_deploy(@args)\n        File.read(integration_log).should =~ /No configuration file defined data for project `project`, environment `bogus`/\n      end\n      \n      it 'exits with a false status' do\n        run_deploy(@args).should == false\n      end\n    end\n  end\nend"
  },
  {
    "path": "spec/integration/helper_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper.rb'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'whiskey_disk'))\n\nintegration_spec do\n  describe 'when a post_deploy hook uses the changed? method' do\n    before do\n      setup_deployment_area\n      @config = scenario_config('remote/deploy.yml')\n      @args = \"--path=#{@config} --to=project:hook_with_changed\"\n    end\n\n    describe 'and performing a setup' do\n      it 'performs a checkout of the repository to the target path' do\n        run_setup(@args)\n        File.exists?(deployed_file('project/README')).should == true\n      end\n\n      it 'considers all files changed, running any actions guarded by #changed?' do\n        run_setup(@args)\n        File.read(integration_log).should =~ /changed\\? was true/\n      end\n\n      it 'considers all files changed, including by rsync, running any actions guarded by #changed?' do\n        run_setup(@args)\n        File.read(integration_log).should =~ /changed\\? by rsync was true/\n      end\n\n      it 'considers all files changed, not running any actions guarded by ! #changed?' do\n        run_setup(@args)\n        File.read(integration_log).should.not =~ /changed\\? was false/\n      end\n\n      it 'considers all files changed, including by rsync not running any actions guarded by ! #changed?' do\n        run_setup(@args)\n        File.read(integration_log).should.not =~ /changed\\? by rsync was false/\n      end\n\n      it 'reports the remote setup as successful' do\n        run_setup(@args)\n        File.read(integration_log).should =~ /vagrant => succeeded/\n      end\n\n      it 'exits with a true status' do\n        run_setup(@args).should == true\n      end\n    end\n\n    describe 'and performing a deployment' do\n      before do\n        checkout_repo('project', 'hook_with_changed')\n        checkout_repo('config')\n        jump_to_initial_commit('project') # reset the deployed checkout\n      end\n\n      it 'updates the repo checkout' do\n        run_deploy(@args)\n        File.exists?(deployed_file('project/README')).should == true\n      end\n\n      it 'runs actions contingent on file changes' do\n        run_deploy(@args)\n        File.read(integration_log).should =~ /changed\\? was true/\n      end\n\n      it 'runs actions contingent on rsync file changes' do\n        run_deploy(@args)\n        File.read(integration_log).should =~ /changed\\? by rsync was true/\n      end\n\n      it 'does not run actions contingent upon files not changing' do\n        run_deploy(@args)\n        File.read(integration_log).should =~ /changed\\? was false/\n      end\n\n      it 'does not run actions contingent upon rsync files not changing' do\n        run_deploy(@args)\n        File.read(integration_log).should =~ /changed\\? by rsync was false/\n      end\n\n      it 'exits with a true status' do\n        run_deploy(@args).should == true\n      end\n\n      it 'reports the deployment as successful' do\n        run_deploy(@args)\n        File.read(integration_log).should =~ /vagrant => succeeded/\n      end\n    end\n  end\nend"
  },
  {
    "path": "spec/integration/invalid_configuration_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper.rb'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'whiskey_disk'))\n\nintegration_spec do\n  describe 'when an invalid configuration file is specified' do\n    before do\n      setup_deployment_area\n      @config = scenario_config('invalid/deploy.yml')\n      @args = \"--path=#{@config} --to=project:invalid\"\n    end\n    \n    describe 'performing a setup' do\n      it 'exits with a false status' do\n        run_setup(@args).should == false\n      end\n      \n      it 'does not create a repo checkout' do\n        run_setup(@args)\n        File.exists?(deployed_file('project')).should == false\n      end\n    end\n  \n    describe 'performing a deployment' do\n      before do\n        checkout_repo('project')\n        File.unlink(deployed_file('project/README'))  # modify the deployed checkout\n      end\n\n      it 'exits with a false status' do\n        run_deploy(@args).should == false\n      end      \n    \n      it 'does not update a repo checkout' do\n        run_deploy(@args)\n        File.exists?(deployed_file('project/README')).should == false\n      end\n    end\n  end\nend"
  },
  {
    "path": "spec/integration/local_deployments_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper.rb'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'whiskey_disk'))\n\nintegration_spec do\n  describe 'when configured for a local deployment' do\n    before do\n      setup_deployment_area\n    end\n\n    describe 'when the configuration specifies no domain' do\n      before do\n        @config = scenario_config('local/deploy.yml.erb')\n        @args = \"--path=#{@config} --to=project:local-default\"\n      end\n\n      describe 'performing a setup' do\n        it 'performs a checkout of the repository to the target path' do\n          run_setup(@args)\n          File.exists?(deployed_file('project/README')).should == true\n        end\n\n        it 'reports the local setup as successful' do\n          run_setup(@args)\n          File.read(integration_log).should =~ /local => succeeded/\n        end\n\n        it 'exits with a true status' do\n          run_setup(@args).should == true\n        end\n      end\n\n      describe 'performing a deployment' do\n        before do\n          checkout_repo('project')\n          File.unlink(deployed_file('project/README'))  # modify the deployed checkout\n        end\n\n        it 'updates the checkout of the repository on the target path' do\n          run_deploy(@args)\n          File.exists?(deployed_file('project/README')).should == true\n        end\n\n        it 'reports the local deployment as successful' do\n          run_deploy(@args)\n          File.read(integration_log).should =~ /local => succeeded/\n        end\n\n        it 'exits with a true status' do\n          run_deploy(@args).should == true\n        end\n      end\n    end\n\n    describe 'when the configuration specifies a single domain via the \"local\" keyword' do\n      before do\n        @config = scenario_config('local/deploy.yml.erb')\n        @args = \"--path=#{@config} --to=project:local-keyword\"\n      end\n\n      describe 'performing a setup' do\n        it 'performs a checkout of the repository to the target path' do\n          run_setup(@args)\n          File.exists?(deployed_file('project/README')).should == true\n        end\n\n        it 'reports the local setup as successful' do\n          run_setup(@args)\n          File.read(integration_log).should =~ /local => succeeded/\n        end\n\n        it 'exits with a true status' do\n          run_setup(@args).should == true\n        end\n      end\n\n      describe 'performing a deployment' do\n        before do\n          checkout_repo('project')\n          File.unlink(deployed_file('project/README'))  # modify the deployed checkout\n        end\n\n        it 'updates the checkout of the repository on the target path' do\n          run_deploy(@args)\n          File.exists?(deployed_file('project/README')).should == true\n        end\n\n        it 'reports the local deployment as successful' do\n          run_deploy(@args)\n          File.read(integration_log).should =~ /local => succeeded/\n        end\n\n        it 'exits with a true status' do\n          run_deploy(@args).should == true\n        end\n      end\n    end\n\n    describe 'when the configuration specifies a single domain specified as user@domain, using --only=domain' do\n      before do\n        @config = scenario_config('local/deploy.yml.erb')\n        @args = \"--path=#{@config} --to=project:local-user-domain --only=localhost\"\n      end\n\n      describe 'performing a setup' do\n        it 'performs a checkout of the repository to the target path' do\n          run_setup(@args)\n          File.exists?(deployed_file('project/README')).should == true\n        end\n\n        it 'reports the named domain setup as successful' do\n          run_setup(@args)\n          File.read(integration_log).should =~ /localhost => succeeded/\n        end\n\n        it 'exits with a true status' do\n          run_setup(@args).should == true\n        end\n      end\n\n      describe 'performing a deployment' do\n        before do\n          checkout_repo('project')\n          File.unlink(deployed_file('project/README'))  # modify the deployed checkout\n        end\n\n        it 'updates the checkout of the repository on the target path' do\n          run_deploy(@args)\n          File.exists?(deployed_file('project/README')).should == true\n        end\n\n        it 'reports the named domain deployment as successful' do\n          run_deploy(@args)\n          File.read(integration_log).should =~ /localhost => succeeded/\n        end\n\n        it 'exits with a true status' do\n          run_deploy(@args).should == true\n        end\n      end\n    end\n\n    describe 'when the configuration specifies a single domain without username, using --only=domain' do\n      before do\n        @config = scenario_config('local/deploy.yml.erb')\n        @args = \"--path=#{@config} --to=project:local-domain --only=localhost\"\n      end\n\n      describe 'performing a setup' do\n        it 'performs a checkout of the repository to the target path' do\n          run_setup(@args)\n          File.exists?(deployed_file('project/README')).should == true\n        end\n\n        it 'reports the named domain setup as successful' do\n          run_setup(@args)\n          File.read(integration_log).should =~ /localhost => succeeded/\n        end\n\n        it 'exits with a true status' do\n          run_setup(@args).should == true\n        end\n      end\n\n      describe 'performing a deployment' do\n        before do\n          checkout_repo('project')\n          File.unlink(deployed_file('project/README'))  # modify the deployed checkout\n        end\n\n        it 'updates the checkout of the repository on the target path' do\n          run_deploy(@args)\n          File.exists?(deployed_file('project/README')).should == true\n        end\n\n        it 'reports the named domain deployment as successful' do\n          run_deploy(@args)\n          File.read(integration_log).should =~ /localhost => succeeded/\n        end\n\n        it 'exits with a true status' do\n          run_deploy(@args).should == true\n        end\n      end\n    end\n\n    describe 'when the configuration specifies a single domain which does not match the --only domain' do\n      before do\n        @config = scenario_config('local/deploy.yml.erb')\n        @args = \"--path=#{@config} --to=project:local-domain --only=vagrant2\"\n      end\n\n      describe 'performing a setup' do\n        it 'does not perform a checkout of the repository to the target path' do\n          run_setup(@args)\n          File.exists?(deployed_file('project/README')).should == false\n        end\n\n        it 'reports that there were no deployments' do\n          run_setup(@args)\n          File.read(integration_log).should =~ /No deployments/\n        end\n\n        it 'exits with a true status' do\n          run_setup(@args).should == true\n        end\n      end\n\n      describe 'performing a deployment' do\n        before do\n          checkout_repo('project')\n          File.unlink(deployed_file('project/README'))  # modify the deployed checkout\n        end\n\n        it 'does not update the checkout of the repository on the target path' do\n          run_deploy(@args)\n          File.exists?(deployed_file('project/README')).should == false\n        end\n\n        it 'reports that there were no deployments' do\n          run_deploy(@args)\n          File.read(integration_log).should =~ /No deployments/\n        end\n\n        it 'exits with a true status' do\n          run_deploy(@args).should == true\n        end\n      end\n    end\n  end\nend"
  },
  {
    "path": "spec/integration/post_rake_tasks_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper.rb'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'whiskey_disk'))\n\nintegration_spec do\n  describe 'when configured for a remote deployment' do\n    before do\n      setup_deployment_area\n    end\n  \n    describe 'with no Rakefile in the project' do\n      before do\n        @config = scenario_config('remote/deploy.yml')\n        @args = \"--path=#{@config} --to=project:no_rakefile\"\n      end\n      \n      describe 'performing a setup' do\n        it 'performs a checkout of the repository to the target path' do\n          run_setup(@args)\n          File.exists?(deployed_file('project/README')).should == true\n        end\n        \n        it 'does not run a deploy:post_setup rake task' do\n          run_setup(@args)\n          File.read(integration_log).should.not =~ /Running a post_setup task/\n        end\n            \n        it 'reports the remote setup as successful' do\n          run_setup(@args)\n          File.read(integration_log).should =~ /vagrant => succeeded/\n        end\n\n        it 'exits with a true status' do\n          run_setup(@args).should == true\n        end\n      end\n      \n      describe 'performing a deployment' do\n        before do\n          checkout_repo('project')\n          File.unlink(deployed_file('project/README'))  # modify the deployed checkout\n        end\n        \n        it 'updates the checkout of the repository on the target path' do\n          run_deploy(@args)\n          File.exists?(deployed_file('project/README')).should == true\n        end    \n\n        it 'does not run a deploy:post_deploy rake task' do\n          run_deploy(@args)\n          File.read(integration_log).should.not =~ /Running a post_deploy task/\n        end\n            \n        it 'reports the remote deployment as successful' do\n          run_deploy(@args)\n          File.read(integration_log).should =~ /vagrant => succeeded/\n        end\n\n        it 'exits with a true status' do\n          run_deploy(@args).should == true\n        end\n      end\n    end\n    \n    describe 'with an unparseable Rakefile in the project' do\n      before do\n        @config = scenario_config('remote/deploy.yml')\n        @args = \"--path=#{@config} --to=project:bad_rakefile\"\n      end\n      \n      describe 'performing a setup' do\n        it 'performs a checkout of the repository to the target path' do\n          run_setup(@args)\n          File.exists?(deployed_file('project/README')).should == true\n        end\n        \n        it 'does not run a deploy:post_setup rake task' do\n          run_setup(@args)\n          File.read(integration_log).should.not =~ /Running a post_setup task/\n        end\n            \n        it 'reports the remote setup as a failure' do\n          run_setup(@args)\n          File.read(integration_log).should =~ /vagrant => failed/\n        end\n\n        it 'exits with a false status' do\n          run_setup(@args).should == false\n        end\n      end\n      \n      describe 'performing a deployment' do\n        before do\n          checkout_repo('project', 'bad_rakefile')\n          File.unlink(deployed_file('project/README'))  # modify the deployed checkout\n        end\n        \n        it 'updates the checkout of the repository on the target path' do\n          run_deploy(@args)\n          File.exists?(deployed_file('project/README')).should == true\n        end    \n\n        it 'does not run a deploy:post_deploy rake task' do\n          run_deploy(@args)\n          File.read(integration_log).should.not =~ /Running a post_deploy task/\n        end\n            \n        it 'reports the remote deployment as a failure' do\n          run_deploy(@args)\n          File.read(integration_log).should =~ /vagrant => failed/\n        end\n\n        it 'exits with a false status' do\n          run_deploy(@args).should == false\n        end\n      end      \n    end\n    \n    describe 'with a valid Rakefile in the project with no post_setup or post_deploy hooks' do\n      before do\n        @config = scenario_config('remote/deploy.yml')\n        @args = \"--path=#{@config} --to=project:no_rake_hooks\"\n      end\n      \n      describe 'and doing a setup' do\n        it 'performs a checkout of the repository to the target path' do\n          run_setup(@args)\n          File.exists?(deployed_file('project/README')).should == true\n        end\n        \n        it 'does not run a deploy:post_setup rake task' do\n          run_setup(@args)\n          File.read(integration_log).should.not =~ /Running a post_setup task/\n        end\n            \n        it 'reports the remote setup as successful' do\n          run_setup(@args)\n          File.read(integration_log).should =~ /vagrant => succeeded/\n        end\n\n        it 'exits with a true status' do\n          run_setup(@args).should == true\n        end\n      end\n\n      describe 'and doing a deploy' do\n        before do\n          checkout_repo('project', 'no_rake_hooks')\n          File.unlink(deployed_file('project/README'))  # modify the deployed checkout\n        end\n        \n        it 'updates the checkout of the repository on the target path' do\n          run_deploy(@args)\n          File.exists?(deployed_file('project/README')).should == true\n        end    \n\n        it 'does not run a deploy:post_deploy rake task' do\n          run_deploy(@args)\n          File.read(integration_log).should.not =~ /Running a post_deploy task/\n        end\n            \n        it 'reports the remote deployment as successful' do\n          run_deploy(@args)\n          File.read(integration_log).should =~ /vagrant => succeeded/\n        end\n\n        it 'exits with a true status' do\n          run_deploy(@args).should == true\n        end\n      end\n    end\n    \n    describe 'with a valid Rakefile in the project with post_setup and post_deploy hooks' do\n      before do\n        @config = scenario_config('remote/deploy.yml')\n        @args = \"--path=#{@config} --to=project:with_rake_hooks\"\n      end\n      \n      describe 'and doing a setup' do\n        it 'performs a checkout of the repository to the target path' do\n          run_setup(@args)\n          File.exists?(deployed_file('project/README')).should == true\n        end\n        \n        it 'runs a deploy:post_setup rake task' do\n          run_setup(@args)\n          File.read(integration_log).should =~ /Running a post_setup task/\n        end\n            \n        it 'reports the remote setup as successful' do\n          run_setup(@args)\n          File.read(integration_log).should =~ /vagrant => succeeded/\n        end\n\n        it 'exits with a true status' do\n          run_setup(@args).should == true\n        end\n      end\n\n      describe 'and doing a deploy' do\n        before do\n          checkout_repo('project', 'post_rake_tasks')\n          File.unlink(deployed_file('project/README'))  # modify the deployed checkout\n        end\n        \n        it 'updates the checkout of the repository on the target path' do\n          run_deploy(@args)\n          File.exists?(deployed_file('project/README')).should == true\n        end    \n\n        it 'runs a deploy:post_deploy rake task' do\n          run_deploy(@args)\n          File.read(integration_log).should =~ /Running a post_deploy task/\n        end\n            \n        it 'reports the remote deployment as successful' do\n          run_deploy(@args)\n          File.read(integration_log).should =~ /vagrant => succeeded/\n        end\n\n        it 'exits with a true status' do\n          run_deploy(@args).should == true\n        end\n      end\n    end\n  end\nend"
  },
  {
    "path": "spec/integration/post_scripts_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper.rb'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'whiskey_disk'))\n\nintegration_spec do\n  describe 'when configured for a remote deployment' do\n    before do\n      setup_deployment_area\n    end\n  \n    describe 'with no post_* scripts defined' do\n      before do\n        @config = scenario_config('remote/deploy.yml')\n        @args = \"--path=#{@config} --to=project:no_post_scripts\"\n      end\n      \n      describe 'performing a setup' do\n        it 'performs a checkout of the repository to the target path' do\n          run_setup(@args)\n          File.exists?(deployed_file('project/README')).should == true\n        end\n        \n        it 'does not run a post_setup script' do\n          run_setup(@args)\n          File.read(integration_log).should.not =~ /^Running post script/\n        end\n            \n        it 'reports the remote setup as successful' do\n          run_setup(@args)\n          File.read(integration_log).should =~ /vagrant => succeeded/\n        end\n\n        it 'exits with a true status' do\n          run_setup(@args).should == true\n        end\n      end\n      \n      describe 'performing a deployment' do\n        before do\n          checkout_repo('project')\n          File.unlink(deployed_file('project/README'))  # modify the deployed checkout\n        end\n        \n        it 'updates the checkout of the repository on the target path' do\n          run_deploy(@args)\n          File.exists?(deployed_file('project/README')).should == true\n        end    \n\n        it 'does not run a post_deploy script' do\n          run_deploy(@args)\n          File.read(integration_log).should.not =~ /^Running post script/\n        end\n            \n        it 'reports the remote deployment as successful' do\n          run_deploy(@args)\n          File.read(integration_log).should =~ /vagrant => succeeded/\n        end\n\n        it 'exits with a true status' do\n          run_deploy(@args).should == true\n        end\n      end\n    end\n    \n    describe 'with missing post_* scripts defined' do\n      before do\n        @config = scenario_config('remote/deploy.yml')\n        @args = \"--path=#{@config} --to=project:missing_post_scripts\"\n      end\n      \n      describe 'performing a setup' do\n        it 'performs a checkout of the repository to the target path' do\n          run_setup(@args)\n          File.exists?(deployed_file('project/README')).should == true\n        end\n        \n        it 'attempts to run a post_setup script' do\n          run_setup(@args)\n          File.read(integration_log).should =~ /^Running post script/\n        end\n        \n        it 'passes environment variable settings to the post_setup script' do\n          run_setup(@args)\n          File.read(integration_log).should =~ /FOO=BAR/\n        end\n            \n        it 'reports the remote setup as a failure' do\n          run_setup(@args)\n          File.read(integration_log).should =~ /vagrant => failed/\n        end\n\n        it 'exits with a false status' do\n          run_setup(@args).should == false\n        end\n      end\n      \n      describe 'performing a deployment' do\n        before do\n          checkout_repo('project')\n          File.unlink(deployed_file('project/README'))  # modify the deployed checkout\n        end\n        \n        it 'updates the checkout of the repository on the target path' do\n          run_deploy(@args)\n          File.exists?(deployed_file('project/README')).should == true\n        end    \n\n        it 'attempts to run a post_deploy script' do\n          run_deploy(@args)\n          File.read(integration_log).should =~ /^Running post script/\n        end\n            \n        it 'passes environment variable settings to the post_deploy script' do\n          run_deploy(@args)\n          File.read(integration_log).should =~ /FOO='BAR'/\n        end\n            \n        it 'reports the remote deployment as a failure' do\n          run_deploy(@args)\n          File.read(integration_log).should =~ /vagrant => failed/\n        end\n\n        it 'exits with a false status' do\n          run_deploy(@args).should == false\n        end\n      end      \n    end\n    \n    describe 'with post_* scripts specified and present' do\n      before do\n        @config = scenario_config('remote/deploy.yml')\n        @args = \"--path=#{@config} --to=project:with_post_scripts\"\n      end\n      \n      describe 'and doing a setup' do\n        it 'performs a checkout of the repository to the target path' do\n          run_setup(@args)\n          File.exists?(deployed_file('project/README')).should == true\n        end\n        \n        describe 'and the post_setup script is successful' do\n          it 'runs the post_setup script' do\n            run_setup(@args)\n            File.read(integration_log).should =~ /^Running the post_setup script/\n          end\n\n          it 'passes environment variable settings to the post_setup script' do\n            run_setup(@args)\n            File.read(integration_log).should =~ /FOO=BAR/\n          end\n\n          it 'reports the remote setup as successful' do\n            run_setup(@args)\n            File.read(integration_log).should =~ /vagrant => succeeded/\n          end\n\n          it 'exits with a true status' do\n            run_setup(@args).should == true\n          end          \n        end\n        \n        describe 'and the post_setup script fails' do\n          before do\n            @args = \"--path=#{@config} --to=project:with_failing_post_scripts\"\n          end\n          \n          it 'runs the post_setup script' do\n            run_setup(@args)\n            File.read(integration_log).should =~ /^Running the post_setup script/\n          end\n\n          it 'passes environment variable settings to the post_setup script' do\n            run_setup(@args)\n            File.read(integration_log).should =~ /FOO=BAR/\n          end\n\n          it 'reports the remote setup as a failure' do\n            run_setup(@args)\n            File.read(integration_log).should =~ /vagrant => failed/\n          end\n\n          it 'exits with a false status' do\n            run_setup(@args).should == false\n          end          \n        end\n      end\n\n      describe 'and doing a deploy' do\n        before do\n          checkout_repo('project')\n          File.unlink(deployed_file('project/README'))  # modify the deployed checkout\n        end\n        \n        it 'updates the checkout of the repository on the target path' do\n          run_deploy(@args)\n          File.exists?(deployed_file('project/README')).should == true\n        end    \n\n        describe 'and the post_deploy script is successful' do\n          it 'runs the post_deploy script' do\n            run_deploy(@args)\n            File.read(integration_log).should =~ /^Running the post_deploy script/\n          end\n\n          it 'passes environment variable settings to the post_deploy script' do\n            run_deploy(@args)\n            File.read(integration_log).should =~ /FOO='BAR'/\n          end\n\n          it 'reports the remote deployment as successful' do\n            run_deploy(@args)\n            File.read(integration_log).should =~ /vagrant => succeeded/\n          end\n\n          it 'exits with a true status' do\n            run_deploy(@args).should == true\n          end          \n        end\n        \n        describe 'and the post_deploy script fails' do\n          before do\n            @args = \"--path=#{@config} --to=project:with_failing_post_scripts\"\n          end\n          \n          it 'runs the post_deploy script' do\n            run_deploy(@args)\n            File.read(integration_log).should =~ /^Running the post_deploy script/\n          end\n\n          it 'passes environment variable settings to the post_deploy script' do\n            run_deploy(@args)\n            File.read(integration_log).should =~ /FOO='BAR'/\n          end\n\n          it 'reports the remote deployment as a failure' do\n            run_deploy(@args)\n            File.read(integration_log).should =~ /vagrant => failed/\n          end\n\n          it 'exits with a false status' do\n            run_deploy(@args).should == false\n          end          \n        end\n      end\n    end\n  end\nend"
  },
  {
    "path": "spec/integration/remote_deployments_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper.rb'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'whiskey_disk'))\n\nintegration_spec do\n  describe 'when configured for a remote deployment' do\n    before do\n      setup_deployment_area\n    end\n\n    describe 'with a single remote domain' do\n      before do\n        @config = scenario_config('remote/deploy.yml')\n        @args = \"--path=#{@config} --to=project:remote\"\n      end\n\n      describe 'performing a setup' do\n        it 'performs a checkout of the repository to the target path' do\n          run_setup(@args)\n          File.exists?(deployed_file('project/README')).should == true\n        end\n\n        it 'has the working copy set to the master branch' do\n          run_setup(@args)\n          current_branch('project').should == 'master'\n        end\n\n        it 'has the working copy set to the specified branch when one is available' do\n          @args = \"--path=#{@config} --to=project:remote-on-other-branch\"\n          run_setup(@args)\n          current_branch('project').should == 'no_rake_hooks'\n        end\n\n        it 'reports the remote setup as successful' do\n          run_setup(@args)\n          File.read(integration_log).should =~ /vagrant => succeeded/\n        end\n\n        it 'exits with a true status' do\n          run_setup(@args).should == true\n        end\n      end\n\n      describe 'performing a deployment' do\n        before do\n          checkout_repo('project')\n          File.unlink(deployed_file('project/README'))  # modify the deployed checkout\n        end\n\n        it 'updates the checkout of the repository on the target path' do\n          run_deploy(@args)\n          File.exists?(deployed_file('project/README')).should == true\n        end\n\n        it 'has the working copy set to the master branch' do\n          run_deploy(@args)\n          current_branch('project').should == 'master'\n        end\n\n        it 'has the working copy set to the specified branch when one is available' do\n          @args = \"--path=#{@config} --to=project:remote-on-other-branch\"\n          checkout_branch('project', 'no_rake_hooks')\n          run_deploy(@args)\n          current_branch('project').should == 'no_rake_hooks'\n        end\n\n        it 'reports the remote deployment as successful' do\n          run_deploy(@args)\n          File.read(integration_log).should =~ /vagrant => succeeded/\n        end\n\n        it 'exits with a true status' do\n          run_deploy(@args).should == true\n        end\n      end\n\n      describe 'performing a deploy after a setup' do\n        describe 'and using the master branch' do\n          before do\n            run_setup(@args)\n            File.unlink(deployed_file('project/README'))  # modify the deployed checkout\n          end\n\n          it 'updates the checkout of the repository on the target path' do\n            run_deploy(@args)\n            File.exists?(deployed_file('project/README')).should == true\n          end\n\n          it 'has the working copy set to the master branch' do\n            run_deploy(@args)\n            current_branch('project').should == 'master'\n          end\n\n          it 'has the working copy set to the specified branch when one is available' do\n            setup_deployment_area\n\n            @args = \"--path=#{@config} --to=project:remote-on-other-branch\"\n            run_setup(@args)\n\n            File.unlink(deployed_file('project/README'))\n\n            run_deploy(@args)\n            current_branch('project').should == 'no_rake_hooks'\n          end\n\n          it 'reports the remote deployment as successful' do\n            run_deploy(@args)\n            File.read(integration_log).should =~ /vagrant => succeeded/\n          end\n\n          it 'exits with a true status' do\n            run_deploy(@args).should == true\n          end\n        end\n      end\n    end\n\n    describe 'with ssh options specified' do\n      before do\n        @config = scenario_config('remote/deploy.yml')\n        @args = \"--path=#{@config} --to=project:with_ssh_options\"\n      end\n\n      describe 'performing a setup' do\n        # TODO FIXME -- this spec fails due to interplay between STDOUT and file buffering in ruby system() (*WTF*)\n        #\n        # it 'uses specified ssh options when performing the setup' do\n        #   run_setup(@args)\n        #   dump_log\n        #   File.read(integration_log).should =~ /ssh.* -t /\n        # end\n\n        it 'reports the remote setup as successful' do\n          run_setup(@args)\n          File.read(integration_log).should =~ /vagrant => succeeded/\n        end\n\n        it 'exits with a true status' do\n          run_setup(@args).should == true\n        end\n      end\n\n      describe 'performing a deployment' do\n        before do\n          checkout_repo('project')\n          File.unlink(deployed_file('project/README'))  # modify the deployed checkout\n        end\n\n        # TODO FIXME -- this spec fails due to interplay between STDOUT and file buffering in ruby system() (*WTF*)\n        #\n        # it 'uses specified ssh options when performing the setup' do\n        #   run_deploy(@args, true)\n        #   File.read(integration_log).should =~ /ssh.* -t /\n        # end\n\n        it 'reports the remote deployment as successful' do\n          run_deploy(@args)\n          File.read(integration_log).should =~ /vagrant => succeeded/\n        end\n\n        it 'exits with a true status' do\n          run_deploy(@args).should == true\n        end\n      end\n    end\n  end\nend"
  },
  {
    "path": "spec/integration/staleness_checks_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper.rb'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'whiskey_disk'))\n\nintegration_spec do\n  describe 'when configured for a local deployment' do\n    before do\n      setup_deployment_area\n      @config = scenario_config('local/deploy.yml.erb')\n    end\n\n    describe 'when staleness checkes are enabled' do\n      before do\n        @args = \"--path=#{@config} --to=project:local-default --check\"\n      end\n\n      describe 'performing a deployment' do\n        before do\n          checkout_repo('project')\n          File.unlink(deployed_file('project/README'))  # modify the deployed checkout\n        end\n\n        it 'does not update the checkout of the repository on the target path' do\n          run_deploy(@args)\n          File.exists?(deployed_file('project/README')).should == false\n        end\n\n        it 'reports the local deployment as successful' do\n          run_deploy(@args)\n          File.read(integration_log).should =~ /local => succeeded/\n        end\n\n        it 'exits with a true status' do\n          run_deploy(@args).should == true\n        end\n      end\n    end\n  end\n\n  describe 'when configured for a remote deployment' do\n    before do\n      setup_deployment_area\n      @config = scenario_config('remote/deploy.yml')\n    end\n\n    describe 'when staleness checkes are enabled' do\n      before do\n        @args = \"--path=#{@config} --to=project:remote --check\"\n      end\n\n      describe 'performing a deployment' do\n        before do\n          checkout_repo('project')\n          File.unlink(deployed_file('project/README'))  # modify the deployed checkout\n        end\n\n        it 'does not update the checkout of the repository on the target path' do\n          run_deploy(@args)\n          File.exists?(deployed_file('project/README')).should == false\n        end\n\n        it 'reports the local deployment as successful' do\n          run_deploy(@args)\n          File.read(integration_log).should =~ /vagrant => succeeded/\n        end\n\n        it 'exits with a true status' do\n          run_deploy(@args).should == true\n        end\n      end\n    end\n  end\nend"
  },
  {
    "path": "spec/spec_helper.rb",
    "content": "require 'rubygems'\nrequire 'bacon'\nrequire 'facon'\nrequire 'fileutils'\nrequire 'tempfile'\nrequire 'erb'\n\nif ENV['DEBUG'] and ENV['DEBUG'] != ''\n  STDERR.puts \"Enabling debugger for spec runs...\"\n  require 'rubygems'\n  require 'ruby-debug'\n  Debugger.start\nend\n\n$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')))\n\n# local target directory, integration spec workspace\ndef deployment_root\n  File.expand_path(File.join(File.dirname(__FILE__), '..', 'scenarios', 'setup', 'vagrant', 'deployed', 'target'))\nend\n\n# allow defining an integration spec block\ndef integration_spec(&block)\n  yield if ENV['INTEGRATION'] and ENV['INTEGRATION'] != ''\nend\n\n# reset the deployment directory for integration specs\ndef setup_deployment_area\n  FileUtils.rm_rf(deployment_root)\n  File.umask(0)\n  Dir.mkdir(deployment_root, 0777)\n  Dir.mkdir(deployed_file('log'), 0777)\nend\n\n# run a wd setup using the provided arguments string\ndef run_setup(arguments, debugging = true)\n  wd_path  = File.join(File.dirname(__FILE__), '..', 'bin', 'wd')\n  lib_path = File.join(File.dirname(__FILE__), '..', 'lib')\n  debug = debugging ? '--debug' : ''\n  system(\"/usr/bin/env ruby -I #{lib_path} -r whiskey_disk -rubygems #{wd_path} setup #{debug} #{arguments} > #{integration_log} 2> #{integration_log}\")\nend\n\ndef integration_log\n  deployed_file('log/out.txt')\nend\n\n# run a wd setup using the provided arguments string\ndef run_deploy(arguments, debugging = true)\n  wd_path  = File.join(File.dirname(__FILE__), '..', 'bin', 'wd')\n  lib_path = File.join(File.dirname(__FILE__), '..', 'lib')\n  debug = debugging ? '--debug' : ''\n  status = system(\"/usr/bin/env ruby -I #{lib_path} -r whiskey_disk -rubygems #{wd_path} deploy #{debug} #{arguments} > #{integration_log} 2> #{integration_log}\")\n  status\nend\n\n# build the correct local path to the deployment configuration for a given scenario\ndef scenario_config(path)\n  return erb_scenario_config(path) if path =~ /\\.erb$/\n  scenario_config_path(path)\nend\n\ndef scenario_config_path(path)\n  File.join(File.dirname(__FILE__), '..', 'scenarios', path)\nend\n\ndef erb_scenario_config(path)\n  data = File.read(scenario_config_path(path))\n  converted = erb_eval(data)\n  write_tempfile(converted)\nend\n\ndef erb_eval(data)\n  ERB.new(data).result\nend\n\ndef write_tempfile(data)\n  tmp_file = Tempfile.new('whiskey_disk_integration_spec_scenario')\n  tmp_file.puts(data)\n  tmp_file.close\n  tmp_file.path\nend\n\n# clone a git repository locally (as if a \"wd setup\" had been deployed)\ndef checkout_repo(repo_name, branch = nil)\n  repo_path = File.expand_path(File.join(File.dirname(__FILE__), '..', 'scenarios', 'git_repositories', \"#{repo_name}.git\"))\n  system(\"cd #{deployment_root} && git clone #{repo_path} >/dev/null 2>/dev/null && cd #{repo_name} && git remote set-url origin #{remote_url(repo_name)}\")\n  checkout_branch(repo_name, branch)\nend\n\ndef remote_url(repo)\n  \"git://wd-git.example.com/#{repo}.git\"\nend\n\ndef checkout_branch(repo_name, branch = nil)\n  return unless branch\n  system(\"cd #{deployment_root}/#{repo_name} && git checkout #{branch} >/dev/null 2>/dev/null\")\nend\n\ndef jump_to_initial_commit(path)\n  system(%Q(cd #{File.join(deployment_root, path)} && git reset --hard `git log --oneline | tail -1 | awk '{print $1}'` >/dev/null 2>/dev/null))\nend\n\ndef run_log\n  File.readlines(integration_log)\nend\n\ndef deployed_file(path)\n  File.join(deployment_root, path)\nend\n\ndef dump_log\n  STDERR.puts(\"\\n\\n\\n\" + File.read(integration_log) + \"\\n\\n\\n\")\nend\n\ndef current_branch(path)\n  `cd #{deployed_file(path)} && git branch`.split(\"\\n\").grep(/^\\*/).first.sub(/^\\* /, '')\nend"
  },
  {
    "path": "spec/wd_command_spec.rb",
    "content": "require_relative('spec_helper.rb')\nrequire 'rake'\n\ndef run_command\n  cmd_path = File.expand_path(File.join(File.dirname(__FILE__), *%w[.. bin wd]))\n  path = File.expand_path(File.dirname(cmd_path))\n  file = File.read(cmd_path)\n\n  Dir.chdir(path) do |path|\n    eval(file)\n  end\nend\n\ndescribe 'wd command' do\n  before do\n    @stderr, @stdout, $stderr, $stdout = $stderr, $stdout, StringIO.new, StringIO.new\n    ENV['to'] = ENV['path'] = nil\n  end\n\n  after do\n    @stderr, @stdout, $stderr, $stdout = $stderr, $stdout, @stderr, @stdout\n  end\n  \n  describe 'when no command-line arguments are specified' do\n    before do\n      Object.send(:remove_const, :ARGV)\n      ARGV = []\n    end  \n    \n    it 'does not run rake tasks' do\n      Rake::Application.should.receive(:new).never\n      lambda { run_command }\n    end\n  \n    it 'exits' do\n      lambda { run_command }.should.raise(SystemExit)\n    end\n    \n    it 'exits with a failure status' do\n      begin\n        run_command\n      rescue Exception => e\n        e.success?.should == false\n      end\n    end\n  end\n\n  it 'outputs usage without a backtrace when --help is specified' do\n    Object.send(:remove_const, :ARGV)\n    ARGV = ['--help']\n    lambda { run_command }.should.raise(SystemExit)\n  end\n  \n  it 'outputs usage without a backtrace when garbage options are specified' do\n    Object.send(:remove_const, :ARGV)\n    ARGV = ['--slkjfsdflkj']\n    lambda { run_command }.should.raise(SystemExit)\n  end\n  \n  describe 'when --version argument is specified' do\n    before do\n      Object.send(:remove_const, :ARGV)\n      ARGV = ['--version']\n    end\n  \n    # it 'outputs the version stored in the VERSION file' do\n    #   version = File.read(File.expand_path(File.join(File.dirname(__FILE__), '..', 'VERSION'))).chomp\n    #   # TODO: capture version output\n    #   lambda{ run_command }\n    # end\n  \n    it 'exits' do\n      lambda { run_command }.should.raise(SystemExit)\n    end\n  \n    it 'exits successfully' do\n      begin\n        run_command\n      rescue SystemExit => e\n        e.success?.should == true\n      end\n    end\n  end\n\n  describe \"when the 'setup' command is specified\" do\n    before do\n      Object.send(:remove_const, :ARGV)\n      ARGV = ['setup']\n    end  \n\n    describe 'and no target is specified' do    \n      it 'does not run rake tasks' do\n        Rake::Application.should.receive(:new).never\n        lambda { run_command }\n      end\n\n      it 'exits when a target is specified' do\n        lambda { run_command }.should.raise(SystemExit)\n      end\n\n      it 'exits with a failing status when a target is specified' do\n        begin\n          run_command\n        rescue SystemExit => e\n          e.success?.should == false\n        end\n      end\n    end\n\n    \n    describe 'and a --to argument is specified' do\n      before do\n        ARGV.push '--to=foo'\n        @rake = Rake::Task['deploy:setup']\n        @rake.stub!(:invoke)\n      end\n      \n      it 'does not fail' do\n        lambda { run_command }.should.not.raise\n      end\n      \n      it 'runs the deploy:setup rake task' do\n        @rake.should.receive(:invoke)\n        run_command\n      end\n      \n      it 'makes the specified target available as a \"to\" argument to the rake task' do\n        run_command\n        ENV['to'].should == 'foo'\n      end\n      \n      describe 'and a --path argument is specified' do\n        before do\n          ARGV.push '--path=/path/to/foo'\n        end\n        \n        it 'makes the specified path available as a \"path\" argument to the rake task' do\n          run_command\n          ENV['path'].should == '/path/to/foo'\n        end\n      \n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n      \n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n      \n      describe 'and a -p argument is specified' do\n        before do\n          ARGV.push '-p'\n          ARGV.push '/path/to/foo'\n        end\n        \n        it 'makes the specified path available as a \"path\" argument to the rake task' do\n          run_command\n          ENV['path'].should == '/path/to/foo'\n        end\n      \n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n      \n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n      \n      describe 'and no --path or -p argument is specified' do\n        it 'does not make a \"path\" argument available to the rake task' do\n          ENV['path'].should.be.nil\n        end\n      \n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n      \n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n\n      describe 'and a --only argument is specified' do\n        before do\n          @domain = 'smeghost'\n          ARGV.push \"--only=#{@domain}\"\n        end\n\n        it 'makes the specified domain available as an \"only\" argument to the rake task' do\n          run_command\n          ENV['only'].should == @domain\n        end\n\n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n\n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n\n      describe 'and a -o argument is specified' do\n        before do\n          @domain = 'smeghost'\n          ARGV.push '-o'\n          ARGV.push @domain\n        end\n\n        it 'makes the specified domain available as an \"only\" argument to the rake task' do\n          run_command\n          ENV['only'].should == @domain\n        end\n\n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n\n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n\n      describe 'and no --only or -o argument is specified' do\n        it 'does not make an \"only\" argument available to the rake task' do\n          run_command\n          ENV['only'].should.be.nil\n        end\n\n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n\n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n\n      describe 'and a --debug argument is specified' do\n        before do\n          ARGV.push '--debug'\n        end\n\n        it 'runs the deploy:now rake task' do\n          @rake.should.receive(:invoke)\n          run_command\n        end\n\n        it 'makes the specified target available as a \"debug\" argument to the rake task' do\n          run_command\n          ENV['debug'].should == 'true'\n        end\n\n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n\n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n      \n      describe 'and a -d argument is specified' do\n        before do\n          ARGV.push '-d'\n        end\n\n        it 'runs the deploy:now rake task' do\n          @rake.should.receive(:invoke)\n          run_command\n        end\n\n        it 'makes the specified target available as a \"debug\" argument to the rake task' do\n          run_command\n          ENV['debug'].should == 'true'\n        end\n\n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n\n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n\n      describe 'and no --debug or -d argument is specified' do\n        it 'does not make a \"debug\" argument available to the rake task' do\n          run_command\n          ENV['debug'].should.be.nil\n        end\n\n        it 'runs the deploy:now rake task' do\n          @rake.should.receive(:invoke)\n          run_command\n        end\n\n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n\n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n    end\n\n    describe 'and a -t argument is specified' do\n      before do\n        ARGV.push '-t'\n        ARGV.push 'foo'\n        @rake = Rake::Task['deploy:setup']\n        @rake.stub!(:invoke)\n      end\n\n      it 'does not fail' do\n        lambda { run_command }.should.not.raise\n      end\n\n      it 'runs the deploy:setup rake task' do\n        @rake.should.receive(:invoke)\n        run_command\n      end\n\n      it 'makes the specified target available as a \"to\" argument to the rake task' do\n        run_command\n        ENV['to'].should == 'foo'\n      end\n\n      describe 'and a --path argument is specified' do\n        before do\n          ARGV.push '--path=/path/to/foo'\n        end\n        \n        it 'makes the specified path available as a \"path\" argument to the rake task' do\n          run_command\n          ENV['path'].should == '/path/to/foo'\n        end\n      \n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n      \n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n      \n      describe 'and a -p argument is specified' do\n        before do\n          ARGV.push '-p'\n          ARGV.push '/path/to/foo'\n        end\n        \n        it 'makes the specified path available as a \"path\" argument to the rake task' do\n          run_command\n          ENV['path'].should == '/path/to/foo'\n        end\n      \n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n      \n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n      \n      describe 'and no --path or -p argument is specified' do\n        it 'does not make a \"path\" argument available to the rake task' do\n          ENV['path'].should.be.nil\n        end\n      \n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n      \n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n\n      describe 'and a --only argument is specified' do\n        before do\n          @domain = 'smeghost'\n          ARGV.push \"--only=#{@domain}\"\n        end\n\n        it 'makes the specified domain available as an \"only\" argument to the rake task' do\n          run_command\n          ENV['only'].should == @domain\n        end\n\n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n\n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n\n      describe 'and a -o argument is specified' do\n        before do\n          @domain = 'smeghost'\n          ARGV.push '-o'\n          ARGV.push @domain\n        end\n\n        it 'makes the specified domain available as an \"only\" argument to the rake task' do\n          run_command\n          ENV['only'].should == @domain\n        end\n\n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n\n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n\n      describe 'and no --only or -o argument is specified' do\n        it 'does not make an \"only\" argument available to the rake task' do\n          run_command\n          ENV['only'].should.be.nil\n        end\n\n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n\n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n    end\n  end\n  \n  describe \"when the 'deploy' command is specified\" do\n    before do\n      Object.send(:remove_const, :ARGV)\n      ARGV = ['deploy']\n    end  \n\n    describe 'but no target is specified' do\n      it 'does not run rake tasks' do\n        Rake::Application.should.receive(:new).never\n        lambda { run_command }\n      end\n  \n      it 'exits when a target is specified' do\n        lambda { run_command }.should.raise(SystemExit)\n      end\n\n      it 'exits with a failing status when a target is specified' do\n        begin\n          run_command\n        rescue SystemExit => e\n          e.success?.should == false\n        end\n      end\n    end\n    \n    describe 'and a --to argument is specified' do\n      before do\n        ARGV.push '--to=foo'\n        @rake = Rake::Task['deploy:now']\n        @rake.stub!(:invoke)\n      end\n      \n      it 'does not fail' do\n        lambda { run_command }.should.not.raise\n      end\n      \n      it 'runs the deploy:now rake task' do\n        @rake.should.receive(:invoke)\n        run_command\n      end\n      \n      it 'makes the specified target available as a \"to\" argument to the rake task' do\n        run_command\n        ENV['to'].should == 'foo'\n      end\n    \n      describe 'and a --check argument is specified' do\n        before do\n          ARGV.push '--check'\n          @rake = Rake::Task['deploy:now']\n          @rake.stub!(:invoke)\n        end\n           \n        it 'does not fail' do\n          lambda { run_command }.should.not.raise\n        end\n      \n        it 'runs the deploy:now rake task' do\n          @rake.should.receive(:invoke)\n          run_command\n        end\n      \n        it 'makes the specified target available as a \"check\" argument to the rake task' do\n          run_command\n          ENV['check'].should == 'true'\n        end\n      end\n\n      describe 'and a -c argument is specified' do\n        before do\n          ARGV.push '-c'\n          @rake = Rake::Task['deploy:now']\n          @rake.stub!(:invoke)\n        end\n           \n        it 'does not fail' do\n          lambda { run_command }.should.not.raise\n        end\n      \n        it 'runs the deploy:now rake task' do\n          @rake.should.receive(:invoke)\n          run_command\n        end\n      \n        it 'makes the specified target available as a \"check\" argument to the rake task' do\n          run_command\n          ENV['check'].should == 'true'\n        end\n      end\n\n      describe 'and no --check or -c argument is specified' do        \n        it 'does not make a \"check\" argument available to the rake task' do          \n          run_command\n          ENV['check'].should.be.nil\n        end\n      \n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n      \n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n\n      describe 'and a --path argument is specified' do\n        before do\n          ARGV.push '--path=/path/to/foo'\n        end\n        \n        it 'makes the specified path available as a \"path\" argument to the rake task' do\n          run_command\n          ENV['path'].should == '/path/to/foo'\n        end\n      \n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n      \n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n      \n      describe 'and a -p argument is specified' do\n        before do\n          ARGV.push '-p'\n          ARGV.push '/path/to/foo'\n        end\n        \n        it 'makes the specified path available as a \"path\" argument to the rake task' do\n          run_command\n          ENV['path'].should == '/path/to/foo'\n        end\n      \n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n      \n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n      \n      describe 'and no --path or -p argument is specified' do        \n        it 'does not make a \"path\" argument available to the rake task' do\n          run_command\n          ENV['path'].should.be.nil\n        end\n      \n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n      \n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n\n      describe 'and a --only argument is specified' do\n        before do\n          @domain = 'smeghost'\n          ARGV.push \"--only=#{@domain}\"\n        end\n        \n        it 'makes the specified domain available as an \"only\" argument to the rake task' do\n          run_command\n          ENV['only'].should == @domain\n        end\n      \n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n      \n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n      \n      describe 'and a -o argument is specified' do\n        before do\n          @domain = 'smeghost'\n          ARGV.push '-o'\n          ARGV.push @domain\n        end\n        \n        it 'makes the specified domain available as an \"only\" argument to the rake task' do\n          run_command\n          ENV['only'].should == @domain\n        end\n      \n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n      \n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n      \n      describe 'and no --only or -o argument is specified' do\n        it 'does not make an \"only\" argument available to the rake task' do\n          run_command\n          ENV['only'].should.be.nil\n        end\n      \n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n      \n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n    end\n\n    describe 'and a -t argument is specified' do\n      before do\n        ARGV.push '-t'\n        ARGV.push 'foo'\n        @rake = Rake::Task['deploy:now']\n        @rake.stub!(:invoke)\n      end\n\n      it 'does not fail' do\n        lambda { run_command }.should.not.raise\n      end\n\n      it 'runs the deploy:now rake task' do\n        @rake.should.receive(:invoke)\n        run_command\n      end\n\n      it 'makes the specified target available as a \"to\" argument to the rake task' do\n        run_command\n        ENV['to'].should == 'foo'\n      end\n  \n      describe 'and a --check argument is specified' do\n        before do\n          ARGV.push '--check'\n          @rake = Rake::Task['deploy:now']\n          @rake.stub!(:invoke)\n        end\n         \n        it 'does not fail' do\n          lambda { run_command }.should.not.raise\n        end\n    \n        it 'runs the deploy:now rake task' do\n          @rake.should.receive(:invoke)\n          run_command\n        end\n    \n        it 'makes the specified target available as a \"check\" argument to the rake task' do\n          run_command\n          ENV['check'].should == 'true'\n        end\n      end\n\n      describe 'and a -c argument is specified' do\n        before do\n          ARGV.push '-c'\n          @rake = Rake::Task['deploy:now']\n          @rake.stub!(:invoke)\n        end\n         \n        it 'does not fail' do\n          lambda { run_command }.should.not.raise\n        end\n    \n        it 'runs the deploy:now rake task' do\n          @rake.should.receive(:invoke)\n          run_command\n        end\n    \n        it 'makes the specified target available as a \"check\" argument to the rake task' do\n          run_command\n          ENV['check'].should == 'true'\n        end\n      end\n\n      describe 'and no --check or -c argument is specified' do        \n        it 'does not make a \"check\" argument available to the rake task' do          \n          run_command\n          ENV['check'].should.be.nil\n        end\n      \n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n      \n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n\n      describe 'and a --path argument is specified' do\n        before do\n          ARGV.push '--path=/path/to/foo'\n        end\n        \n        it 'makes the specified path available as a \"path\" argument to the rake task' do\n          run_command\n          ENV['path'].should == '/path/to/foo'\n        end\n      \n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n      \n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n      \n      describe 'and a -p argument is specified' do\n        before do\n          ARGV.push '-p'\n          ARGV.push '/path/to/foo'\n        end\n        \n        it 'makes the specified path available as a \"path\" argument to the rake task' do\n          run_command\n          ENV['path'].should == '/path/to/foo'\n        end\n      \n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n      \n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n      \n      describe 'and no --path or -p argument is specified' do\n        it 'does not make a \"path\" argument available to the rake task' do\n          ENV['path'].should.be.nil\n        end\n      \n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n      \n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n          \n      describe 'and a --only argument is specified' do\n        before do\n          @domain = 'smeghost'\n          ARGV.push \"--only=#{@domain}\"\n        end\n        \n        it 'makes the specified domain available as an \"only\" argument to the rake task' do\n          run_command\n          ENV['only'].should == @domain\n        end\n      \n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n      \n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n      \n      describe 'and a -o argument is specified' do\n        before do\n          @domain = 'smeghost'\n          ARGV.push '-o'\n          ARGV.push @domain\n        end\n        \n        it 'makes the specified domain available as an \"only\" argument to the rake task' do\n          run_command\n          ENV['only'].should == @domain\n        end\n      \n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n      \n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n      \n      describe 'and no --only or -o argument is specified' do\n        it 'does not make an \"only\" argument available to the rake task' do\n          run_command\n          ENV['only'].should.be.nil\n        end\n      \n        it 'fails if the rake task fails' do\n          @rake.stub!(:invoke).and_raise(RuntimeError)\n          lambda { run_command }.should.raise\n        end\n      \n        it 'does not fail if the rake task succeeds' do\n          @rake.stub!(:invoke).and_return(true)\n          lambda { run_command }.should.not.raise\n        end\n      end\n    end\n  end\n  \n  describe 'and more than one command is specified' do\n    before do\n      Object.send(:remove_const, :ARGV)\n      ARGV = ['frazzlebazzle', 'shizzlebizzle']\n    end\n    \n    describe 'when no target is specified' do\n      it 'exits when a target is specified' do\n        lambda { run_command }.should.raise(SystemExit)\n      end\n\n      it 'exits with a failing status when a target is specified' do\n        begin\n          run_command\n        rescue SystemExit => e\n          e.success?.should == false\n        end\n      end\n    end\n\n    describe 'when a target is specified' do\n      before do\n        ARGV.push('--to=foo')        \n      end\n      \n      it 'exits when a target is specified' do\n        lambda { run_command }.should.raise(SystemExit)\n      end\n\n      it 'exits with a failing status when a target is specified' do\n        begin\n          run_command\n        rescue SystemExit => e\n          e.success?.should == false\n        end\n      end\n    end\n  end\n  \n  describe 'and an unknown command is specified' do\n    before do\n      Object.send(:remove_const, :ARGV)\n      ARGV = ['frazzlebazzle']\n    end\n    \n    describe 'when no target is specified' do\n      it 'exits when a target is specified' do\n        lambda { run_command }.should.raise(SystemExit)\n      end\n\n      it 'exits with a failing status when a target is specified' do\n        begin\n          run_command\n        rescue SystemExit => e\n          e.success?.should == false\n        end\n      end\n    end\n\n    describe 'when a target is specified' do\n      before do\n        ARGV.push('--to=foo')        \n      end\n      \n      it 'exits when a target is specified' do\n        lambda { run_command }.should.raise(SystemExit)\n      end\n\n      it 'exits with a failing status when a target is specified' do\n        begin\n          run_command\n        rescue SystemExit => e\n          e.success?.should == false\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "spec/wd_role_command_spec.rb",
    "content": "require_relative 'spec_helper.rb'\n\ndef run_command\n  eval File.read(File.join(File.dirname(__FILE__), *%w[.. bin wd_role]))\nend\n\ndescribe 'wd role command' do\n  before do\n    ENV['WD_ROLES'] = nil\n  end\n  \n  describe 'when no command-line arguments are specified' do\n    before do\n      Object.send(:remove_const, :ARGV)\n      ARGV = []\n    end  \n    \n    it 'fails' do\n      lambda { run_command }.should.raise(SystemExit)\n    end\n  end\n  \n  describe \"when a role is specified on the command-line\" do\n    before do\n      Object.send(:remove_const, :ARGV)\n      ARGV = ['app']\n    end  \n\n    it 'fails when no WD_ROLES environment setting is present' do\n      ENV['WD_ROLES'] = nil\n      lambda { run_command }.should.raise(SystemExit)\n    end\n    \n    it 'fails when an empty WD_ROLES environment setting is present' do\n      ENV['WD_ROLES'] = ''\n      lambda { run_command }.should.raise(SystemExit)\n    end\n    \n    it 'fails when the WD_ROLES environment setting does not contain that role' do\n      ENV['WD_ROLES'] = 'web:nonapp:db'\n      lambda { run_command }.should.raise(SystemExit)\n    end\n    \n    it 'succeeds when the WD_ROLES environment setting contains that role' do\n      ENV['WD_ROLES'] = 'web:app:db'\n      lambda { run_command }.should.not.raise\n    end    \n  end\nend\n"
  },
  {
    "path": "spec/whiskey_disk/config/filter_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper.rb'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'lib', 'whiskey_disk', 'config'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'lib', 'whiskey_disk', 'config', 'filter'))\n\ndescribe WhiskeyDisk::Config::Filter, 'filtering configuration data' do\n  before do\n    ENV['to'] = @env = 'foo:erl'\n\n    @config = WhiskeyDisk::Config.new\n    @filter = WhiskeyDisk::Config::Filter.new(@config)\n\n    @data = {\n      'foo' => { \n        'xyz' => { 'repository' => 'x' },\n        'eee' => { 'repository' => 'x', 'domain' => '' },\n        'abc' => { 'repository' => 'x', 'domain' => 'what@example.com' },\n        'baz' => { 'repository' => 'x', 'domain' => [ 'bar@example.com', 'baz@domain.com' ]},\n        'bar' => { 'repository' => 'x', 'domain' => [ 'user@example.com', nil, 'foo@domain.com' ]},\n        'bat' => { 'repository' => 'x', 'domain' => [ 'user@example.com', 'foo@domain.com', '' ]},\n        'hsh' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com' }, { 'name' => 'baz@domain.com' } ]},\n        'mix' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com' }, 'baz@domain.com' ]},            \n        'erl' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com', \n                                                        'roles' => nil,\n                                                        'ssh_options' => ['-t', '-v' ] }, \n                                                      { 'name' => 'baz@domain.com', \n                                                        'ssh_options' => '-t',\n                                                        'roles' => '' },\n                                                      { 'name' => 'aok@domain.com', \n                                                        'ssh_options' => [], \n                                                        'roles' => [] } ]},\n        'rol' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com', 'roles' => [ 'web', 'db' ] }, \n                                                      { 'name' => 'baz@domain.com', 'roles' => [ 'db' ] },            \n                                                      { 'name' => 'aok@domain.com', 'roles' => 'app' } ]},            \n        'wow' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com', 'roles' => [ 'web', 'db' ] }, \n                                                      { 'name' => 'baz@domain.com', 'roles' => [ 'db' ] },   \n                                                        '', 'foo@bar.example.com',      \n                                                      { 'name' => 'aok@domain.com', 'roles' => 'app' } ]},            \n      },\n\n      'zyx' => {\n        'xyz' => { 'repository' => 'x' },\n        'eee' => { 'repository' => 'x', 'domain' => '' },\n        'abc' => { 'repository' => 'x', 'domain' => 'what@example.com' },\n        'hij' => { 'repository' => 'x', 'domain' => [ 'bar@example.com', 'baz@domain.com' ]},\n        'def' => { 'repository' => 'x', 'domain' => [ 'user@example.com', nil, 'foo@domain.com' ]},\n        'dex' => { 'repository' => 'x', 'domain' => [ 'user@example.com', 'foo@domain.com', '' ]},\n        'hsh' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com' }, { 'name' => 'baz@domain.com' } ]},\n        'mix' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com' }, 'baz@domain.com' ]},\n        'erl' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com', 'roles' => nil }, \n                                                      { 'name' => 'baz@domain.com', 'roles' => '' },\n                                                      { 'name' => 'aok@domain.com', 'roles' => [] } ]},\n        'rol' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com', 'roles' => [ 'web', 'db' ] }, \n                                                      { 'name' => 'baz@domain.com', 'roles' => [ 'db' ] },         \n                                                      { 'name' => 'aok@domain.com', 'roles' => 'app' } ]},            \n        'wow' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com', 'roles' => [ 'web', 'db' ] }, \n                                                      { 'name' => 'baz@domain.com', 'roles' => [ 'db' ] },   \n                                                         '', 'foo@bar.example.com',      \n                                                      { 'name' => 'aok@domain.com', 'roles' => 'app' } ]},            \n      }\n    }\n  end\n  \n  it 'should apply all available filters' do\n    @filter.filter_data(@data).should == {\n      'repository'    => \"x\", \n      'project'       => \"foo\", \n      'config_target' => \"erl\", \n      'environment'   => \"erl\",\n      'domain'        => [ \n        { 'name' => \"bar@example.com\", 'ssh_options' => [ '-t', '-v' ] }, \n        { 'name' => \"baz@domain.com\", 'ssh_options' => [ '-t' ] }, \n        { 'name' => \"aok@domain.com\" }\n      ]\n    }\n  end\nend\n\n"
  },
  {
    "path": "spec/whiskey_disk/config/filters/add_environment_name_filter_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper.rb'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config', 'filters', 'add_environment_name_filter'))\n\ndescribe 'filtering configuration data by adding the environment name' do\n  before do\n    @config = WhiskeyDisk::Config.new\n    @filter = WhiskeyDisk::Config::AddEnvironmentNameFilter.new(@config)\n    \n    ENV['to'] = 'project:environment'\n  end\n  \n  it 'adds an environment value when none is present' do\n    @filter.filter('foo' => 'bar').should == { 'environment' => 'environment', 'foo' => 'bar' }\n  end\n  \n  it 'overwrites an environment value when one is present' do\n    @filter.filter('environment' => 'baz', 'foo' => 'bar').should == { 'environment' => 'environment', 'foo' => 'bar' }      \n  end\nend\n"
  },
  {
    "path": "spec/whiskey_disk/config/filters/add_project_name_filter_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper.rb'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config', 'filters', 'add_project_name_filter'))\n\ndescribe 'filtering configuration data by adding the project name' do\n  before do\n    @config = WhiskeyDisk::Config.new\n    @filter = WhiskeyDisk::Config::AddProjectNameFilter.new(@config)\n    ENV['to'] = 'project:environment'\n  end\n  \n  it 'adds an environment value when none is present' do\n    @filter.filter('foo' => 'bar').should == { 'project' => 'project', 'foo' => 'bar' }\n  end\n  \n  it 'overwrites an environment value when one is present' do\n    @filter.filter('project' => 'baz', 'foo' => 'bar').should == { 'project' => 'project', 'foo' => 'bar' }      \n  end  \nend"
  },
  {
    "path": "spec/whiskey_disk/config/filters/check_for_duplicate_domains_filter_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper.rb'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config', 'filters', 'check_for_duplicate_domains_filter'))\n\ndescribe 'filtering configuration data by normalizing domains' do\n  before do\n    @config = WhiskeyDisk::Config.new\n    @filter = WhiskeyDisk::Config::CheckForDuplicateDomainsFilter.new(@config)\n  end\n  \n  it 'should return the suuplied data if no domains appear more than once in a target' do\n    @data = { \n      'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com', 'roles' => nil }, \n                                         { 'name' => 'baz@domain.com',  'roles' => '' } ]\n    }\n    \n    @filter.filter(@data).should == @data\n  end\n  \n  it 'raises an exception if a domain appears more than once in a target' do\n    @data = { \n      'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com', 'roles' => nil }, \n                                         { 'name' => 'baz@domain.com',  'roles' => '' },\n                                         { 'name' => 'bar@example.com', 'roles' => [] } ]\n    }\n    \n    lambda { @filter.filter(@data) }.should.raise\n  end\nend"
  },
  {
    "path": "spec/whiskey_disk/config/filters/convert_role_strings_to_list_filter_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper.rb'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config', 'filters', 'convert_role_strings_to_list_filter'))\n\ndescribe 'converting domain role strings into lists' do\n  before do\n    @config = WhiskeyDisk::Config.new\n    @filter = WhiskeyDisk::Config::ConvertRoleStringsToListFilter.new(@config)\n  end\n  \n  it 'handles single strings' do\n    @data = {\n      'domain' => [\n        { 'name' => 'foo', 'roles' => 'baz' },\n        { 'name' => 'bar', 'roles' => 'xyzzy' },\n      ]\n    }\n    \n    @filter.filter(@data).should == {      \n      'domain' => [\n        { 'name' => 'foo', 'roles' => [ 'baz' ] },\n        { 'name' => 'bar', 'roles' => [ 'xyzzy' ] },\n      ]\n    }\n  end\n  \n  it 'does not touch domains without roles' do\n    @data = {\n      'domain' => [\n        { 'name' => 'foo' },\n        { 'name' => 'bar' }\n      ]\n    }\n    \n    @filter.filter(@data).should == @data  \n  end\n  \n  it 'leaves existing role lists alone' do\n    @data = {\n      'domain' => [\n        { 'name' => 'foo', 'roles' => [ 'baz' ] },\n        { 'name' => 'bar', 'roles' => [ 'xyzzy', 'quux' ] },\n      ]\n    }\n    \n    @filter.filter(@data).should == @data\n  end\nend"
  },
  {
    "path": "spec/whiskey_disk/config/filters/default_config_target_filter_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper.rb'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config', 'filters', 'default_config_target_filter'))\n\ndescribe 'filtering configuration data by defaulting the config target' do\n  before do\n    @config = WhiskeyDisk::Config.new\n    @filter = WhiskeyDisk::Config::DefaultConfigTargetFilter.new(@config)\n    ENV['to'] = 'project:environment'\n  end\n  \n  it 'adds a config_target value set to the environment name when none is present' do\n    @filter.filter('foo' => 'bar').should == { 'config_target' => 'environment', 'foo' => 'bar' }\n  end\n  \n  it 'preserves the existing config_target when one is present' do\n    @filter.filter('config_target' => 'baz', 'foo' => 'bar').should == { 'config_target' => 'baz', 'foo' => 'bar' }      \n  end    \nend\n"
  },
  {
    "path": "spec/whiskey_disk/config/filters/default_domain_filter_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper.rb'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config', 'filters', 'default_domain_filter'))\n\ndescribe 'setting empty domain entries to \"local\"' do\n  before do\n    @config = WhiskeyDisk::Config.new\n    @filter = WhiskeyDisk::Config::DefaultDomainFilter.new(@config)\n  end\n  \n  it 'leaves data intact if it has a domain' do\n    @filter.filter({ 'domain' => 'anything' }).should == { 'domain' => 'anything' }\n  end\n\n  it 'adds a local domain entry if data does not have a domain' do\n    @filter.filter({}).should == { 'domain' => [{ 'name' => 'local' }] }\n  end\nend"
  },
  {
    "path": "spec/whiskey_disk/config/filters/drop_empty_domain_roles_filter_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper.rb'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config', 'filters', 'drop_empty_domain_roles_filter'))\n\ndescribe 'converting domain role strings into lists' do\n  before do\n    @config = WhiskeyDisk::Config.new\n    @filter = WhiskeyDisk::Config::DropEmptyDomainRolesFilter.new(@config)\n  end\n  \n  it 'drops roles with nil values' do\n    @data = {\n      'domain' => [\n        { 'name' => 'foo', 'roles' => nil },\n        { 'name' => 'bar', 'roles' => nil }\n      ]\n    }\n    \n    @filter.filter(@data).should == {\n      'domain' => [\n        { 'name' => 'foo' },\n        { 'name' => 'bar' }\n      ]\n    }\n  end\n  \n  it 'drops roles with empty list values' do\n    @data = {\n      'domain' => [\n        { 'name' => 'foo', 'roles' => [] },\n        { 'name' => 'bar', 'roles' => [] }\n      ]\n    }\n    \n    @filter.filter(@data).should == {\n      'domain' => [\n        { 'name' => 'foo' },\n        { 'name' => 'bar' }\n      ]\n    }    \n  end\n  \n  it 'preserves non-empty roles' do\n    @data = {\n      'domain' => [\n        { 'name' => 'foo', 'roles' => nil },\n        { 'name' => 'bar', 'roles' => [] },\n        { 'name' => 'baz', 'roles' => [ 'x', 'y', 'z' ] }\n      ]\n    }\n    \n    @filter.filter(@data).should == {\n      'domain' => [\n        { 'name' => 'foo' },\n        { 'name' => 'bar' },\n        { 'name' => 'baz', 'roles' => [ 'x', 'y', 'z' ] }\n      ]\n    }\n  end\nend"
  },
  {
    "path": "spec/whiskey_disk/config/filters/environment_scope_filter_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper.rb'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config', 'filters', 'environment_scope_filter'))\n\ndescribe 'filtering configuration data by adding environment scoping' do\n  before do\n    ENV['to'] = @env = 'foo:staging'\n\n    @config = WhiskeyDisk::Config.new\n    @filter = WhiskeyDisk::Config::EnvironmentScopeFilter.new(@config)\n\n    @bare_data  = { 'repository' => 'git://foo/bar.git', 'domain' => [ { :name => 'ogc@ogtastic.com' } ] }\n    @env_data   = { 'staging' => @bare_data }\n    @proj_data  = { 'foo' => @env_data }\n  end\n\n  it 'fails if the configuration data is not a hash' do\n    lambda { @filter.filter([]) }.should.raise\n  end\n\n  it 'returns the original data if it has both project and environment scoping' do\n    @filter.filter(@proj_data).should == @proj_data\n  end\n\n  it 'returns the original data if it has environment scoping' do\n    @filter.filter(@env_data).should == @env_data\n  end\n\n  it 'returns the data wrapped in an environment scope if it has no environment scoping' do\n    @filter.filter(@bare_data).should == { 'staging' => @bare_data }\n  end\nend"
  },
  {
    "path": "spec/whiskey_disk/config/filters/hashify_domain_entries_filter_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper.rb'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config', 'filters', 'hashify_domain_entries_filter'))\n\ndescribe 'setting empty domain entries to \"local\"' do\n  before do\n    @config = WhiskeyDisk::Config.new\n    @filter = WhiskeyDisk::Config::HashifyDomainEntriesFilter.new(@config)\n  end\n\n  it 'handles empty domain filtering among roles across all projects and targets' do\n    @data = {\n      'domain' => [\n        'x', \n        nil, \n        { 'name' => 'foo', 'roles' => ['x', 'y'] },\n        '', \n        'local'\n      ]\n    }\n    \n    @filter.filter(@data).should == {\n      'domain' => [\n        { 'name' => 'x' },\n        { 'name' => nil },\n        { 'name' => 'foo', 'roles' => ['x', 'y'] },\n        { 'name' => '' },\n        { 'name' => 'local' }\n      ]\n    }\n  end\n  \n  it 'handles the degenerate case of a single domain name' do\n    @data = { 'domain' => 'foo' }\n    @filter.filter(@data).should == { 'domain' => [ { 'name' => 'foo' } ] }\n  end\n  \n  it 'handles the degenerate case of no domain specified' do\n    @filter.filter({}).should == { 'domain' => { 'name' => '' } }\n  end\nend"
  },
  {
    "path": "spec/whiskey_disk/config/filters/localize_domains_filter_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper.rb'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config', 'filters', 'localize_domains_filter'))\n\ndescribe 'setting empty domain entries to \"local\"' do\n  before do\n    @config = WhiskeyDisk::Config.new\n    @filter = WhiskeyDisk::Config::LocalizeDomainsFilter.new(@config)\n  end\n\n  it 'handles empty domain filtering among roles across all projects and targets' do\n    @data = {\n      'domain' => [\n        { 'name' => nil },\n        { 'name' => '' },\n        { 'name' => 'local' },\n        { 'name' => 'x' }\n      ]\n    }\n    \n    @filter.filter(@data).should == {\n      'domain' => [\n        { 'name' => 'local' },\n        { 'name' => 'local' },\n        { 'name' => 'local' },\n        { 'name' => 'x' }\n      ]\n    }\n  end\nend"
  },
  {
    "path": "spec/whiskey_disk/config/filters/normalize_ssh_options_filter_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper.rb'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config', 'filters', 'normalize_ssh_options_filter'))\n\ndescribe 'normalizing SSH options' do\n  before do\n    @config = WhiskeyDisk::Config.new\n    @filter = WhiskeyDisk::Config::NormalizeSshOptionsFilter.new(@config)\n  end\n    \n  it 'eliminates ssh options with nil, or empty values' do\n    @data = {\n      'domain' => [\n        { 'name' => 'foo', 'ssh_options' => nil },\n        { 'name' => 'bar', 'ssh_options' => '' },\n        { 'name' => 'baz', 'ssh_options' => [] },\n        { 'name' => 'xyzzy', 'ssh_options' => ['', ''] },\n        { 'name' => 'quux', 'ssh_options' => [nil, '', nil] },\n      ]\n    }\n    \n    @filter.filter(@data).should == {\n      'domain' => [\n        { 'name' => 'foo' },\n        { 'name' => 'bar' },\n        { 'name' => 'baz' },\n        { 'name' => 'xyzzy' },\n        { 'name' => 'quux' }\n      ]\n    }\n  end\n  \n  it 'preserves non-empty ssh options' do\n    @data = {\n      'domain' => [\n        { 'name' => 'foo', 'ssh_options' => nil },\n        { 'name' => 'bar', 'ssh_options' => 'c' },\n        { 'name' => 'baz', 'ssh_options' => [] },\n        { 'name' => 'xyzzy', 'ssh_options' => ['', 'c'] },\n        { 'name' => 'quux', 'ssh_options' => [nil, '', 'a', nil, 'b' ] },\n        { 'name' => 'wut', 'ssh_options' => [nil, '', 'x', 'a', 'a', nil, 'b' ] },\n      ]\n    }\n    \n    @filter.filter(@data).should == {\n      'domain' => [\n        { 'name' => 'foo' },\n        { 'name' => 'bar', 'ssh_options' => [ 'c' ] },\n        { 'name' => 'baz' },\n        { 'name' => 'xyzzy', 'ssh_options' => [ 'c' ] },\n        { 'name' => 'quux', 'ssh_options' => [ 'a', 'b' ] },\n        { 'name' => 'wut', 'ssh_options' => [ 'x', 'a', 'a', 'b' ] }\n      ]\n    }\n  end\nend"
  },
  {
    "path": "spec/whiskey_disk/config/filters/project_scope_filter_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper.rb'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config', 'filters', 'project_scope_filter'))\n\ndescribe 'filtering configuration data by adding project scoping' do\n  before do\n    ENV['to'] = @env = 'foo:staging'\n\n    @config = WhiskeyDisk::Config.new\n    @filter = WhiskeyDisk::Config::ProjectScopeFilter.new(@config)\n\n    @bare_data  = { 'staging' => { 'repository' => 'git://foo/bar.git', 'domain' => [ { :name => 'ogc@ogtastic.com' } ] } }\n    @proj_data  = { 'foo' => @bare_data }\n  end\n\n  it 'fails if the configuration data is not a hash' do\n    lambda { @filter.filter([]) }.should.raise\n  end\n\n  describe 'when no project name is specified via ENV[\"to\"]' do\n    before do\n      ENV['to'] = @env = 'staging'\n    end\n\n    it 'returns the original data if it has both project and environment scoping' do\n      @filter.filter(@proj_data).should == @proj_data\n    end\n\n    describe 'when no project name is specified in the bare config hash' do\n      it 'returns the original data wrapped in project scope, using a dummy project, if it has environment scoping but no project scoping' do\n        @filter.filter(@bare_data).should == { 'unnamed_project' => @bare_data }\n      end\n    end\n\n    describe 'when a project name is specified in the bare config hash' do\n      before do\n        @bare_data['staging']['project'] = 'whiskey_disk'\n      end\n\n      it 'returns the original data wrapped in project scope if it has environment scoping but no project scoping' do\n        @filter.filter(@bare_data).should == { 'whiskey_disk' => @bare_data }\n      end\n    end\n  end\n\n  describe 'when a project name is specified via ENV[\"to\"]' do\n    before do\n      ENV['to'] = @env = 'whiskey_disk:staging'\n    end\n  \n    describe 'when a project name is not specified in the bare config hash' do\n      it 'returns the original data if it has both project and environment scoping' do\n        @filter.filter(@proj_data).should == @proj_data\n      end\n  \n      it 'returns the original data wrapped in project scope if it has environment scoping but no project scoping' do\n        @filter.filter(@bare_data).should == { 'whiskey_disk' => @bare_data }\n      end\n    end\n  \n    describe 'when a project name is specified in the bare config hash' do\n      before do\n        @bare_data['staging']['project'] = 'whiskey_disk'\n      end\n  \n      it 'returns the original data if it has both project and environment scoping' do\n        @filter.filter(@proj_data).should == @proj_data\n      end\n  \n      it 'returns the original data wrapped in project scope if it has environment scoping but no project scoping' do\n        @filter.filter(@bare_data).should == { 'whiskey_disk' => @bare_data }\n      end\n    end\n  end \nend\n"
  },
  {
    "path": "spec/whiskey_disk/config/filters/select_project_and_environment_filter_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper.rb'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config', 'filters', 'select_project_and_environment_filter'))\n\ndescribe 'filtering configuration data by selecting the data for the project and environment' do\n  before do\n    @config = WhiskeyDisk::Config.new\n    @filter = WhiskeyDisk::Config::SelectProjectAndEnvironmentFilter.new(@config)\n    \n    @data = { \n      'project' => { 'environment' => { 'a' => 'b' } },\n      'other'   => { 'missing' => { 'c' => 'd' } },\n    }\n  end\n  \n  it 'fails when the specified project cannot be found' do\n    ENV['to'] = @env = 'something:environment'\n    lambda { @filter.filter(@data) }.should.raise\n  end\n\n  it 'fails when the specified environment cannot be found for the specified project' do\n    ENV['to'] = @env = 'other:environment'\n    lambda { @filter.filter(@data) }.should.raise\n  end\n\n  it 'returns only the data for the specified project and environment' do\n    ENV['to'] = @env = 'project:environment'\n    @filter.filter(@data).should == @data['project']['environment']\n  end\nend"
  },
  {
    "path": "spec/whiskey_disk/config/filters/stringify_hash_keys_filter_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper.rb'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib', 'whiskey_disk', 'config', 'filters', 'stringify_hash_keys_filter'))\n\ndescribe 'filtering configuration data to only have symbol hash keys' do\n  before do\n    @config = WhiskeyDisk::Config.new\n    @filter = WhiskeyDisk::Config::StringifyHashKeysFilter.new(@config)\n    @data = { \n      'a' => {\n        :x => 'y',\n        'c' => 'd',\n        :e => {\n          'f' => ['a', 'b', 'c']\n        }\n      },\n      :b => [ '1', '2', '3' ]\n    }\n  end\n  \n  it 'recursively stringifies hash keys in the provided data structure' do\n    @filter.filter(@data).should == {\n      'a' => {\n        'x' => 'y',\n        'c' => 'd',\n        'e' => {\n          'f' => [ 'a', 'b', 'c' ]\n        }\n      },\n      'b' => [ '1', '2', '3' ]\n    }\n  end\n  \n  it 'clones value data so that the original data structure is not shared' do\n    original = @data.clone\n    result = @filter.filter(@data)\n    result['a']['e']['f'] << 'd'\n    @data.should == original\n  end\nend"
  },
  {
    "path": "spec/whiskey_disk/config_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper.rb'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'whiskey_disk', 'config'))\nrequire 'yaml'\nrequire 'tmpdir'\nrequire 'fileutils'\n\n# create a file at the specified path\ndef make(path)\n  FileUtils.mkdir_p(File.dirname(path))\n  FileUtils.touch(path)\nend\n\ndef build_temp_dir\n  return Dir.mktmpdir(nil, '/private/tmp') if File.exists?('/private/tmp')\n  Dir.mktmpdir\nend\n\ndef write_config_file(data)\n  File.open(@config_file, 'w') { |f| f.puts YAML.dump(data) }\nend\n\n# class for testing .open calls -- for use with URL config paths\nclass TestURLConfig < WhiskeyDisk::Config\n  def set_response(data)\n    @fake_response = YAML.dump(data)\n  end\n\n  def open(path)\n    @fake_response || raise\n  end\nend\n\ndescribe WhiskeyDisk::Config do\n  before do\n    @config = WhiskeyDisk::Config.new\n  end\n  \n  describe 'when computing the environment name' do\n    it 'returns false when there is no ENV[\"to\"] setting' do\n      ENV['to'] = nil\n      @config.environment_name.should == false\n    end\n\n    it 'returns false when the ENV[\"to\"] setting is blank' do\n      ENV['to'] = ''\n      @config.environment_name.should == false\n    end\n\n    it 'returns the ENV[\"to\"] setting when it is non-blank' do\n      ENV['to'] = 'staging'\n      @config.environment_name.should == 'staging'\n    end\n\n    it 'returns the environment portion of the ENV[\"to\"] setting when a project is specified' do\n      ENV['to'] = 'project:staging'\n      @config.environment_name.should == 'staging'\n    end\n  end\n\n  describe 'when determining whether to do a staleness check before updating' do\n    it 'returns false when there is no ENV[\"check\"] setting' do\n      ENV['check'] = nil\n      @config.check_staleness?.should == false\n    end\n\n    it 'returns false when the ENV[\"check\"] setting is blank' do\n      ENV['check'] = ''\n      @config.check_staleness?.should == false\n    end\n\n    it 'returns true if the ENV[\"check\"] setting is \"t\"' do\n      ENV['check'] = 't'\n      @config.check_staleness?.should == true\n    end\n\n    it 'returns true if the ENV[\"check\"] setting is \"true\"' do\n      ENV['check'] = 'true'\n      @config.check_staleness?.should == true\n    end\n\n    it 'returns true if the ENV[\"check\"] setting is \"y\"' do\n      ENV['check'] = 'y'\n      @config.check_staleness?.should == true\n    end\n\n    it 'returns true if the ENV[\"check\"] setting is \"yes\"' do\n      ENV['check'] = 'yes'\n      @config.check_staleness?.should == true\n    end\n\n    it 'returns true if the ENV[\"check\"] setting is \"1\"' do\n      ENV['check'] = '1'\n      @config.check_staleness?.should == true\n    end\n  end\n  \n  describe 'when determining whether there is a domain limit set' do\n    it 'returns false when ENV[\"only\"] is nil' do\n      ENV['only'] = nil\n      @config.domain_limit.should == false\n    end\n    \n    it 'returns false when ENV[\"only\"] is empty' do\n      ENV['only'] = ''\n      @config.domain_limit.should == false\n    end\n    \n    it 'returns the value in ENV[\"only\"] when it is non-empty' do\n      ENV['only'] = 'somedomain'\n      @config.domain_limit.should == 'somedomain'      \n    end\n  end\n\n  describe 'when determining whether to turn debug mode on' do\n    it 'returns false when there is no ENV[\"debug\"] setting' do\n      ENV['debug'] = nil\n      @config.debug?.should == false\n    end\n\n    it 'returns false when the ENV[\"debug\"] setting is blank' do\n      ENV['debug'] = ''\n      @config.debug?.should == false\n    end\n\n    it 'returns true if the ENV[\"debug\"] setting is \"t\"' do\n      ENV['debug'] = 't'\n      @config.debug?.should == true\n    end\n\n    it 'returns true if the ENV[\"debug\"] setting is \"true\"' do\n      ENV['debug'] = 'true'\n      @config.debug?.should == true\n    end\n\n    it 'returns true if the ENV[\"debug\"] setting is \"y\"' do\n      ENV['debug'] = 'y'\n      @config.debug?.should == true\n    end\n\n    it 'returns true if the ENV[\"debug\"] setting is \"yes\"' do\n      ENV['debug'] = 'yes'\n      @config.debug?.should == true\n    end\n\n    it 'returns true if the ENV[\"debug\"] setting is \"1\"' do\n      ENV['debug'] = '1'\n      @config.debug?.should == true\n    end\n  end\n\n  describe 'when fetching configuration' do\n    describe 'and path specified is an URL' do\n      before do\n        ENV['to'] = @env = 'foo:staging'\n        ENV['path'] = 'https://www.example.com/foo/bar/deploy.yml'\n        @config = TestURLConfig.new\n      end\n      \n      it 'fails if the current environment cannot be determined' do\n        ENV['to'] = nil\n        lambda { @config.fetch }.should.raise\n      end\n\n      it 'fails if the configuration data cannot be retrieved' do\n        @config.stub!(:open).and_raise(RuntimeError)\n        lambda { @config.fetch }.should.raise\n      end\n\n      it 'fails if the retrieved configuration data is invalid' do\n        @config.stub!(:open).and_return(\"}\")\n        lambda { @config.fetch }.should.raise\n      end\n\n      it 'fails if the retrieved configuration data does not define data for this environment' do\n        @config.set_response('foo' => { 'production' => { 'a' => 'b'} })\n        lambda { @config.fetch }.should.raise\n      end\n\n      it 'returns the retrieved configuration yaml data for this environment as a hash' do\n        staging = { 'foo' => 'bar', 'repository' => 'xyzzy' }\n        @config.set_response('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })\n        result = @config.fetch\n        staging.each_pair do |k,v|\n          result[k].should == v\n        end\n      end\n    \n      it 'does not include configuration information for other environments in the returned hash' do\n        staging = { 'foo' => 'bar', 'baz' => 'xyzzy' }\n        @config.set_response('production' => { 'repository' => 'c', 'a' => 'b'}, 'staging' => staging)\n        @config.fetch['a'].should.be.nil\n      end\n\n      it 'includes the environment in the hash' do\n        staging = { 'foo' => 'bar', 'baz' => 'xyzzy' }\n        @config.set_response('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })\n        @config.fetch['environment'].should == 'staging'\n      end\n\n      it 'does not allow overriding the environment in the configuration file' do\n        staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'environment' => 'production' }\n        @config.set_response('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })\n        @config.fetch['environment'].should == 'staging'\n      end\n\n      it 'includes the project handle in the hash' do\n        staging = { 'foo' => 'bar', 'repository' => 'xyzzy' }\n        @config.set_response('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })\n        @config.fetch['project'].should == 'foo'\n      end\n\n      it 'does not allow overriding the project handle in the configuration file when a project root is specified' do\n        staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'project' => 'diskey_whisk' }\n        @config.set_response('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })\n        @config.fetch['project'].should == 'foo'\n      end\n\n      it 'allows overriding the project handle in the configuration file when a project root is not specified' do\n        ENV['to'] = @env = 'staging'\n        staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'project' => 'diskey_whisk' }\n        @config.set_response('production' => { 'repository' => 'b'}, 'staging' => staging)\n        @config.fetch['project'].should == 'diskey_whisk'\n      end\n    \n      it 'includes the environment name as the config_target setting when no config_target is specified' do\n        staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'project' => 'diskey_whisk' }\n        @config.set_response('production' => { 'repository' => 'b'}, 'staging' => staging)\n        @config.fetch['config_target'].should == 'staging'\n      end\n    \n      it 'includes the config_target setting when a config_target is specified' do\n        staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'project' => 'diskey_whisk', 'config_target' => 'testing' }\n        @config.set_response('production' => { 'repository' => 'b'}, 'staging' => staging)\n        @config.fetch['config_target'].should == 'testing'\n      end\n      \n      it 'fails if the named target cannot be found' do\n        ENV['to'] = @env = 'bogus:thing'\n        lambda { @config.fetch }.should.raise\n      end\n    end\n    \n    describe 'and path specified is not an URL' do\n      before do\n        ENV['to'] = @env = 'foo:staging'\n        @path = build_temp_dir\n        ENV['path'] = @config_file = File.join(@path, 'deploy.yml')\n      end\n\n      after do\n        FileUtils.rm_rf(@path)\n      end\n      \n      it 'fails if the current environment cannot be determined' do\n        ENV['to'] = nil\n        lambda { @config.fetch }.should.raise\n      end\n\n      it 'fails if the configuration file does not exist' do\n        lambda { @config.fetch }.should.raise\n      end\n\n      it 'fails if the configuration file cannot be read' do\n        Dir.mkdir(File.join(@path, 'tmp'))\n        lambda { @config.fetch }.should.raise\n      end\n\n      it 'fails if the configuration file is invalid' do\n        File.open(@config_file, 'w') {|f| f.puts \"}\" }\n        lambda { @config.fetch }.should.raise\n      end\n\n      it 'fails if the configuration file does not define data for this environment' do\n        write_config_file('foo' => { 'production' => { 'a' => 'b'} })\n        lambda { @config.fetch }.should.raise\n      end\n\n      it 'returns the configuration yaml file data for this environment as a hash' do\n        staging = { 'foo' => 'bar', 'repository' => 'xyzzy' }\n        write_config_file('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })\n        result = @config.fetch\n        staging.each_pair do |k,v|\n          result[k].should == v\n        end\n      end\n    \n      it 'does not include configuration information for other environments in the returned hash' do\n        staging = { 'foo' => 'bar', 'baz' => 'xyzzy' }\n        write_config_file('production' => { 'repository' => 'c', 'a' => 'b'}, 'staging' => staging)\n        @config.fetch['a'].should.be.nil\n      end\n\n      it 'includes the environment in the hash' do\n        staging = { 'foo' => 'bar', 'baz' => 'xyzzy' }\n        write_config_file('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })\n        @config.fetch['environment'].should == 'staging'\n      end\n\n      it 'does not allow overriding the environment in the configuration file' do\n        staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'environment' => 'production' }\n        write_config_file('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })\n        @config.fetch['environment'].should == 'staging'\n      end\n\n      it 'includes the project handle in the hash' do\n        staging = { 'foo' => 'bar', 'repository' => 'xyzzy' }\n        write_config_file('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })\n        @config.fetch['project'].should == 'foo'\n      end\n\n      it 'does not allow overriding the project handle in the configuration file when a project root is specified' do\n        staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'project' => 'diskey_whisk' }\n        write_config_file('foo' => { 'production' => { 'repository' => 'b'}, 'staging' => staging })\n        @config.fetch['project'].should == 'foo'\n      end\n\n      it 'allows overriding the project handle in the configuration file when a project root is not specified' do\n        ENV['to'] = @env = 'staging'\n        staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'project' => 'diskey_whisk' }\n        write_config_file('production' => { 'repository' => 'b'}, 'staging' => staging)\n        @config.fetch['project'].should == 'diskey_whisk'\n      end\n    \n      it 'includes the environment name as the config_target setting when no config_target is specified' do\n        staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'project' => 'diskey_whisk' }\n        write_config_file('production' => { 'repository' => 'b'}, 'staging' => staging)\n        @config.fetch['config_target'].should == 'staging'\n      end\n    \n      it 'includes the config_target setting when a config_target is specified' do\n        staging = { 'foo' => 'bar', 'repository' => 'xyzzy', 'project' => 'diskey_whisk', 'config_target' => 'testing' }\n        write_config_file('production' => { 'repository' => 'b'}, 'staging' => staging)\n        @config.fetch['config_target'].should == 'testing'\n      end\n      \n      it 'fails if the named target cannot be found' do\n        ENV['to'] = @env = 'bogus:thing'\n        lambda { @config.fetch }.should.raise\n      end\n    end\n  end\n\n  describe 'returning configuration data from a configuration file' do\n    before do\n      @path = build_temp_dir\n      ENV['path'] = @config_file = File.join(@path, 'deploy.yml')\n    end\n    \n    after do\n      FileUtils.rm_rf(@path)\n    end\n\n    it 'fails if the configuration file does not exist' do\n      lambda { @config.configuration_data }.should.raise\n    end\n\n    it 'returns the contents of the configuration file' do\n      File.open(@config_file, 'w') { |f| f.puts \"file contents\" }\n      @config.configuration_data.should == \"file contents\\n\"\n    end\n  end\n\n  describe 'loading data from the configuration file' do\n    before do\n      ENV['to'] = 'foo:bar'\n      @path = build_temp_dir\n      ENV['path'] = @config_file = File.join(@path, 'deploy.yml')\n    end\n    \n    after do\n      FileUtils.rm_rf(@path)\n    end\n    \n    it 'fails if the configuration data cannot be loaded' do\n      lambda { @config.load_data }.should.raise\n    end\n\n    it 'fails if converting the configuration data from YAML fails' do\n      File.open(@config_file, 'w') { |f| f.puts \"}\" }\n      lambda { @config.load_data }.should.raise\n    end\n\n    it 'returns the un-YAMLized configuration data' do\n      write_config_file('repository' => 'x')\n      @config.load_data.should == { 'repository' => 'x' }\n    end    \n  end\n\n  describe 'computing the project name' do\n    it 'returns the project name from the ENV[\"to\"] setting when it is available' do\n      ENV['to'] = 'foo:staging'\n      @config.project_name.should == 'foo'\n    end\n\n    it 'returns \"unnamed_project\" when ENV[\"to\"] is unset' do\n      ENV['to'] = ''\n      @config.project_name.should == 'unnamed_project'\n    end\n\n    it 'returns \"unnamed_project\" when no ENV[\"to\"] project setting is available' do\n      ENV['to'] = 'staging'\n      @config.project_name.should == 'unnamed_project'\n    end\n  end\n\n  describe 'finding the configuration file' do\n    before do\n      ENV['to'] = @env = 'staging'\n    end\n\n    describe 'and no path is specified' do\n      before do\n        ENV['path'] = @path = nil\n        @original_path = Dir.pwd\n        @base_path = build_temp_dir\n        Dir.chdir(@base_path)\n        FileUtils.touch(File.join(@base_path, 'Rakefile'))\n        @dir = File.join(@base_path, 'config')\n        Dir.mkdir(@dir)\n        \n        [ \n          \"/deploy/foo/staging.yml\", \n          \"/deploy/foo.yml\", \n          \"/deploy/staging.yml\",\n          \"/staging.yml\", \n          \"/deploy.yml\"\n        ].each { |file| make(File.join(@dir, file)) }\n      end\n      \n      after do\n        FileUtils.rm_rf(@base_path)\n        Dir.chdir(@original_path)\n      end\n      \n      describe 'and a project name is specified in ENV[\"to\"]' do\n        before do\n          ENV['to'] = @env = 'foo:staging'\n        end\n\n        it 'returns the path to deploy/foo/<environment>.yml under the project base path if it exists' do\n          @config.configuration_file.should == \"#{@dir}/deploy/foo/staging.yml\"\n        end\n\n        it 'returns the path to deploy/foo.yml under the project base path if it exists' do\n          File.unlink(\"#{@dir}/deploy/foo/staging.yml\")\n          @config.configuration_file.should == \"#{@dir}/deploy/foo.yml\"\n        end\n\n        it 'returns the path to a per-environment configuration file in the deploy/ directory under the project base path if it exists' do\n          File.unlink(\"#{@dir}/deploy/foo/staging.yml\")\n          File.unlink(\"#{@dir}/deploy/foo.yml\")\n          @config.configuration_file.should == \"#{@dir}/deploy/staging.yml\"\n        end\n\n        it 'returns the path to a per-environment configuration file under the project base path if it exists' do\n          File.unlink(\"#{@dir}/deploy/foo/staging.yml\")\n          File.unlink(\"#{@dir}/deploy/foo.yml\")\n          File.unlink(\"#{@dir}/deploy/staging.yml\")\n          @config.configuration_file.should == \"#{@dir}/staging.yml\"\n        end\n\n        it 'returns the path to deploy.yml under the project base path' do\n          File.unlink(\"#{@dir}/deploy/foo/staging.yml\")\n          File.unlink(\"#{@dir}/deploy/foo.yml\")\n          File.unlink(\"#{@dir}/deploy/staging.yml\")\n          File.unlink(\"#{@dir}/staging.yml\")\n          @config.configuration_file.should == \"#{@dir}/deploy.yml\"\n        end\n\n        it 'fails if no per-environment config file nor deploy.yml exists under the project base path' do\n          File.unlink(\"#{@dir}/deploy/foo/staging.yml\")\n          File.unlink(\"#{@dir}/deploy/foo.yml\")\n          File.unlink(\"#{@dir}/deploy/staging.yml\")\n          File.unlink(\"#{@dir}/staging.yml\")\n          File.unlink(\"#{@dir}/deploy.yml\")\n          lambda { @config.configuration_file }.should.raise\n        end\n      end\n\n      describe 'and no project name is specified in ENV[\"to\"]' do\n        it 'returns the path to a per-environment configuration file in the deploy/ directory under the project base path if it exists' do\n          @config.configuration_file.should == \"#{@dir}/deploy/staging.yml\"\n        end\n\n        it 'returns the path to a per-environment configuration file under the project base path if it exists' do\n          File.unlink(\"#{@dir}/deploy/staging.yml\")\n          @config.configuration_file.should == \"#{@dir}/staging.yml\"\n        end\n\n        it 'returns the path to deploy.yml under the project base path' do\n          File.unlink(\"#{@dir}/deploy/staging.yml\")\n          File.unlink(\"#{@dir}/staging.yml\")\n          @config.configuration_file.should == \"#{@dir}/deploy.yml\"\n        end\n\n        it 'fails if no per-environment config file nor deploy.yml exists under the project base path' do\n          File.unlink(\"#{@dir}/deploy/staging.yml\")\n          File.unlink(\"#{@dir}/staging.yml\")\n          File.unlink(\"#{@dir}/deploy.yml\")\n          lambda { @config.configuration_file }.should.raise\n        end\n      end\n    end\n\n    describe 'and looking up a file' do\n      before do\n        @path = build_temp_dir\n        ENV['path'] = @config_file = File.join(@path, 'deploy.yml')\n      end\n      \n      after do\n        FileUtils.rm_rf(@path)\n      end\n    \n      it 'fails if a path is specified which does not exist' do\n        lambda { @config.configuration_file }.should.raise\n      end\n\n      it 'returns the file path when a path which points to an existing file is specified' do\n        FileUtils.touch(@config_file)\n        @config.configuration_file.should == @config_file\n      end\n    end\n\n    describe 'and a path which points to a directory is specified' do\n      before do\n        ENV['path'] = @path = build_temp_dir\n        \n        [ \n          \"/deploy/foo/staging.yml\", \n          \"/deploy/foo.yml\", \n          \"/deploy/staging.yml\",\n          \"/staging.yml\", \n          \"/deploy.yml\"\n        ].each { |file| make(File.join(@path, file)) }\n      end\n\n      after do\n        FileUtils.rm_rf(@path)\n      end\n      \n      describe 'and a project name is specified in ENV[\"to\"]' do\n        before do\n          ENV['to'] = @env = 'foo:staging'\n        end\n\n        it 'returns the path to deploy/foo/<environment>.yml under the project base path if it exists' do\n          @config.configuration_file.should == File.join(@path, 'deploy', 'foo' ,'staging.yml')\n        end\n\n        it 'returns the path to deploy/foo.yml under the project base path if it exists' do\n          File.unlink(File.join(@path, 'deploy', 'foo', 'staging.yml'))\n          @config.configuration_file.should == File.join(@path, 'deploy', 'foo.yml')\n        end\n\n        it 'returns the path to a per-environment configuration file under deploy/ in the path specified if that file exists' do\n          File.unlink(File.join(@path, 'deploy', 'foo', 'staging.yml'))\n          File.unlink(File.join(@path, 'deploy', 'foo.yml'))\n          @config.configuration_file.should == File.join(@path, 'deploy', 'staging.yml')\n        end\n\n        it 'returns the path to a per-environment configuration file in the path specified if that file exists' do\n          File.unlink(File.join(@path, 'deploy', 'foo', 'staging.yml'))\n          File.unlink(File.join(@path, 'deploy', 'foo.yml'))\n          File.unlink(File.join(@path, 'deploy', 'staging.yml'))\n          @config.configuration_file.should == File.join(@path, 'staging.yml')\n        end\n\n        it 'returns the path to deploy.yaml in the path specified if deploy.yml exists' do\n          File.unlink(File.join(@path, 'deploy', 'foo', 'staging.yml'))\n          File.unlink(File.join(@path, 'deploy', 'foo.yml'))\n          File.unlink(File.join(@path, 'deploy', 'staging.yml'))\n          File.unlink(File.join(@path, 'staging.yml'))\n          @config.configuration_file.should == File.join(@path, 'deploy.yml')\n        end\n\n        it 'fails if no per-environment configuration file nor deploy.yml exists in the path specified' do\n          File.unlink(File.join(@path, 'deploy', 'foo', 'staging.yml'))\n          File.unlink(File.join(@path, 'deploy', 'foo.yml'))\n          File.unlink(File.join(@path, 'deploy', 'staging.yml'))\n          File.unlink(File.join(@path, 'staging.yml'))\n          File.unlink(File.join(@path, 'deploy.yml'))\n          lambda { @config.configuration_file }.should.raise\n        end\n      end\n\n      describe 'and no project name is specified in ENV[\"to\"]' do\n        it 'returns the path to a per-environment configuration file under deploy/ in the path specified if that file exists' do\n          @config.configuration_file.should == File.join(@path, 'deploy', 'staging.yml')\n        end\n\n        it 'returns the path to a per-environment configuration file in the path specified if that file exists' do\n          File.unlink(File.join(@path, 'deploy', 'staging.yml'))\n          @config.configuration_file.should == File.join(@path, 'staging.yml')\n        end\n\n        it 'returns the path to deploy.yaml in the path specified if deploy.yml exists' do\n          File.unlink(File.join(@path, 'deploy', 'staging.yml'))\n          File.unlink(File.join(@path, 'staging.yml'))\n          @config.configuration_file.should == File.join(@path, 'deploy.yml')\n        end\n\n        it 'fails if no per-environment configuration file nor deploy.yml exists in the path specified' do\n          File.unlink(File.join(@path, 'deploy', 'staging.yml'))\n          File.unlink(File.join(@path, 'staging.yml'))\n          File.unlink(File.join(@path, 'deploy.yml'))\n          lambda { @config.configuration_file }.should.raise\n        end\n      end\n    end\n  end\n\n  describe 'filtering configuration data' do\n    before do\n      ENV['to'] = @env = 'foo:erl'\n      @data = {\n        'foo' => { \n          'xyz' => { 'repository' => 'x' },\n          'eee' => { 'repository' => 'x', 'domain' => '' },\n          'abc' => { 'repository' => 'x', 'domain' => 'what@example.com' },\n          'baz' => { 'repository' => 'x', 'domain' => [ 'bar@example.com', 'baz@domain.com' ]},\n          'bar' => { 'repository' => 'x', 'domain' => [ 'user@example.com', nil, 'foo@domain.com' ]},\n          'bat' => { 'repository' => 'x', 'domain' => [ 'user@example.com', 'foo@domain.com', '' ]},\n          'hsh' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com' }, { 'name' => 'baz@domain.com' } ]},\n          'mix' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com' }, 'baz@domain.com' ]},            \n          'erl' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com', 'roles' => nil }, \n                                                        { 'name' => 'baz@domain.com', 'roles' => '' },\n                                                        { 'name' => 'aok@domain.com', 'roles' => [] } ]},\n          'rol' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com', 'roles' => [ 'web', 'db' ] }, \n                                                        { 'name' => 'baz@domain.com', 'roles' => [ 'db' ] },            \n                                                        { 'name' => 'aok@domain.com', 'roles' => 'app' } ]},            \n          'wow' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com', 'roles' => [ 'web', 'db' ] }, \n                                                        { 'name' => 'baz@domain.com', 'roles' => [ 'db' ] },   \n                                                          '', 'foo@bar.example.com',      \n                                                        { 'name' => 'aok@domain.com', 'roles' => 'app' } ]},            \n        },\n  \n        'zyx' => {\n          'xyz' => { 'repository' => 'x' },\n          'eee' => { 'repository' => 'x', 'domain' => '' },\n          'abc' => { 'repository' => 'x', 'domain' => 'what@example.com' },\n          'hij' => { 'repository' => 'x', 'domain' => [ 'bar@example.com', 'baz@domain.com' ]},\n          'def' => { 'repository' => 'x', 'domain' => [ 'user@example.com', nil, 'foo@domain.com' ]},\n          'dex' => { 'repository' => 'x', 'domain' => [ 'user@example.com', 'foo@domain.com', '' ]},\n          'hsh' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com' }, { 'name' => 'baz@domain.com' } ]},\n          'mix' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com' }, 'baz@domain.com' ]},\n          'erl' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com', 'roles' => nil }, \n                                                        { 'name' => 'baz@domain.com', 'roles' => '' },\n                                                        { 'name' => 'aok@domain.com', 'roles' => [] } ]},\n          'rol' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com', 'roles' => [ 'web', 'db' ] }, \n                                                        { 'name' => 'baz@domain.com', 'roles' => [ 'db' ] },         \n                                                        { 'name' => 'aok@domain.com', 'roles' => 'app' } ]},            \n          'wow' => { 'repository' => 'x', 'domain' => [ { 'name' => 'bar@example.com', 'roles' => [ 'web', 'db' ] }, \n                                                        { 'name' => 'baz@domain.com', 'roles' => [ 'db' ] },   \n                                                           '', 'foo@bar.example.com',      \n                                                        { 'name' => 'aok@domain.com', 'roles' => 'app' } ]},            \n        }\n      }\n    end\n    \n    it 'should apply all available filters' do\n      @config.filter_data(@data).should == {\n        \"repository\" => \"x\", \n        \"project\" => \"foo\", \n        \"config_target\" => \"erl\", \n        \"environment\" => \"erl\",\n        \"domain\"     => [ \n          { 'name' => \"bar@example.com\" }, \n          { 'name' => \"baz@domain.com\" }, \n          { 'name' => \"aok@domain.com\" }\n        ]\n      }\n    end\n  end\n\n  describe 'computing the base path for the project' do\n    before do\n      @original_path = Dir.pwd\n      ENV['path'] = @path = nil\n    end\n\n    after do\n      Dir.chdir(@original_path)\n    end\n\n    describe 'and a \"path\" environment variable is set' do\n      before do\n        ENV['path'] = @path = build_temp_dir\n        @original_path = Dir.pwd\n      end\n      \n      after do\n        FileUtils.rm_rf(@path)\n        Dir.chdir(@original_path)\n      end\n\n      it 'returns the path set in the \"path\" environment variable' do\n        @config.base_path.should == @path\n      end\n\n      it 'leaves the current working path the same as when the base path lookup started' do\n        @config.base_path\n        Dir.pwd.should == @original_path\n      end\n    end\n\n    describe 'and there is no Rakefile in the root path to the current directory' do\n      before do\n        @original_path = Dir.pwd\n        @path = build_temp_dir\n        Dir.chdir(@path)\n      end\n\n      after do\n        Dir.chdir(@original_path)\n        FileUtils.rm_rf(@path)\n      end\n\n      it 'returns the config directory under the current directory if there is no Rakefile along the root path to the current directory' do\n        @config.base_path.should == File.join(@path, 'config')\n      end\n\n      it 'leaves the current working path the same as when the base path lookup started' do\n        prior = Dir.pwd\n        @config.base_path\n        Dir.pwd.should == prior\n      end\n    end\n\n    describe 'and there is a Rakefile in the root path to the current directory' do\n      before do\n        @original_path = Dir.pwd\n        @path = build_temp_dir\n        Dir.chdir(@path)\n        FileUtils.touch(File.join(@path, 'Rakefile'))\n      end\n\n      after do\n        Dir.chdir(@original_path)\n        FileUtils.rm_rf(@path)\n      end\n\n      it 'return the config directory in the nearest enclosing path with a Rakefile along the root path to the current directory' do\n        @config.base_path.should == File.join(@path, 'config')\n      end\n\n      it 'leaves the current working path the same as when the base path lookup started' do\n        prior = Dir.pwd\n        @config.base_path\n        Dir.pwd.should == prior\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "spec/whiskey_disk/helpers_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper.rb'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'whiskey_disk', 'helpers'))\n\ndescribe 'when checking for a role during setup or deployment' do\n  it 'accepts a role string' do\n    lambda { role?('web') }.should.not.raise(ArgumentError)\n  end\n  \n  it 'requires a role string' do\n    lambda { role? }.should.raise(ArgumentError)\n  end\n\n  it 'returns false if the WD_ROLES environment variable is unset' do\n    ENV['WD_ROLES'] = nil\n    role?(:web).should.be.false\n  end\n\n  it 'returns false if the WD_ROLES environment variable is empty' do\n    ENV['WD_ROLES'] = ''\n    role?(:web).should.be.false\n  end\n  \n  it 'returns true if the role, as a symbol is among the roles in the WD_ROLES env variable' do\n    ENV['WD_ROLES'] = 'db:web'\n    role?(:db).should.be.true\n  end\n  \n  it 'returns true if the role, as a string is among the roles in the WD_ROLES env variable' do\n    ENV['WD_ROLES'] = 'db:web'\n    role?('db').should.be.true\n  end\n  \n  it 'returns false if the role, as a symbol is not among the roles in the WD_ROLES env variable' do\n    ENV['WD_ROLES'] = 'db:web'\n    role?(:app).should.be.false\n  end\n  \n  it 'returns false if the role, as a string is not among the roles in the WD_ROLES env variable' do\n    ENV['WD_ROLES'] = 'db:web'\n    role?('app').should.be.false\n  end\nend\n\ndef set_git_changes(changes)\n  self.stub!(:git_changes).and_return(changes)\nend\n\ndef set_rsync_changes(changes)\n  self.stub!(:rsync_changes).and_return(changes)\nend\n\ndescribe 'when determining if certain files changed when a deployment was run' do\n  before do\n    @matching_file     = '/path/to/file'\n    @matching_path     = '/path/to'\n    @non_matching_file = '/nowhere/file'\n    @substring_file    = '/nowhere/filething'\n    @random_file       = '/random/path'\n    \n    set_git_changes([])\n    set_rsync_changes([])\n  end\n  \n  it 'accepts a path' do\n    lambda { changed?('foo') }.should.not.raise(ArgumentError)\n  end\n  \n  it 'requires a path' do\n    lambda { changed? }.should.raise(ArgumentError)\n  end\n  \n  it 'returns true when the specified file is in the list of git changes' do\n    set_git_changes([ @matching_file, @random_file])\n    changed?(@matching_file).should.be.true\n  end\n  \n  it 'ignores trailing \"/\"s in the provided path when doing an exact git change match' do\n    set_git_changes([ @matching_file, @random_file])\n    changed?(@matching_file + '///').should.be.true    \n  end\n  \n  it 'returns true when the specified path is a full path prefix in the list of git changes' do\n    set_git_changes([ @matching_file , @random_file])\n    changed?(@matching_path).should.be.true    \n  end\n  \n  it 'ignores trailing \"/\"s in the provided path when doing a path git change match' do\n    set_git_changes([ @matching_file , @random_file])\n    changed?(@matching_path + '///').should.be.true    \n  end\n\n  it 'returns true when the specified file is in the list of rsync changes' do    \n    set_rsync_changes([ @matching_file, @random_file])\n    changed?(@matching_file).should.be.true\n  end\n\n  it 'ignores trailing \"/\"s in the provided path when doing an exact rsync change match' do\n    set_rsync_changes([ @matching_file, @random_file])\n    changed?(@matching_file + \"///\").should.be.true\n  end\n\n  it 'returnes true when the specified path is a full path prefix in the list of git changes' do\n    set_rsync_changes([ @matching_file , @random_file])\n    changed?(@matching_path).should.be.true    \n  end\n  \n  it 'ignores trailing \"/\"s in the provided path when doing a path rsync change match' do\n    set_rsync_changes([ @matching_file , @random_file])\n    changed?(@matching_path + '///').should.be.true    \n  end\n  \n  it 'ignores regex metacharacters when looking for a git match' do\n    set_git_changes([ '/path/to/somestring'])\n    changed?('/path/to/some.*').should.be.false\n  end\n  \n  it 'ignores regex metacharacters when looking for an rsync match' do\n    set_rsync_changes([ '/path/to/somestring'])\n    changed?('/path/to/some.*').should.be.false\n  end\n  \n  it 'returns true when the git changes file cannot be found' do\n    set_git_changes(nil)\n    changed?(@matching_file).should.be.true    \n  end\n  \n  it 'returns false if not path or file matches the specified file' do\n    set_git_changes([@matching_file, @matching_path, @random_file, @substring_file])\n    set_rsync_changes([@matching_file, @matching_path, @random_file, @substring_file])\n    changed?(@non_matching_file).should.be.false\n  end\nend\n\ndescribe \"when finding files changed by git in a deployment\" do\n  before do\n    @contents = 'CHANGELOG\nREADME.markdown\nRakefile\nVERSION\nlib/whiskey_disk.rb\nlib/whiskey_disk/config.rb\nlib/whiskey_disk/helpers.rb\nscenarios/git_repositories/project.git/objects/04/26e152e66c8cd42974279bdcae09be9839c172\nscenarios/git_repositories/project.git/objects/04/f4de85eaf72ef1631dc6d7424045c0a749b757\nscenarios/git_repositories/project.git/refs/heads/bad_rakefile\nscenarios/git_repositories/project.git/refs/heads/master\nscenarios/remote/deploy.yml\nspec/integration/deployment_failures_spec.rb\nspec/integration/post_rake_tasks_spec.rb\nspec/integration/staleness_checks_spec.rb\nspec/spec_helper.rb\nspec/whiskey_disk/config_spec.rb\nspec/whiskey_disk/helpers_spec.rb\nspec/whiskey_disk_spec.rb\nwhiskey_disk.gemspec\n'   \n  end\n    \n  it 'works without arguments' do\n    lambda { git_changes }.should.not.raise(ArgumentError)\n  end\n  \n  it 'does not allow arguments' do\n    lambda { git_changes(:foo) }.should.raise(ArgumentError)\n  end\n  \n  it 'returns nil when a git changes file cannot be found' do\n    self.stub!(:read_git_changes_file).and_raise\n    git_changes.should.be.nil\n  end\n  \n  it 'returns an empty list if no files are found in the git changes file' do\n    self.stub!(:read_git_changes_file).and_return('')\n    git_changes.should == []\n  end\n  \n  it 'returns a list of all filenames mentioned in the git changes file' do\n    self.stub!(:read_git_changes_file).and_return(@contents)\n    git_changes.should == @contents.split(\"\\n\")\n  end\n  \n  it 'strips duplicates from filenames mentioned in the git changes file' do\n    lines = @contents.split(\"\\n\")\n    duplicates = @contents + lines.first + \"\\n\" + lines.last + \"\\n\"\n    self.stub!(:read_git_changes_file).and_return(duplicates)\n    git_changes.sort.should == @contents.split(\"\\n\").sort\n  end\nend\n\ndescribe \"when finding files changed by rsync in a deployment\" do\n  before do\n    @contents = '2011/02/27 20:11:42 [36728] receiving file list\n2011/02/27 20:11:42 [36728] sent 24 bytes  received 9 bytes  total size 0\n2011/02/27 20:11:58 [36780] receiving file list\n2011/02/27 20:11:58 [36780] sent 24 bytes  received 9 bytes  total size 0\n2011/02/27 20:12:09 [36808] receiving file list\n2011/02/27 20:12:09 [36808] sent 24 bytes  received 9 bytes  total size 0\n2011/02/27 20:12:19 [36835] receiving file list\n2011/02/27 20:12:19 [36835] .d..t.... ./\n2011/02/27 20:12:19 [36835] >f+++++++ Info.plist\n2011/02/27 20:12:19 [36835] cd+++++++ Application Support/\n2011/02/27 20:12:19 [36835] cd+++++++ Application Support/Google/\n2011/02/27 20:12:19 [36835] cd+++++++ Application Support/Google/GoogleTalkPlugin.app/\n2011/02/27 20:12:19 [36835] cd+++++++ Application Support/Google/GoogleTalkPlugin.app/Contents/\n2011/02/27 20:12:19 [36835] >f+++++++ Application Support/Google/GoogleTalkPlugin.app/Contents/Info.plist\n2011/02/27 20:12:19 [36835] cd+++++++ Application Support/Google/GoogleTalkPlugin.app/Contents/Frameworks/\n2011/02/27 20:12:19 [36835] cd+++++++ Application Support/Google/GoogleTalkPlugin.app/Contents/Frameworks/GoogleBreakpad.framework/\n2011/02/27 20:12:19 [36835] cL+++++++ Application Support/Google/GoogleTalkPlugin.app/Contents/Frameworks/GoogleBreakpad.framework/GoogleBreakpad -> Versions/Current/GoogleBreakpad\n2011/02/27 20:12:19 [36835] cL+++++++ Application Support/Google/GoogleTalkPlugin.app/Contents/Frameworks/GoogleBreakpad.framework/Resources -> Versions/Current/Resources\n2011/02/27 20:12:19 [36835] cd+++++++ Application Support/Google/GoogleTalkPlugin.app/Contents/Frameworks/GoogleBreakpad.framework/Versions/\n2011/02/27 20:12:19 [36835] cL+++++++ Application Support/Google/GoogleTalkPlugin.app/Contents/Frameworks/GoogleBreakpad.framework/Versions/Current -> A\n2011/02/27 20:12:19 [36835] cd+++++++ Application Support/Google/GoogleTalkPlugin.app/Contents/Frameworks/GoogleBreakpad.framework/Versions/A/\n2011/02/27 20:12:19 [36835] cd+++++++ Application Support/Google/GoogleTalkPlugin.app/Contents/Frameworks/GoogleBreakpad.framework/Versions/A/Resources/\n2011/02/27 20:12:19 [36835] cd+++++++ Application Support/Google/GoogleTalkPlugin.app/Contents/Frameworks/GoogleBreakpad.framework/Versions/A/Resources/Reporter.app/\n2011/02/27 20:12:19 [36835] cd+++++++ Application Support/Google/GoogleTalkPlugin.app/Contents/Frameworks/GoogleBreakpad.framework/Versions/A/Resources/Reporter.app/Contents/\n2011/02/27 20:12:19 [36835] cd+++++++ Application Support/Google/GoogleTalkPlugin.app/Contents/MacOS/\n2011/02/27 20:12:20 [36835] >f+++++++ Application Support/Google/GoogleTalkPlugin.app/Contents/MacOS/GoogleTalkPlugin\n2011/02/27 20:12:20 [36835] cd+++++++ Internet Plug-Ins/\n2011/02/27 20:12:20 [36835] cd+++++++ Internet Plug-Ins/googletalkbrowserplugin.plugin/\n2011/02/27 20:12:20 [36835] cd+++++++ Internet Plug-Ins/googletalkbrowserplugin.plugin/Contents/\n2011/02/27 20:12:20 [36835] cd+++++++ Internet Plug-Ins/googletalkbrowserplugin.plugin/Contents/MacOS/\n2011/02/27 20:12:20 [36835] >f+++++++ Internet Plug-Ins/googletalkbrowserplugin.plugin/Contents/MacOS/googletalkbrowserplugin\n2011/02/27 20:12:20 [36835] cd+++++++ Internet Plug-Ins/googletalkbrowserplugin.plugin/Contents/Resources/\n2011/02/27 20:12:20 [36835] cd+++++++ Internet Plug-Ins/npgtpo3dautoplugin.plugin/\n2011/02/27 20:12:20 [36835] cd+++++++ Internet Plug-Ins/npgtpo3dautoplugin.plugin/Contents/\n2011/02/27 20:12:20 [36835] >f+++++++ Internet Plug-Ins/npgtpo3dautoplugin.plugin/Contents/Info.plist\n2011/02/27 20:12:20 [36835] cd+++++++ Internet Plug-Ins/npgtpo3dautoplugin.plugin/Contents/Frameworks/\n2011/02/27 20:12:20 [36835] cd+++++++ Internet Plug-Ins/npgtpo3dautoplugin.plugin/Contents/Frameworks/Cg.framework/\n2011/02/27 20:12:20 [36835] cL+++++++ Internet Plug-Ins/npgtpo3dautoplugin.plugin/Contents/Frameworks/Cg.framework/Cg -> Versions/Current/Cg\n2011/02/27 20:12:20 [36835] cL+++++++ Internet Plug-Ins/npgtpo3dautoplugin.plugin/Contents/Frameworks/Cg.framework/Resources -> Versions/Current/Resources\n2011/02/27 20:12:20 [36835] cd+++++++ Internet Plug-Ins/npgtpo3dautoplugin.plugin/Contents/Frameworks/Cg.framework/Versions/\n2011/02/27 20:12:20 [36835] cL+++++++ Internet Plug-Ins/npgtpo3dautoplugin.plugin/Contents/Frameworks/Cg.framework/Versions/Current -> 1.0\n2011/02/27 20:12:20 [36835] cd+++++++ Internet Plug-Ins/npgtpo3dautoplugin.plugin/Contents/Frameworks/Cg.framework/Versions/1.0/\n2011/02/27 20:12:20 [36835] cd+++++++ Internet Plug-Ins/npgtpo3dautoplugin.plugin/Contents/MacOS/\n2011/02/27 20:12:20 [36835] cd+++++++ Internet Plug-Ins/npgtpo3dautoplugin.plugin/Contents/Resources/\n2011/02/27 20:12:20 [36835] cd+++++++ Internet Plug-Ins/npgtpo3dautoplugin.plugin/Contents/Resources/English.lproj/\n2011/02/27 20:12:20 [36835] cd+++++++ QuickTime/\n2011/02/27 20:12:20 [36835] cd+++++++ QuickTime/Google Camera Adapter 0.component/\n2011/02/27 20:12:20 [36835] cd+++++++ QuickTime/Google Camera Adapter 0.component/Contents/\n2011/02/27 20:12:20 [36835] cd+++++++ QuickTime/Google Camera Adapter 0.component/Contents/MacOS/\n2011/02/27 20:12:20 [36835] cd+++++++ QuickTime/Google Camera Adapter 0.component/Contents/Resources/\n2011/02/27 20:12:20 [36835] cd+++++++ QuickTime/Google Camera Adapter 1.component/\n2011/02/27 20:12:20 [36835] cd+++++++ QuickTime/Google Camera Adapter 1.component/Contents/\n2011/02/27 20:12:20 [36835] >f+++++++ QuickTime/Google Camera Adapter 1.component/Contents/Info.plist\n2011/02/27 20:12:20 [36835] cd+++++++ QuickTime/Google Camera Adapter 1.component/Contents/MacOS/\n2011/02/27 20:12:20 [36835] cd+++++++ QuickTime/Google Camera Adapter 1.component/Contents/Resources/\n2011/02/27 20:12:20 [36835] sent 386 bytes  received 1431 bytes  total size 5229466\n'\n\n    @changes = [\n        \"Info.plist\",\n        \"Application Support\",\n        \"Application Support/Google\",\n        \"Application Support/Google/GoogleTalkPlugin.app\",\n        \"Application Support/Google/GoogleTalkPlugin.app/Contents\",\n        \"Application Support/Google/GoogleTalkPlugin.app/Contents/Frameworks\",\n        \"Application Support/Google/GoogleTalkPlugin.app/Contents/Frameworks/GoogleBreakpad.framework\",\n        \"Application Support/Google/GoogleTalkPlugin.app/Contents/Frameworks/GoogleBreakpad.framework/GoogleBreakpad -> Versions/Current/GoogleBreakpad\",\n        \"Application Support/Google/GoogleTalkPlugin.app/Contents/Frameworks/GoogleBreakpad.framework/Resources -> Versions/Current/Resources\",\n        \"Application Support/Google/GoogleTalkPlugin.app/Contents/Frameworks/GoogleBreakpad.framework/Versions\",\n        \"Application Support/Google/GoogleTalkPlugin.app/Contents/Frameworks/GoogleBreakpad.framework/Versions/A\",\n        \"Application Support/Google/GoogleTalkPlugin.app/Contents/Frameworks/GoogleBreakpad.framework/Versions/A/Resources\",\n        \"Application Support/Google/GoogleTalkPlugin.app/Contents/Frameworks/GoogleBreakpad.framework/Versions/A/Resources/Reporter.app\",\n        \"Application Support/Google/GoogleTalkPlugin.app/Contents/Frameworks/GoogleBreakpad.framework/Versions/A/Resources/Reporter.app/Contents\",\n        \"Application Support/Google/GoogleTalkPlugin.app/Contents/Frameworks/GoogleBreakpad.framework/Versions/Current -> A\",\n        \"Application Support/Google/GoogleTalkPlugin.app/Contents/Info.plist\",\n        \"Application Support/Google/GoogleTalkPlugin.app/Contents/MacOS\",\n        \"Application Support/Google/GoogleTalkPlugin.app/Contents/MacOS/GoogleTalkPlugin\",\n        \"Internet Plug-Ins\",\n        \"Internet Plug-Ins/googletalkbrowserplugin.plugin\",\n        \"Internet Plug-Ins/googletalkbrowserplugin.plugin/Contents\",\n        \"Internet Plug-Ins/googletalkbrowserplugin.plugin/Contents/MacOS\",\n        \"Internet Plug-Ins/googletalkbrowserplugin.plugin/Contents/MacOS/googletalkbrowserplugin\",\n        \"Internet Plug-Ins/googletalkbrowserplugin.plugin/Contents/Resources\",\n        \"Internet Plug-Ins/npgtpo3dautoplugin.plugin\",\n        \"Internet Plug-Ins/npgtpo3dautoplugin.plugin/Contents\",\n        \"Internet Plug-Ins/npgtpo3dautoplugin.plugin/Contents/Frameworks\",\n        \"Internet Plug-Ins/npgtpo3dautoplugin.plugin/Contents/Frameworks/Cg.framework\",\n        \"Internet Plug-Ins/npgtpo3dautoplugin.plugin/Contents/Frameworks/Cg.framework/Cg -> Versions/Current/Cg\",\n        \"Internet Plug-Ins/npgtpo3dautoplugin.plugin/Contents/Frameworks/Cg.framework/Resources -> Versions/Current/Resources\",\n        \"Internet Plug-Ins/npgtpo3dautoplugin.plugin/Contents/Frameworks/Cg.framework/Versions\",\n        \"Internet Plug-Ins/npgtpo3dautoplugin.plugin/Contents/Frameworks/Cg.framework/Versions/1.0\",\n        \"Internet Plug-Ins/npgtpo3dautoplugin.plugin/Contents/Frameworks/Cg.framework/Versions/Current -> 1.0\",\n        \"Internet Plug-Ins/npgtpo3dautoplugin.plugin/Contents/Info.plist\",\n        \"Internet Plug-Ins/npgtpo3dautoplugin.plugin/Contents/MacOS\",\n        \"Internet Plug-Ins/npgtpo3dautoplugin.plugin/Contents/Resources\",\n        \"Internet Plug-Ins/npgtpo3dautoplugin.plugin/Contents/Resources/English.lproj\",\n        \"QuickTime\",\n        \"QuickTime/Google Camera Adapter 0.component\",\n        \"QuickTime/Google Camera Adapter 0.component/Contents\",\n        \"QuickTime/Google Camera Adapter 0.component/Contents/MacOS\",\n        \"QuickTime/Google Camera Adapter 0.component/Contents/Resources\",\n        \"QuickTime/Google Camera Adapter 1.component\",\n        \"QuickTime/Google Camera Adapter 1.component/Contents\",\n        \"QuickTime/Google Camera Adapter 1.component/Contents/Info.plist\",\n        \"QuickTime/Google Camera Adapter 1.component/Contents/MacOS\",\n        \"QuickTime/Google Camera Adapter 1.component/Contents/Resources\",\n      ]\n  end\n\n  it 'works without arguments' do\n    lambda { rsync_changes }.should.not.raise(ArgumentError)\n  end\n\n  it 'does not allow arguments' do\n    lambda { rsync_changes(:foo) }.should.raise(ArgumentError)\n  end\n\n  it 'returns nil when an rsync changes file cannot be found' do\n    self.stub!(:read_rsync_changes_file).and_raise\n    rsync_changes.should.be.nil\n  end\n\n  it 'returns an empty list if no files are found in the rsync changes file' do\n    self.stub!(:read_rsync_changes_file).and_return('')\n    rsync_changes.should == []\n  end\n\n  it 'returns a list of all changed filenames mentioned in the rsync changes file, excluding \".\"' do\n    self.stub!(:read_rsync_changes_file).and_return(@contents)\n    rsync_changes.sort.first.should == @changes.sort.first\n  end\nend\n\ndescribe 'when reading the git-related changes for a deployment' do\n  before do\n    @contents = 'git changes'\n    @changes_path = '/path/to/git/changes'\n    self.stub!(:git_changes_path).and_return(@changes_path)\n    File.stub!(:read).with(@changes_path).and_return(@contents)\n  end\n  \n  it 'works without arguments' do\n    lambda { read_git_changes_file }.should.not.raise(ArgumentError)\n  end\n  \n  it 'does not allow arguments' do\n    lambda { read_git_changes_file(:foo) }.should.raise(ArgumentError)\n  end\n  \n  it 'reads the git changes file' do\n    File.should.receive(:read) do |arg|\n      arg.should == @changes_path\n      @contents\n    end\n    read_git_changes_file\n  end\n  \n  it 'returns the contents of the git changes file' do\n    read_git_changes_file.should == @contents\n  end\n  \n  it 'fails if the git changes file cannot be read' do\n    File.stub!(:read).with(@changes_path).and_raise(Errno::ENOENT)\n    lambda { read_git_changes_file }.should.raise(Errno::ENOENT)\n  end\nend\n\ndescribe 'when reading the rsync-related changes for a deployment' do\n  before do\n    @contents = 'rsync changes'\n    @changes_path = '/path/to/rsync/changes'\n    self.stub!(:rsync_changes_path).and_return(@changes_path)\n    File.stub!(:read).with(@changes_path).and_return(@contents)\n  end\n  \n  it 'works without arguments' do\n    lambda { read_rsync_changes_file }.should.not.raise(ArgumentError)\n  end\n  \n  it 'does not allow arguments' do\n    lambda { read_rsync_changes_file(:foo) }.should.raise(ArgumentError)\n  end\n  \n  it 'reads the rsync changes file' do\n    File.should.receive(:read) do |arg|\n      arg.should == @changes_path\n      @contents\n    end\n    read_rsync_changes_file\n  end\n  \n  it 'returns the contents of the rsync changes file' do\n    read_rsync_changes_file.should == @contents\n  end\n  \n  it 'fails if the rsync changes file cannot be read' do\n    File.stub!(:read).with(@changes_path).and_raise(Errno::ENOENT)\n    lambda { read_rsync_changes_file }.should.raise(Errno::ENOENT)\n  end\nend\n\ndescribe 'computing the path to the git changes file' do\n  before do\n    @git_path = '/path/to/toplevel'\n    @io_handle = ''\n    IO.stub!(:popen).with(\"git rev-parse --show-toplevel\").and_return(@io_handle)\n    @io_handle.stub!(:read).and_return(@git_path + \"\\n\")\n  end\n  \n  it 'works without arguments' do\n    lambda { git_changes_path }.should.not.raise(ArgumentError)\n  end\n  \n  it 'does not allow arguments' do\n    lambda { git_changes_path(:foo) }.should.raise(ArgumentError)\n  end\n  \n  it 'returns the path to the .whiskey_disk_git_changes file in the git top-level path' do\n    git_changes_path.should == File.join(@git_path, '.whiskey_disk_git_changes')\n  end\n  \n  it 'returns the path to the .whiskey_disk_git_changes file in the current directory of the git top-level cannot be found' do\n    @io_handle.stub!(:read).and_return('')\n    git_changes_path.should == File.join(Dir.pwd, '.whiskey_disk_git_changes')    \n  end\nend\n\ndescribe 'computing the path to the rsync changes file' do\n  before do\n    @rsync_path = '/path/to/toplevel'\n    @io_handle = ''\n    IO.stub!(:popen).with(\"git rev-parse --show-toplevel\").and_return(@io_handle)\n    @io_handle.stub!(:read).and_return(@rsync_path + \"\\n\")\n  end\n  \n  it 'works without arguments' do\n    lambda { rsync_changes_path }.should.not.raise(ArgumentError)\n  end\n  \n  it 'does not allow arguments' do\n    lambda { rsync_changes_path(:foo) }.should.raise(ArgumentError)\n  end\n  \n  it 'returns the path to the .whiskey_disk_rsync_changes file in the git top-level path' do\n    rsync_changes_path.should == File.join(@rsync_path, '.whiskey_disk_rsync_changes')\n  end\n  \n  it 'returns the path to the .whiskey_disk_rsync_changes file in the current directory of the git top-level cannot be found' do\n    @io_handle.stub!(:read).and_return('')\n    rsync_changes_path.should == File.join(Dir.pwd, '.whiskey_disk_rsync_changes')    \n  end\nend"
  },
  {
    "path": "spec/whiskey_disk/rake_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper.rb'))\nrequire 'rake'\n\ndescribe 'rake tasks' do\n  before do\n    Rake.application = @rake = Rake::Application.new\n    load File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'whiskey_disk', 'rake.rb'))\n    @whiskey_disk = WhiskeyDisk.new\n    WhiskeyDisk.stub!(:new).and_return(@whiskey_disk)\n  end\n\n  after do\n    Rake.application = nil\n  end\n  \n  describe 'deploy:setup' do\n    before do\n      @whiskey_disk.configuration = {}\n      [ \n        :ensure_main_parent_path_is_present, \n        :ensure_config_parent_path_is_present,\n        :checkout_main_repository,\n        :install_hooks,\n        :checkout_configuration_repository,\n        :update_main_repository_checkout,\n        :update_configuration_repository_checkout,\n        :refresh_configuration,\n        :initialize_all_changes,\n        :run_post_setup_hooks, \n        :flush,\n        :summarize\n      ].each do |meth| \n        @whiskey_disk.stub!(meth)\n      end\n\n      @whiskey_disk.stub!(:success?).and_return(true)\n    end\n    \n    it 'ensures that the parent path for the main repository checkout is present' do\n      @whiskey_disk.should.receive(:ensure_main_parent_path_is_present)\n      @rake[\"deploy:setup\"].invoke\n    end\n    \n    describe 'when a configuration repo is specified' do\n      it 'ensures that the parent path for the configuration repository checkout is present' do\n        @whiskey_disk.configuration = { 'config_repository' => 'foo' }\n        @whiskey_disk.should.receive(:ensure_config_parent_path_is_present)\n        @rake[\"deploy:setup\"].invoke    \n      end\n    end\n    \n    describe 'when no configuration repo is specified' do\n      it 'does not ensure that the path for the configuration repository checkout is present' do\n        @whiskey_disk.should.not.receive(:ensure_config_parent_path_is_present)\n        @rake[\"deploy:setup\"].invoke        \n      end\n    end\n    \n    it 'checks out the main repository' do\n      @whiskey_disk.should.receive(:checkout_main_repository)\n      @rake[\"deploy:setup\"].invoke\n    end\n    \n    describe 'when a configuration repository is specified' do\n      it 'checks out the configuration repository' do\n        @whiskey_disk.configuration = { 'config_repository' => 'foo' }\n        @whiskey_disk.should.receive(:checkout_configuration_repository)\n        @rake[\"deploy:setup\"].invoke\n      end\n    end\n    \n    describe 'when no configuration repository is specified' do\n      it 'does not check out the configuration repository' do\n        @whiskey_disk.should.not.receive(:checkout_configuration_repository)\n        @rake[\"deploy:setup\"].invoke\n      end\n    end\n    \n    it 'updates the main repository checkout' do\n      @whiskey_disk.should.receive(:update_main_repository_checkout)\n      @rake[\"deploy:setup\"].invoke\n    end\n    \n    describe 'when a configuration repository is specified' do\n      it 'updates the configuration repository checkout' do\n        @whiskey_disk.configuration = { 'config_repository' => 'foo' }\n        @whiskey_disk.should.receive(:update_configuration_repository_checkout)\n        @rake[\"deploy:setup\"].invoke\n      end\n    end\n    \n    it 'clears any tracked git or rsync changes' do\n      @whiskey_disk.should.receive(:initialize_all_changes)\n      @rake[\"deploy:setup\"].invoke\n    end\n    \n    describe 'when no configuration repository is specified' do\n      it 'updates the configuration repository checkout' do\n        @whiskey_disk.should.not.receive(:update_configuration_repository_checkout)\n        @rake[\"deploy:setup\"].invoke\n      end\n    end\n\n    describe 'when a configuration repository is specified' do      \n      it 'refreshes the configuration' do\n        @whiskey_disk.configuration = { 'config_repository' => 'foo' }\n        @whiskey_disk.should.receive(:refresh_configuration)\n        @rake[\"deploy:setup\"].invoke\n      end\n    end\n    \n    describe 'when no configuration repository is specified' do      \n      it 'does not refresh the configuration' do\n        @whiskey_disk.should.not.receive(:refresh_configuration)\n        @rake[\"deploy:setup\"].invoke\n      end\n    end\n    \n    it 'runs any post setup hooks' do        \n      @whiskey_disk.should.receive(:run_post_setup_hooks)\n      @rake[\"deploy:setup\"].invoke\n    end\n    \n    it 'flushes @whiskey_disk changes' do\n      @whiskey_disk.should.receive(:flush)\n      @rake[\"deploy:setup\"].invoke\n    end\n    \n    it 'summarizes the results of the setup run' do\n      @whiskey_disk.should.receive(:summarize)\n      @rake[\"deploy:setup\"].invoke\n    end\n  \n    it 'does not exit in error if all setup runs were successful' do\n      lambda { @rake[\"deploy:setup\"].invoke }.should.not.raise(SystemExit)\n    end\n    \n    it 'exits in error if some setup run was unsuccessful' do\n      @whiskey_disk.stub!(:success?).and_return(false)\n      lambda { @rake[\"deploy:setup\"].invoke }.should.raise(SystemExit)\n    end\n  end\n  \n  describe 'deploy:now' do\n    before do\n      @whiskey_disk.configuration = { }\n      [ \n        :update_main_repository_checkout,\n        :update_configuration_repository_checkout,\n        :refresh_configuration,\n        :run_post_deploy_hooks,\n        :flush, \n        :summarize\n      ].each do |meth| \n        @whiskey_disk.stub!(meth) \n      end\n      \n      @whiskey_disk.stub!(:success?).and_return(true)\n    end\n    \n    it 'enables staleness checks' do\n      WhiskeyDisk.should.receive(:new).with(:staleness_checks => true).and_return(@whiskey_disk)      \n      @rake[\"deploy:now\"].invoke\n    end\n    \n    it 'updates the main repository checkout' do\n      @whiskey_disk.should.receive(:update_main_repository_checkout)\n      @rake[\"deploy:now\"].invoke\n    end\n    \n    describe 'when a configuration repository is specified' do\n      it 'updates the configuration repository checkout' do\n        @whiskey_disk.configuration = { 'config_repository' => 'foo' }\n        @whiskey_disk.should.receive(:update_configuration_repository_checkout)\n        @rake[\"deploy:now\"].invoke\n      end\n    end\n    \n    describe 'when no configuration repository is specified' do\n      it 'does not update the configuration repository checkout' do\n        @whiskey_disk.should.not.receive(:update_configuration_repository_checkout)\n        @rake[\"deploy:now\"].invoke\n      end\n    end\n    \n    describe 'when a configuration repository is specified' do\n      it 'refreshes the configuration' do\n        @whiskey_disk.configuration = { 'config_repository' => 'foo' }\n        @whiskey_disk.should.receive(:refresh_configuration)\n        @rake[\"deploy:now\"].invoke\n      end\n    end\n    \n    describe 'when no configuration repository is specified' do\n      it 'does not refresh the configuration' do\n        @whiskey_disk.should.not.receive(:refresh_configuration)\n        @rake[\"deploy:now\"].invoke\n      end\n    end\n    \n    it 'runs any post deployment hooks' do        \n      @whiskey_disk.should.receive(:run_post_deploy_hooks)\n      @rake[\"deploy:now\"].invoke\n    end\n    \n    it 'flushes @whiskey_disk changes' do\n      @whiskey_disk.should.receive(:flush)\n      @rake[\"deploy:now\"].invoke\n    end\n    \n    it 'summarizes the results of the deployment run' do\n      @whiskey_disk.should.receive(:summarize)\n      @rake[\"deploy:now\"].invoke\n    end\n    \n    it 'does not exit in error if all deployment runs were successful' do\n      lambda { @rake[\"deploy:now\"].invoke }.should.not.raise(SystemExit)\n    end\n    \n    it 'exits in error if some deployment run was unsuccessful' do\n      @whiskey_disk.stub!(:success?).and_return(false)\n      lambda { @rake[\"deploy:now\"].invoke }.should.raise(SystemExit)\n    end\n  end\n      \n  describe 'deploy:post_setup' do\n    it 'runs the defined post_setup rake task when a post_setup rake task is defined for this environment' do\n      @whiskey_disk.configuration = { 'environment' => 'production'}\n\n      task \"deploy:production:post_setup\" do\n        @whiskey_disk.fake_method\n      end\n\n      @whiskey_disk.should.receive(:fake_method)\n      Rake::Task['deploy:post_setup'].invoke\n    end\n\n    it 'does not fail when no post_setup rake task is defined for this environment' do\n      @whiskey_disk.configuration = { 'environment' => 'staging'}\n      lambda { Rake::Task['deploy:post_setup'].invoke }.should.not.raise\n    end\n  end\n  \n  describe 'deploy:post_deploy' do\n    it 'runs the defined post_deploy rake task when a post_deploy rake task is defined for this environment' do\n      @whiskey_disk.configuration = { 'environment' => 'production'}\n\n      task \"deploy:production:post_deploy\" do\n        @whiskey_disk.fake_method\n      end\n\n      @whiskey_disk.should.receive(:fake_method)\n      Rake::Task['deploy:post_deploy'].invoke\n    end\n\n    it 'does not fail when no post_deploy rake task is defined for this environment' do\n      @whiskey_disk.configuration = { 'environment' => 'staging'}\n      lambda { Rake::Task['deploy:post_deploy'].invoke }.should.not.raise\n    end\n  end\nend\n"
  },
  {
    "path": "spec/whiskey_disk_spec.rb",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper.rb'))\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'whiskey_disk'))\nrequire 'rake'\n\n# @whiskey_disk subclass that allows us to test in what order ssh commands are \n#   issued by @whiskey_disk.run\nclass TestOrderedExecution < WhiskeyDisk\n  class << self\n    def commands\n      result = @commands\n      @commands = []\n      result\n    end\n    \n    def system(*args)\n      @commands ||= []\n      @commands << args.join(' ')\n    end\n  end\nend\n\ndescribe 'requiring the main library' do\n  before do\n    Rake.application = @rake = Rake::Application.new\n    load File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'whiskey_disk', 'rake.rb'))\n  end\n\n  after do\n    Rake.application = nil\n  end\n\n  it 'makes the deploy:setup rake task available' do\n    Rake::Task.task_defined?('deploy:setup').should.be.true\n  end\n\n  it 'makes the deploy:now rake task available' do\n    Rake::Task.task_defined?('deploy:now').should.be.true\n  end\nend\n\ndescribe '@whiskey_disk' do\n  describe 'when initializing' do\n    it 'works without arguments' do\n      lambda { WhiskeyDisk.new }.should.not.raise(ArgumentError)\n    end\n    \n    it 'works with an options hash' do\n      lambda { WhiskeyDisk.new(:foo => 'bar') }.should.not.raise(ArgumentError)\n    end\n    \n    it 'saves the staleness checks state if enabled via the options hash' do\n      @whiskey_disk = WhiskeyDisk.new(:staleness_checks => true)\n      @whiskey_disk.staleness_checks_enabled?.should == true\n    end\n\n    it 'leaves staleness checks disabled if not enabled via the options hash' do\n      @whiskey_disk = WhiskeyDisk.new\n      @whiskey_disk.staleness_checks_enabled?.should == false\n    end\n\n    it 'leaves staleness checks disabled if disabled via the options hash' do\n      @whiskey_disk = WhiskeyDisk.new(:staleness_checks => false)\n      @whiskey_disk.staleness_checks_enabled?.should == false\n    end\n  end\n  \n  before do\n    @whiskey_disk = WhiskeyDisk.new\n  end\n  \n  describe 'determining if the deployment is remote' do\n    before do\n      @parameters = { 'deploy_to' => '/path/to/main/repo' }\n      @whiskey_disk.configuration = @parameters\n    end\n    \n    it 'allows a domain argument' do\n      lambda { @whiskey_disk.remote?('domain') }.should.not.raise(ArgumentError)\n    end\n    \n    it 'requires a domain argument' do\n      lambda { @whiskey_disk.remote? }.should.raise(ArgumentError)\n    end\n\n    describe 'when a domain limit is specified in the configuration' do\n      before do\n        @domain = 'myhost'\n        @config = WhiskeyDisk::Config.new\n        @config.stub!(:domain_limit).and_return(@domain)\n        @whiskey_disk.config = @config\n      end\n      \n      it 'returns false if the provided domain is nil' do\n        @whiskey_disk.remote?(nil).should == false\n      end\n\n      it 'returns false if the provided domain is the string \"local\"' do\n        @whiskey_disk.remote?('local').should == false\n      end\n\n      it 'returns false if the provided domain matches the limit domain from the configuration' do\n        @whiskey_disk.remote?(@domain).should == false\n      end\n\n      it 'returns false if the provided domain, ignoring any user@, matches the limit domain from the configuration' do\n        @whiskey_disk.remote?(\"user@\" + @domain).should == false\n      end\n\n      it 'returns true if the provided domain does not match the limit domain from the configuration' do\n        @whiskey_disk.remote?('smeghost').should == true\n      end\n    end\n    \n    describe 'when no domain limit is specified in the configuration' do\n      before do\n        @config = WhiskeyDisk::Config.new\n        @config.stub!(:domain_limit).and_return(nil)\n        @whiskey_disk.config = @config\n      end\n\n      it 'returns false if the provided domain is nil' do\n        @whiskey_disk.remote?(nil).should == false\n      end\n    \n      it 'returns false if the provided domain is the string \"local\"' do\n        @whiskey_disk.remote?('local').should == false\n      end\n\n      it 'returns true if the provided domain is non-empty' do\n        @whiskey_disk.remote?('smeghost').should == true\n      end\n    end\n  end\n  \n  describe 'determining if the deployment has a configuration repository' do\n    before do\n      @parameters = { 'deploy_to' => '/path/to/main/repo' }\n      @whiskey_disk.configuration = @parameters\n    end\n    \n    it 'works without arguments' do\n      lambda { @whiskey_disk.has_config_repo? }.should.not.raise(ArgumentError)\n    end\n    \n    it 'does not allow arguments' do\n      lambda { @whiskey_disk.has_config_repo?(:foo) }.should.raise(ArgumentError)\n    end\n    \n    it 'returns true if the configuration includes a non-empty config_repository setting' do\n      @parameters['config_repository'] = 'git://foo.git'\n      @whiskey_disk.has_config_repo?.should == true\n    end\n    \n    it 'returns false if the configuration includes a nil config_repository setting' do\n      @parameters['config_repository'] = nil\n      @whiskey_disk.has_config_repo?.should == false\n    end\n    \n    it 'returns false if the configuration includes a blank config_repository setting' do\n      @parameters['config_repository'] = ''\n      @whiskey_disk.has_config_repo?.should == false\n    end\n  end\n  \n  describe 'when checking staleness checks' do\n    it 'returns false if staleness checks have not been enabled' do\n      @whiskey_disk.staleness_checks_enabled?.should == false\n    end\n    \n    it 'returns true if staleness checks have been enabled' do\n      @whiskey_disk = WhiskeyDisk.new(:staleness_checks => true)\n      @whiskey_disk.staleness_checks_enabled?.should == true\n    end\n  end\n\n  describe 'ensuring that the parent path for the main repository checkout is present' do\n    before do\n      @whiskey_disk.configuration = { 'deploy_to' => '/path/to/main/repo' }\n    end\n    \n    it 'fails if the deployment path is not specified' do\n      @whiskey_disk.configuration = {}\n      lambda { @whiskey_disk.ensure_main_parent_path_is_present }.should.raise\n    end\n    \n    it 'attempts to create the parent path for the repository' do\n      @whiskey_disk.ensure_main_parent_path_is_present\n      @whiskey_disk.buffer.last.should.match(%r{mkdir -p /path/to/main})\n      @whiskey_disk.buffer.last.should.not.match(%r{/path/to/main/repo})\n    end\n  end\n\n  describe 'ensuring that the parent path for the configuration repository checkout is present' do\n    before do\n      @whiskey_disk.configuration = { 'deploy_config_to' => '/path/to/config/repo' }\n    end\n    \n    it 'fails if the configuration deployment path is not specified' do\n      @whiskey_disk.configuration = {}\n      lambda { @whiskey_disk.ensure_config_parent_path_is_present }.should.raise\n    end\n    \n    it 'attempts to create the parent path for the repository' do\n      @whiskey_disk.ensure_config_parent_path_is_present\n      @whiskey_disk.buffer.last.should.match(%r{mkdir -p /path/to/config})\n      @whiskey_disk.buffer.last.should.not.match(%r{/path/to/config/repo})\n    end\n  end\n  \n  describe 'checking out the main repository' do\n    before do\n      @parameters = { 'deploy_to' => '/path/to/main/repo', 'repository' => 'git@ogtastic.com:whiskey_disk.git' }\n      @whiskey_disk.configuration = @parameters\n    end\n    \n    it 'fails if the deployment path is not specified' do\n      @whiskey_disk.configuration = @parameters.merge('deploy_to' => nil)\n      lambda { @whiskey_disk.checkout_main_repository }.should.raise\n    end\n    \n    it 'fails if the repository is not specified' do\n      @whiskey_disk.configuration = @parameters.merge('repository' => nil)\n      lambda { @whiskey_disk.checkout_main_repository }.should.raise\n    end\n    \n    it 'works from the main repository checkout parent path' do\n      @whiskey_disk.checkout_main_repository\n      @whiskey_disk.buffer.join(' ').should.match(%r{cd /path/to/main[^/]})\n    end\n      \n    it 'attempts to clone the main repository to the repository checkout path' do\n      @whiskey_disk.checkout_main_repository\n      @whiskey_disk.buffer.join(' ').should.match(%r{clone #{@parameters['repository']} repo})\n    end\n    \n    it 'makes the main repository clone conditional on the lack of a main repository checkout' do\n      @whiskey_disk.checkout_main_repository\n      @whiskey_disk.buffer.join(' ').should.match(%r{if \\[ -e #{@parameters['deploy_to']} \\]; then .*; fi})\n    end\n    \n    it 'does a branch creation checkout of the master branch when no branch is specified' do\n      @whiskey_disk.checkout_main_repository\n      @whiskey_disk.buffer.join(' ').should.match(%r{git checkout -b master origin/master})\n    end\n    \n    it 'falls back to a regular checkout of the master branch with origin branch when no branch is specified' do\n      @whiskey_disk.checkout_main_repository\n      @whiskey_disk.buffer.join(' ').should.match(%r{\\|\\| git checkout master origin/master})\n    end\n    \n    it 'falls back to a regular checkout of the master branch when no branch is specified' do\n      @whiskey_disk.checkout_main_repository\n      @whiskey_disk.buffer.join(' ').should.match(%r{\\|\\| git checkout master origin/master \\|\\| git checkout master})\n    end\n    \n    it 'does a branch creation checkout of the specified branch when a branch is specified' do\n      @whiskey_disk.configuration = @parameters.merge({'branch' => 'production'})\n      @whiskey_disk.checkout_main_repository\n      @whiskey_disk.buffer.join(' ').should.match(%r{git checkout -b production origin/production})\n    end\n\n    it 'falls back to a regular checkout of the specified branch with origin branch when a branch is specified' do\n      @whiskey_disk.configuration = @parameters.merge({'branch' => 'production'})\n      @whiskey_disk.checkout_main_repository\n      @whiskey_disk.buffer.join(' ').should.match(%r{\\|\\| git checkout production origin/production})\n    end\n\n    it 'falls back to a regular checkout of the specified branch when a branch is specified' do\n      @whiskey_disk.configuration = @parameters.merge({'branch' => 'production'})\n      @whiskey_disk.checkout_main_repository\n      @whiskey_disk.buffer.join(' ').should.match(%r{\\|\\| git checkout production origin/production \\|\\| git checkout production})\n    end\n\n    it 'does branch checkouts from the repository path' do\n      @whiskey_disk.checkout_main_repository\n      @whiskey_disk.buffer.join(' ').should.match(%r{cd /path/to/main/repo && git checkout})      \n    end\n  end\n  \n  describe 'checking out the configuration repository' do\n    before do\n      @parameters = { 'deploy_config_to' => '/path/to/config/repo', 'config_repository' => 'git@ogtastic.com:config.git' }\n      @whiskey_disk.configuration = @parameters\n    end\n\n    it 'fails if the configuration deployment path is not specified' do\n      @whiskey_disk.configuration = @parameters.merge('deploy_config_to' => nil)\n      lambda { @whiskey_disk.checkout_configuration_repository }.should.raise\n    end\n\n    it 'fails if the configuration repository is not specified' do\n      @whiskey_disk.configuration = @parameters.merge('config_repository' => nil)\n      lambda { @whiskey_disk.checkout_configuration_repository }.should.raise\n    end\n\n    it 'works from the configuration repository checkout parent path' do\n      @whiskey_disk.checkout_configuration_repository\n      @whiskey_disk.buffer.join(' ').should.match(%r{cd /path/to/config[^/]})\n    end\n\n    it 'attempts to clone the configuration repository to the repository checkout path' do\n      @whiskey_disk.checkout_configuration_repository\n      @whiskey_disk.buffer.join(' ').should.match(%r{clone #{@parameters['config_repository']} repo})\n    end\n    \n    it 'makes the configuration repository clone conditional on the lack of a main repository checkout' do\n      @whiskey_disk.checkout_configuration_repository\n      @whiskey_disk.buffer.join(' ').should.match(%r{if \\[ -e #{@parameters['deploy_config_to']} \\]; then .*; fi})\n    end\n\n    it 'does a branch creation checkout of the master branch when no branch is specified' do\n      @whiskey_disk.checkout_configuration_repository\n      @whiskey_disk.buffer.join(' ').should.match(%r{git checkout -b master origin/master})\n    end\n    \n    it 'falls back to a regular checkout of the master branch with origin branch when no branch is specified' do\n      @whiskey_disk.checkout_configuration_repository\n      @whiskey_disk.buffer.join(' ').should.match(%r{\\|\\| git checkout master origin/master})\n    end\n    \n    it 'falls back to a regular checkout of the master branch when no branch is specified' do\n      @whiskey_disk.checkout_configuration_repository\n      @whiskey_disk.buffer.join(' ').should.match(%r{\\|\\| git checkout master origin/master \\|\\| git checkout master})\n    end\n    \n    it 'does a branch creation checkout of the specified branch when a branch is specified' do\n      @whiskey_disk.configuration = @parameters.merge({'config_branch' => 'production'})\n      @whiskey_disk.checkout_configuration_repository\n      @whiskey_disk.buffer.join(' ').should.match(%r{git checkout -b production origin/production})\n    end\n\n    it 'falls back to a regular checkout of the specified branch with origin branch when a branch is specified' do\n      @whiskey_disk.configuration = @parameters.merge({'config_branch' => 'production'})\n      @whiskey_disk.checkout_configuration_repository\n      @whiskey_disk.buffer.join(' ').should.match(%r{\\|\\| git checkout production origin/production})\n    end\n    \n    it 'falls back to a regular checkout of the specified branch when a branch is specified' do\n      @whiskey_disk.configuration = @parameters.merge({'config_branch' => 'production'})\n      @whiskey_disk.checkout_configuration_repository\n      @whiskey_disk.buffer.join(' ').should.match(%r{\\|\\| git checkout production origin/production \\|\\| git checkout production})\n    end\n    \n  end\n  \n  describe 'updating the main repository checkout' do\n    before do\n      @parameters = { 'deploy_to' => '/path/to/main/repo' }\n      @whiskey_disk.configuration = @parameters\n    end\n    \n    it 'fails if the deployment path is not specified' do\n      @whiskey_disk.configuration = @parameters.merge('deploy_to' => nil)\n      lambda { @whiskey_disk.update_main_repository_checkout }.should.raise\n    end\n    \n    it 'works from the main repository checkout path' do\n      @whiskey_disk.update_main_repository_checkout\n      @whiskey_disk.buffer.join(' ').should.match(%r{cd /path/to/main/repo})\n    end\n    \n    it 'clears out any existing git changes data' do\n      @whiskey_disk.update_main_repository_checkout\n      @whiskey_disk.buffer.join(' ').should.match(%r{rm -f /path/to/main/repo/.whiskey_disk_git_changes})\n    end\n        \n    it 'captures the current git HEAD ref for the current branch' do\n      @whiskey_disk.configuration = @parameters.merge({'branch' => 'production'})\n      @whiskey_disk.update_main_repository_checkout\n      @whiskey_disk.buffer.join(' ').should.match(%r{ml=\\`git log -1 --pretty=format:%H\\`})\n    end\n    \n    it 'captures the current git HEAD ref for the current branch if no branch is specified' do\n      @whiskey_disk.update_main_repository_checkout\n      @whiskey_disk.buffer.join(' ').should.match(%r{ml=\\`git log -1 --pretty=format:%H\\`})\n    end\n    \n    it 'attempts to fetch only the master branch from the origin if no branch is specified' do\n      @whiskey_disk.update_main_repository_checkout\n      @whiskey_disk.buffer.join(' ').should.match(%r{git fetch origin \\+refs/heads/master:refs/remotes/origin/master})\n    end\n    \n    it 'attempts to fetch the specified branch from the origin if a branch is specified' do\n      @whiskey_disk.configuration = @parameters.merge({'branch' => 'production'})\n      @whiskey_disk.update_main_repository_checkout\n      @whiskey_disk.buffer.join(' ').should.match(%r{git fetch origin \\+refs/heads/production:refs/remotes/origin/production})\n    end\n\n    it 'works from the default branch if no branch is specified' do\n      @whiskey_disk.update_main_repository_checkout\n      @whiskey_disk.buffer.join(' ').should.match(%r{git checkout master})\n    end\n\n    it 'works from the specified branch if one is specified' do\n      @whiskey_disk.configuration = @parameters.merge({'branch' => 'production'})\n      @whiskey_disk.update_main_repository_checkout\n      @whiskey_disk.buffer.join(' ').should.match(%r{git checkout production})\n    end\n\n    it 'attempts to reset the master branch from the origin if no branch is specified' do\n      @whiskey_disk.update_main_repository_checkout\n      @whiskey_disk.buffer.join(' ').should.match(%r{git reset --hard origin/master})\n    end\n    \n    it 'attempts to reset the specified branch from the origin if a branch is specified' do\n      @whiskey_disk.configuration = @parameters.merge({'branch' => 'production'})\n      @whiskey_disk.update_main_repository_checkout\n      @whiskey_disk.buffer.join(' ').should.match(%r{git reset --hard origin/production})\n    end\n    \n    it 'collects git changes data' do\n      @whiskey_disk.update_main_repository_checkout\n      @whiskey_disk.buffer.join(' ').should.match(%r{git diff --name-only \\$\\{ml\\}\\.\\.HEAD > /path/to/main/repo/\\.whiskey_disk_git_changes})\n    end\n  end\n  \n  describe 'updating the configuration repository checkout' do\n    before do\n      @parameters = { 'deploy_config_to' => '/path/to/config/repo', 'deploy_to' => '/path/to/main/repo' }\n      @whiskey_disk.configuration = @parameters\n    end\n    \n    it 'fails if the configuration deployment path is not specified' do\n      @whiskey_disk.configuration = @parameters.merge('deploy_config_to' => nil)\n      lambda { @whiskey_disk.update_configuration_repository_checkout }.should.raise\n    end\n    \n    it 'works from the main repository checkout path' do\n      @whiskey_disk.update_configuration_repository_checkout\n      @whiskey_disk.buffer.join(' ').should.match(%r{cd /path/to/config/repo})\n    end\n    \n    it 'clears out any existing rsync changes data' do\n      @whiskey_disk.update_configuration_repository_checkout\n      @whiskey_disk.buffer.join(' ').should.match(%r{rm -f /path/to/main/repo/.whiskey_disk_rsync_changes})\n    end\n    \n    it 'attempts to fetch only the master branch from the origin if no configuration branch is specified' do\n      @whiskey_disk.update_configuration_repository_checkout\n      @whiskey_disk.buffer.join(' ').should.match(%r{git fetch origin \\+refs/heads/master:refs/remotes/origin/master})\n    end\n    \n    it 'attempts to fetch the specified branch from the origin if a configuration branch is specified' do\n      @whiskey_disk.configuration = @parameters.merge({'config_branch' => 'production'})\n      @whiskey_disk.update_configuration_repository_checkout\n      @whiskey_disk.buffer.join(' ').should.match(%r{git fetch origin \\+refs/heads/production:refs/remotes/origin/production})\n    end\n    \n    it 'attempts to reset the master branch from the origin if no configuration branch is specified' do\n      @whiskey_disk.update_configuration_repository_checkout\n      @whiskey_disk.buffer.join(' ').should.match(%r{git reset --hard origin/master})\n    end\n\n    it 'attempts to reset the master branch from the origin if no configuration branch is specified' do\n      @whiskey_disk.configuration = @parameters.merge({'config_branch' => 'production'})\n      @whiskey_disk.update_configuration_repository_checkout\n      @whiskey_disk.buffer.join(' ').should.match(%r{git reset --hard origin/production})\n    end\n  end\n  \n  describe 'refreshing the configuration' do\n    before do\n      @parameters = { 'deploy_to' => '/path/to/main/repo', \n                      'deploy_config_to' => '/path/to/config/repo',\n                      'environment' => 'production',\n                      'config_repository' => 'git@git://foo.bar.git',\n                      'config_branch' => 'master',\n                      'config_target' => 'staging',\n                      'project' => 'whiskey_disk' }\n      @whiskey_disk.configuration = @parameters\n    end\n\n    it 'fails if the main deployment path is not specified' do\n      @whiskey_disk.configuration = @parameters.merge('deploy_to' => nil)\n      lambda { @whiskey_disk.refresh_configuration }.should.raise\n    end\n  \n    it 'fails if the configuration deployment path is not specified' do\n      @whiskey_disk.configuration = @parameters.merge('deploy_config_to' => nil)\n      lambda { @whiskey_disk.refresh_configuration }.should.raise\n    end\n  \n    it 'fails if no project name was specified' do\n      @whiskey_disk.configuration = @parameters.merge('project' => 'unnamed_project')\n      lambda { @whiskey_disk.refresh_configuration }.should.raise      \n    end\n  \n    it 'uses rsync to overlay the configuration checkout for the project in the config target onto the main checkout' do\n      @whiskey_disk.refresh_configuration\n      @whiskey_disk.buffer.last.should.match(%r{rsync.* /path/to/config/repo/whiskey_disk/staging/ /path/to/main/repo/})\n    end\n    \n    it 'captures rsync change data' do\n      @whiskey_disk.refresh_configuration\n      @whiskey_disk.buffer.last.should.match(%r{rsync.* --log-format=\"%t \\[%p\\] %i %n\".*> /path/to/main/repo/.whiskey_disk_rsync_changes})\n    end\n  end\n\n  describe 'running post setup hooks' do\n    before do\n      @whiskey_disk.configuration = { 'deploy_to' => '/path/to/main/repo' }\n      ENV['debug'] = nil\n    end\n    \n    it 'fails if the deployment path is not specified' do\n      @whiskey_disk.configuration = {}\n      lambda { @whiskey_disk.run_post_setup_hooks }.should.raise\n    end\n    \n    it 'works from the main checkout directory' do\n      @whiskey_disk.run_post_setup_hooks\n      @whiskey_disk.buffer.join(' ').should.match(%r{cd /path/to/main/repo})\n    end\n    \n    describe 'when a post setup script is specified' do\n      describe 'and the script path does not start with a \"/\"' do      \n        before do\n          @whiskey_disk.configuration = { 'deploy_to' => '/path/to/main/repo', 'post_setup_script' => 'path/to/setup/script', 'rake_env' => { 'FOO' => 'BAR' }  }\n        end\n      \n        it 'cds to the deploy_to path prior to running the script' do\n          @whiskey_disk.run_post_setup_hooks\n          @whiskey_disk.buffer.join(' ').should.match(%r{cd /path/to/main/repo;.*bash  /path/to/main/repo/path/to/setup/script})\n        end\n\n        it 'attempts to run the post setup script with the deployment path prepended' do        \n          @whiskey_disk.run_post_setup_hooks\n          @whiskey_disk.buffer.join(' ').should.match(%r{bash  /path/to/main/repo/path/to/setup/script})\n        end\n      \n        it 'passes any environment variables when running the post setup script' do\n          @whiskey_disk.run_post_setup_hooks\n          @whiskey_disk.buffer.join(' ').should.match(%r{FOO='BAR'  bash  /path/to/main/repo/path/to/setup/script})      \n        end\n\n        it 'enables shell verbosity when debugging is enabled' do\n          ENV['debug'] = 'true'\n          @whiskey_disk.run_post_setup_hooks\n          @whiskey_disk.buffer.join(' ').should.match(%r{bash -x /path/to/main/repo/path/to/setup/script})      \n        end\n\n        it 'disables shell verbosity when debugging is not enabled' do\n          ENV['debug'] = 'false'\n          @whiskey_disk.run_post_setup_hooks\n          @whiskey_disk.buffer.join(' ').should.match(%r{bash  /path/to/main/repo/path/to/setup/script})      \n        end\n      end\n      \n      describe 'and the script path starts with a \"/\"' do\n        before do\n          @whiskey_disk.configuration = { 'deploy_to' => '/path/to/main/repo', 'post_setup_script' => '/path/to/setup/script', 'rake_env' => { 'FOO' => 'BAR' } }\n        end\n\n        it 'cds to the deploy_to path prior to running the script' do\n          @whiskey_disk.run_post_setup_hooks\n          @whiskey_disk.buffer.join(' ').should.match(%r{cd /path/to/main/repo;.*bash  /path/to/setup/script})\n        end\n      \n        it 'runs the post setup script using its absolute path' do\n          @whiskey_disk.run_post_setup_hooks\n          @whiskey_disk.buffer.join(' ').should.match(%r{bash  /path/to/setup/script})\n        end\n\n        it 'passes any environment variables when running the post setup script' do\n          @whiskey_disk.run_post_setup_hooks\n          @whiskey_disk.buffer.join(' ').should.match(%r{FOO='BAR'  bash  /path/to/setup/script})      \n        end\n\n        it 'enables shell verbosity when debugging is enabled' do\n          ENV['debug'] = 'true'\n          @whiskey_disk.run_post_setup_hooks\n          @whiskey_disk.buffer.join(' ').should.match(%r{bash -x /path/to/setup/script})      \n        end\n\n        it 'disables shell verbosity when debugging is not enabled' do\n          ENV['debug'] = 'false'\n          @whiskey_disk.run_post_setup_hooks\n          @whiskey_disk.buffer.join(' ').should.match(%r{bash  /path/to/setup/script})      \n        end\n      end\n    end\n        \n    it 'attempts to run the post setup rake tasks' do\n      @whiskey_disk.run_post_setup_hooks\n      @whiskey_disk.buffer.join(' ').should.match(%r{rake.*deploy:post_setup})\n    end\n    \n    it 'uses the same environment when running the rake tasks' do\n      @whiskey_disk.run_post_setup_hooks\n      @whiskey_disk.buffer.join(' ').should.match(%r{to=#{@env}})      \n    end\n    \n    it 'makes the post setup rake tasks conditional on the presence of a Rakefile in the deployment path' do      \n      @whiskey_disk.run_post_setup_hooks\n      @whiskey_disk.buffer.join(' ').should.match(%r{if \\[ -e /path/to/main/repo/Rakefile \\]; then .*; fi})\n    end\n    \n    it 'makes the post setup rake tasks conditional on the deploy:post_setup rake task being defined' do\n      @whiskey_disk.run_post_setup_hooks\n      @whiskey_disk.buffer.join(' ').should.match(%r{rakep=\\`.*rake -P\\` && if \\[\\[ \\`echo \"\\$\\{rakep\\}\" | grep deploy:post_setup\\` != \"\" \\]\\];})      \n    end\n\n    it 'ensures that any rake ENV variable are set when checking for deploy:post_setup tasks' do\n      @parameters = { 'deploy_to' => '/path/to/main/repo', 'rake_env' => { 'RAILS_ENV' => 'production', 'FOO' => 'bar' } }\n      @whiskey_disk.configuration = @parameters\n      @whiskey_disk.run_post_setup_hooks\n      @parameters['rake_env'].each_pair do |k,v|\n        @whiskey_disk.buffer.join(' ').should.match(%r{#{k}='#{v}' .*rake -P})\n      end\n    end\n    \n    it 'sets any rake_env variables when running the rake tasks' do\n      @parameters = { 'deploy_to' => '/path/to/main/repo', 'rake_env' => { 'RAILS_ENV' => 'production', 'FOO' => 'bar' } }\n      @whiskey_disk.configuration = @parameters\n      @whiskey_disk.run_post_setup_hooks\n      @parameters['rake_env'].each_pair do |k,v|\n        @whiskey_disk.buffer.join(' ').should.match(%r{#{k}='#{v}' })\n      end\n    end\n  end\n  \n  describe 'running post deployment hooks' do\n    before do\n      @whiskey_disk.configuration = { 'deploy_to' => '/path/to/main/repo' }\n      ENV['debug'] = nil\n    end\n    \n    it 'fails if the deployment path is not specified' do\n      @whiskey_disk.configuration = {}\n      lambda { @whiskey_disk.run_post_deploy_hooks }.should.raise\n    end\n    \n    it 'works from the main checkout directory' do\n      @whiskey_disk.run_post_deploy_hooks\n      @whiskey_disk.buffer.join(' ').should.match(%r{cd /path/to/main/repo})\n    end\n    \n    describe 'when a post deployment script is specified' do\n      describe 'and the script path does not start with a \"/\"' do      \n        before do\n          @whiskey_disk.configuration = { 'deploy_to' => '/path/to/main/repo', 'post_deploy_script' => 'path/to/deployment/script', 'rake_env' => { 'FOO' => 'BAR' }  }\n        end\n      \n        it 'cds to the deploy_to path prior to running the script' do\n          @whiskey_disk.run_post_deploy_hooks\n          @whiskey_disk.buffer.join(' ').should.match(%r{cd /path/to/main/repo;.*bash  /path/to/main/repo/path/to/deployment/script})\n        end\n\n        it 'attempts to run the post deployment script with the deployment path prepended' do        \n          @whiskey_disk.run_post_deploy_hooks\n          @whiskey_disk.buffer.join(' ').should.match(%r{bash  /path/to/main/repo/path/to/deployment/script})\n        end\n        \n        it 'passes any environment variables when running the post deploy script' do\n          @whiskey_disk.run_post_deploy_hooks\n          @whiskey_disk.buffer.join(' ').should.match(%r{FOO='BAR'  bash  /path/to/main/repo/path/to/deployment/script})      \n        end\n\n        it 'enables shell verbosity when debugging is enabled' do\n          ENV['debug'] = 'true'\n          @whiskey_disk.run_post_deploy_hooks\n          @whiskey_disk.buffer.join(' ').should.match(%r{bash -x /path/to/main/repo/path/to/deployment/script})\n        end\n\n        it 'disables shell verbosity when debugging is not enabled' do\n          ENV['debug'] = 'false'\n          @whiskey_disk.run_post_deploy_hooks\n          @whiskey_disk.buffer.join(' ').should.match(%r{bash  /path/to/main/repo/path/to/deployment/script})\n        end\n      end\n      \n      describe 'and the script path starts with a \"/\"' do\n        before do\n          @whiskey_disk.configuration = { 'deploy_to' => '/path/to/main/repo', 'post_deploy_script' => '/path/to/deployment/script', 'rake_env' => { 'FOO' => 'BAR' }  }\n        end\n\n        it 'cds to the deploy_to path prior to running the script' do\n          @whiskey_disk.run_post_deploy_hooks\n          @whiskey_disk.buffer.join(' ').should.match(%r{cd /path/to/main/repo;.*bash  /path/to/deployment/script})\n        end\n\n        it 'attempts to run the post deployment script using its absolute path' do        \n          @whiskey_disk.run_post_deploy_hooks\n          @whiskey_disk.buffer.join(' ').should.match(%r{bash  /path/to/deployment/script})\n        end\n      \n        it 'passes any environment variables when running the post deploy script' do\n          @whiskey_disk.run_post_deploy_hooks\n          @whiskey_disk.buffer.join(' ').should.match(%r{FOO='BAR'  bash  /path/to/deployment/script})      \n        end\n\n        it 'enables shell verbosity when debugging is enabled' do\n          ENV['debug'] = 'true'\n          @whiskey_disk.run_post_deploy_hooks\n          @whiskey_disk.buffer.join(' ').should.match(%r{bash -x /path/to/deployment/script})      \n        end\n\n        it 'disables shell verbosity when debugging is not enabled' do\n          ENV['debug'] = 'false'\n          @whiskey_disk.run_post_deploy_hooks\n          @whiskey_disk.buffer.join(' ').should.match(%r{bash  /path/to/deployment/script})      \n        end\n      end\n    end\n        \n    it 'attempts to run the post deployment rake tasks' do\n      @whiskey_disk.run_post_deploy_hooks\n      @whiskey_disk.buffer.join(' ').should.match(%r{rake.*deploy:post_deploy})\n    end\n    \n    it 'uses the same environment when running the rake tasks' do\n      @whiskey_disk.run_post_deploy_hooks\n      @whiskey_disk.buffer.join(' ').should.match(%r{to=#{@env}})      \n    end\n\n    it 'makes the post deployment rake tasks conditional on the presence of a Rakefile in the deployment path' do      \n      @whiskey_disk.run_post_deploy_hooks\n      @whiskey_disk.buffer.join(' ').should.match(%r{if \\[ -e /path/to/main/repo/Rakefile \\]; then .*; fi})\n    end\n    \n    it 'makes the post deployment rake tasks conditional on the deploy:post_deploy rake task being defined' do\n      @whiskey_disk.run_post_deploy_hooks\n      @whiskey_disk.buffer.join(' ').should.match(%r{rakep=\\`.*rake -P\\` && if \\[\\[ \\`echo \"\\$\\{rakep\\}\" | grep deploy:post_deploy\\` != \"\" \\]\\];})      \n    end\n\n    it 'ensures that any rake ENV variable are set when checking for deploy:post_setup tasks' do\n      @parameters = { 'deploy_to' => '/path/to/main/repo', 'rake_env' => { 'RAILS_ENV' => 'production', 'FOO' => 'bar' } }\n      @whiskey_disk.configuration = @parameters\n      @whiskey_disk.run_post_deploy_hooks\n      @parameters['rake_env'].each_pair do |k,v|\n        @whiskey_disk.buffer.join(' ').should.match(%r{#{k}='#{v}' .*rake -P})\n      end\n    end\n    \n    it 'sets any rake_env variables when running the rake tasks' do\n      @parameters = { 'deploy_to' => '/path/to/main/repo', 'rake_env' => { 'RAILS_ENV' => 'production', 'FOO' => 'bar' } }\n      @whiskey_disk.configuration = @parameters\n      @whiskey_disk.run_post_deploy_hooks\n      @parameters['rake_env'].each_pair do |k,v|\n        @whiskey_disk.buffer.join(' ').should.match(%r{#{k}='#{v}' })\n      end\n    end\n  end\n  \n  describe 'bundling up buffered commands for execution' do\n    describe 'when staleness checks are disabled' do\n      it 'returns an empty string if there are no commands' do\n        @whiskey_disk.bundle.should == ''\n      end\n\n      it 'wraps each command with {} and join with &&s' do\n        @whiskey_disk.enqueue(\"cd foo/bar/baz || true\")\n        @whiskey_disk.enqueue(\"rsync -avz --progress /yer/mom /yo/\")\n        @whiskey_disk.bundle.should == \"{ cd foo/bar/baz || true ; } && { rsync -avz --progress /yer/mom /yo/ ; }\"\n      end\n\n      it 'does not wrap the bundled commands inside a staleness check' do\n        @whiskey_disk.enqueue(\"cd foo/bar/baz || true\")\n        @whiskey_disk.enqueue(\"rsync -avz --progress /yer/mom /yo/\")\n        @whiskey_disk.bundle.should == \"{ cd foo/bar/baz || true ; } && { rsync -avz --progress /yer/mom /yo/ ; }\"\n      end\n    end\n\n    describe 'when staleness checks are enabled' do\n      before do\n        @whiskey_disk = WhiskeyDisk.new(:staleness_checks => true)\n      end\n      \n      describe 'but not we are not configured for staleness checks on this deployment' do\n        before do\n          ENV['check'] = nil\n        end\n        \n        it 'returns an empty string if there are no commands' do\n          @whiskey_disk.bundle.should == ''\n        end\n\n        it 'wraps each command with {} and join with &&s' do\n          @whiskey_disk.enqueue(\"cd foo/bar/baz || true\")\n          @whiskey_disk.enqueue(\"rsync -avz --progress /yer/mom /yo/\")\n          @whiskey_disk.bundle.should == \"{ cd foo/bar/baz || true ; } && { rsync -avz --progress /yer/mom /yo/ ; }\"\n        end\n\n        it 'does not wrap the bundled commands inside a staleness check' do\n          @whiskey_disk.enqueue(\"cd foo/bar/baz || true\")\n          @whiskey_disk.enqueue(\"rsync -avz --progress /yer/mom /yo/\")\n          @whiskey_disk.bundle.should == \"{ cd foo/bar/baz || true ; } && { rsync -avz --progress /yer/mom /yo/ ; }\"\n        end       \n      end\n      \n      describe 'and we are configured for staleness checks on this deployment' do\n        before do\n          ENV['check'] = 'true'\n        end\n        \n        describe 'when no configuration repository is in use' do\n          before do\n            @deploy_to = '/path/to/main/repo'\n            @repository = 'git@git://foo.bar.git'\n            @parameters = { 'deploy_to' => @deploy_to, 'repository' => @repository }\n            @whiskey_disk.configuration = @parameters\n          end\n          \n          it 'returns an empty string if there are no commands' do\n            @whiskey_disk.bundle.should == ''\n          end\n\n          it 'wraps each command with {} and join with &&s' do\n            @whiskey_disk.enqueue(\"cd foo/bar/baz || true\")\n            @whiskey_disk.enqueue(\"rsync -avz --progress /yer/mom /yo/\")\n            @whiskey_disk.bundle.should.match(Regexp.new(Regexp.escape(\"{ cd foo/bar/baz || true ; } && { rsync -avz --progress /yer/mom /yo/ ; }\")))\n          end\n\n          it 'wraps the bundled commands inside a staleness check which checks only the main repo for staleness' do\n            @whiskey_disk.enqueue(\"COMMAND\")\n            @whiskey_disk.bundle.should.match(Regexp.new(Regexp.escape(\"if [[ $ml != ${mr%%\\t*} ]] ; then { COMMAND ; }\")))\n          end\n          \n          it 'adds a notice message for when the repository is not stale' do\n            @whiskey_disk.enqueue(\"COMMAND\")\n            @whiskey_disk.bundle.should.match(Regexp.new(Regexp.escape(\"then { COMMAND ; }; else echo \\\"No changes to deploy.\\\"; fi\")))            \n          end\n          \n          it \"queries the head of the main checkout's current branch if no branch is specified\" do\n            @whiskey_disk.enqueue(\"COMMAND\")\n            @whiskey_disk.bundle.should.match(Regexp.new(Regexp.escape(\"cd #{@deploy_to}; ml=\\`git log -1 --pretty=format:%H\\`;\")))\n          end\n          \n          it \"queries the head of the main checkout's current branch if a branch is specified\" do\n            @whiskey_disk.configuration = @parameters.merge({'branch' => 'production'})\n            @whiskey_disk.enqueue(\"COMMAND\")\n            @whiskey_disk.bundle.should.match(Regexp.new(Regexp.escape(\"cd #{@deploy_to}; ml=\\`git log -1 --pretty=format:%H\\`;\")))\n          end\n          \n          it \"queries the head on the main repository's master branch if no branch is specified\" do            \n            @whiskey_disk.enqueue(\"COMMAND\")\n            @whiskey_disk.bundle.should.match(Regexp.new(Regexp.escape(\"mr=\\`git ls-remote #{@repository} refs/heads/master\\`;\")))\n          end\n          \n          it \"queries the head of the main repository's specified branch if a branch is specified\" do\n            @whiskey_disk.configuration = @parameters.merge({'branch' => 'production'})\n            @whiskey_disk.enqueue(\"COMMAND\")\n            @whiskey_disk.bundle.should.match(Regexp.new(Regexp.escape(\"mr=\\`git ls-remote #{@repository} refs/heads/production\\`;\")))\n          end\n          \n          it 'does not check a configuration repository for staleness' do\n            @whiskey_disk.enqueue(\"COMMAND\")\n            @whiskey_disk.bundle.should.not.match(/c[lr]=/)\n          end\n        end\n      \n        describe 'when a configuration repository is in use' do\n          before do\n            @deploy_to = '/path/to/main/repo'\n            @repository = 'git@git://foo.bar.git'\n            @deploy_config_to = '/path/to/config/repo'\n            @config_repository = 'git@git://foo.bar-config.git'\n            @parameters = { \n              'deploy_to' => @deploy_to, 'repository' => @repository,\n              'deploy_config_to' => @deploy_config_to, 'config_repository' => @config_repository\n            }\n            @whiskey_disk.configuration = @parameters\n          end\n          \n          it 'returns an empty string if there are no commands' do\n            @whiskey_disk.bundle.should == ''\n          end\n\n          it 'wraps each command with {} and join with &&s' do\n            @whiskey_disk.enqueue(\"cd foo/bar/baz || true\")\n            @whiskey_disk.enqueue(\"rsync -avz --progress /yer/mom /yo/\")\n            @whiskey_disk.bundle.should.match(Regexp.new(Regexp.escape(\"{ cd foo/bar/baz || true ; } && { rsync -avz --progress /yer/mom /yo/ ; }\")))\n          end\n\n          it 'wraps the bundled commands inside a staleness check which checks both main and config repos for staleness' do\n            @whiskey_disk.enqueue(\"COMMAND\")\n            @whiskey_disk.bundle.should.match(Regexp.new(Regexp.escape(\"if [[ $ml != ${mr%%\\t*} ]] || [[ $cl != ${cr%%\\t*} ]]; then { COMMAND ; }\")))\n          end\n          \n          it 'adds a notice message for when the repositories are not stale' do\n            @whiskey_disk.enqueue(\"COMMAND\")\n            @whiskey_disk.bundle.should.match(Regexp.new(Regexp.escape(\"then { COMMAND ; }; else echo \\\"No changes to deploy.\\\"; fi\")))            \n          end\n          \n          it \"queries the head of the main checkout's current branch if no branch is specified\" do\n            @whiskey_disk.enqueue(\"COMMAND\")\n            @whiskey_disk.bundle.should.match(Regexp.new(Regexp.escape(\"cd #{@deploy_to}; ml=\\`git log -1 --pretty=format:%H\\`;\")))\n          end\n          \n          it \"queries the head of the main checkout's current branch if a branch is specified\" do\n            @whiskey_disk.configuration = @parameters.merge({'branch' => 'production'})\n            @whiskey_disk.enqueue(\"COMMAND\")\n            @whiskey_disk.bundle.should.match(Regexp.new(Regexp.escape(\"cd #{@deploy_to}; ml=\\`git log -1 --pretty=format:%H\\`;\")))\n          end\n          \n          it \"queries the head on the main repository's master branch if no branch is specified\" do            \n            @whiskey_disk.enqueue(\"COMMAND\")\n            @whiskey_disk.bundle.should.match(Regexp.new(Regexp.escape(\"mr=\\`git ls-remote #{@repository} refs/heads/master\\`;\")))\n          end\n          \n          it \"queries the head of the main repository's specified branch if a branch is specified\" do\n            @whiskey_disk.configuration = @parameters.merge({'branch' => 'production'})\n            @whiskey_disk.enqueue(\"COMMAND\")\n            @whiskey_disk.bundle.should.match(Regexp.new(Regexp.escape(\"mr=\\`git ls-remote #{@repository} refs/heads/production\\`;\")))\n          end\n          \n          it \"queries the head of the config checkout's current branch if no branch is specified\" do\n            @whiskey_disk.enqueue(\"COMMAND\")\n            @whiskey_disk.bundle.should.match(Regexp.new(Regexp.escape(\"cd #{@deploy_config_to}; cl=\\`git log -1 --pretty=format:%H\\`;\")))\n          end\n          \n          it \"queries the head of the config checkout's current branch if a branch is specified\" do\n            @whiskey_disk.configuration = @parameters.merge({'config_branch' => 'production'})\n            @whiskey_disk.enqueue(\"COMMAND\")\n            @whiskey_disk.bundle.should.match(Regexp.new(Regexp.escape(\"cd #{@deploy_config_to}; cl=\\`git log -1 --pretty=format:%H\\`;\")))\n          end\n          \n          it \"queries the head on the config repository's master branch if no branch is specified\" do            \n            @whiskey_disk.enqueue(\"COMMAND\")\n            @whiskey_disk.bundle.should.match(Regexp.new(Regexp.escape(\"cr=\\`git ls-remote #{@config_repository} refs/heads/master\\`;\")))\n          end\n          \n          it \"queries the head of the config repository's specified branch if a branch is specified\" do\n            @whiskey_disk.configuration = @parameters.merge({'config_branch' => 'production'})\n            @whiskey_disk.enqueue(\"COMMAND\")\n            @whiskey_disk.bundle.should.match(Regexp.new(Regexp.escape(\"cr=\\`git ls-remote #{@config_repository} refs/heads/production\\`;\")))\n          end\n        end\n      end\n    end\n  end\n  \n  describe 'determining if a domain is of interest to us' do\n    before do\n      @config = WhiskeyDisk::Config.new\n      @config.stub!(:domain_limit).and_return(false)\n      @whiskey_disk.config = @config\n    end\n    \n    it 'allows specifying a domain' do\n      lambda { @whiskey_disk.domain_of_interest?(:domain) }.should.not.raise(ArgumentError)\n    end\n    \n    it 'requires a domain' do\n      lambda { @whiskey_disk.domain_of_interest? }.should.raise(ArgumentError)      \n    end\n    \n    it 'returns true when our configuration does not specify a domain limit' do\n      @config.stub!(:domain_limit).and_return(false)\n      @whiskey_disk.domain_of_interest?('somedomain').should == true\n    end\n    \n    it 'returns true when the specified domain matches the configuration domain limit' do\n      @config.stub!(:domain_limit).and_return('somedomain')\n      @whiskey_disk.domain_of_interest?('somedomain').should == true      \n    end\n    \n    it 'returns true when the specified domain matches the configuration domain limit, with a prepended \"user@\"' do\n      @config.stub!(:domain_limit).and_return('somedomain')\n      @whiskey_disk.domain_of_interest?('user@somedomain').should == true      \n    end    \n    \n    it 'returns false when the specified domain does not match the configuration domain limit' do\n      @config.stub!(:domain_limit).and_return('otherdomain')\n      @whiskey_disk.domain_of_interest?('somedomain').should == false  \n    end\n  end\n\n  describe 'flushing changes' do\n    before do\n      @cmd = 'ls'\n      @domains = [ { 'name' => 'ogc@ogtastic.com' }, { 'name' => 'foo@example.com' }, { 'name' => 'local' } ]\n      @whiskey_disk.configuration = { 'domain' => @domains }\n      @whiskey_disk.stub!(:domain_of_interest?).and_return(true)\n      @whiskey_disk.stub!(:bundle).and_return(@cmd)\n      @whiskey_disk.stub!(:system)\n      @whiskey_disk.stub!(:puts)\n    end\n          \n    it 'fails if the domain path is not specified' do\n      @whiskey_disk.configuration = {}\n      lambda { @whiskey_disk.flush}.should.raise\n    end\n\n    it 'uses \"run\" to issue commands for all remote domains' do\n      @whiskey_disk.should.receive(:run).with({ 'name' => 'ogc@ogtastic.com' }, @cmd)\n      @whiskey_disk.should.receive(:run).with({ 'name' => 'foo@example.com' }, @cmd)\n      @whiskey_disk.flush\n    end\n    \n    it 'uses \"shell\" to issue commands for any local domains' do\n      @whiskey_disk.should.receive(:shell).with({ 'name' => 'local' }, @cmd)\n      @whiskey_disk.flush      \n    end    \n\n    it 'does not issue a command via run for a remote domain which is not of interest' do\n      @whiskey_disk.stub!(:domain_of_interest?).with('ogc@ogtastic.com').and_return(false)\n      @whiskey_disk.should.not.receive(:run).with({ 'name' => 'ogc@ogtastic.com' }, @cmd)\n      @whiskey_disk.flush\n    end\n\n    it 'does not issue a command via shell for a local domain which is not of interest' do\n      @whiskey_disk.stub!(:domain_of_interest?).with('local').and_return(false)\n      @whiskey_disk.should.not.receive(:shell).with({ 'name' => 'local' }, @cmd)\n      @whiskey_disk.flush\n    end\n  end\n  \n  describe 'when running a command string locally' do\n    before do\n      @domain_name = 'local'\n      @domain = { 'name' => @domain_name }\n      @whiskey_disk.configuration = { 'domain' => [ @domain ] }\n      @whiskey_disk.stub!(:system)\n      @whiskey_disk.stub!(:puts)\n    end\n    \n    it 'accepts a domain and a command string' do\n      lambda { @whiskey_disk.shell(@domain, 'ls') }.should.not.raise(ArgumentError)\n    end\n    \n    it 'requires a domain and a command string' do\n      lambda { @whiskey_disk.shell(@domain) }.should.raise(ArgumentError)\n    end\n    \n    describe 'when debugging is enabled' do\n      before { ENV['debug'] = 'true' }\n\n      it 'passes the string to the shell with verbosity enabled' do\n        @whiskey_disk.should.receive(:system).with('bash', '-c', \"set -x; ls\")\n        @whiskey_disk.shell(@domain, 'ls')\n      end\n      \n      it 'includes domain role settings when the domain has roles' do\n        @domain = { 'name' => @domain_name, 'roles' => [ 'web', 'db' ] }\n        @whiskey_disk.configuration = { 'domain' => [ @domain ] }\n        @whiskey_disk.should.receive(:system).with('bash', '-c', \"set -x; export WD_ROLES='web:db'; ls\")\n        @whiskey_disk.shell(@domain, 'ls')        \n      end\n    end\n    \n    describe 'when debugging is not enabled' do\n      before { ENV['debug'] = 'false' }\n\n      it 'passes the string to the shell without verbosity enabled' do\n        @whiskey_disk.should.receive(:system).with('bash', '-c', \"ls\")\n        @whiskey_disk.shell(@domain, 'ls')\n      end\n      \n      it 'includes domain role settings when the domain has roles' do\n        @domain = { 'name' => @domain_name, 'roles' => [ 'web', 'db' ] }\n        @whiskey_disk.configuration = { 'domain' => [ @domain ] }\n        @whiskey_disk.should.receive(:system).with('bash', '-c', \"export WD_ROLES='web:db'; ls\")\n        @whiskey_disk.shell(@domain, 'ls')        \n      end\n    end\n  end\n\n  describe 'when running a command string remotely' do\n    before do\n      @domain_name = 'ogc@ogtastic.com'\n      @domain = { 'name' => @domain_name }\n      @whiskey_disk.configuration = { 'domain' => [ @domain ] }\n      @whiskey_disk.stub!(:system)\n      @whiskey_disk.stub!(:puts)\n    end\n    \n    it 'accepts a domain and a command string' do\n      lambda { @whiskey_disk.run(@domain, 'ls') }.should.not.raise(ArgumentError)\n    end\n    \n    it 'requires a domain and a command string' do\n      lambda { @whiskey_disk.run(@domain) }.should.raise(ArgumentError)\n    end\n\n    describe \"building a command\" do\n      it 'includes domain role settings when the domain has roles' do\n        @domain = { 'name' => @domain_name, 'roles' => [ 'web', 'db' ] }\n        @whiskey_disk.configuration = { 'domain' => [ @domain ] }\n        @whiskey_disk.build_command(@domain, 'ls').should.match /export WD_ROLES='web:db'; ls/\n      end\n    end\n\n    describe 'when debugging is enabled' do\n      before { ENV['debug'] = 'true' }\n\n      it 'passes the string to ssh for the domain, with verbosity enabled' do\n        @whiskey_disk.should.receive(:system).with('ssh', @domain_name, '-v', \"set -x; ls\")\n        @whiskey_disk.run(@domain, 'ls')\n      end\n    end\n\n    describe 'when debugging is not enabled' do\n      before { ENV['debug'] = 'false' }\n\n      it 'passes the string to ssh for the domain, with verbosity disabled' do\n        @whiskey_disk.should.receive(:system).with('ssh', @domain_name, \"ls\")\n        @whiskey_disk.run(@domain, 'ls')\n      end\n    end\n    \n    describe 'when ssh_options are specified in the configuration' do\n      before do\n        @domain = { 'name' => @domain_name, 'ssh_options' => [ '-t', '-p 12345' ] }\n        \n        @whiskey_disk.configuration = { 'domain' => [ @domain ] }\n      end\n      \n      it 'includes the ssh options when running ssh' do\n        @whiskey_disk.should.receive(:system).with('ssh', @domain_name, '-t', '-p 12345', 'ls')\n        @whiskey_disk.run(@domain, 'ls')\n      end\n    end\n  end\n\n  describe 'determining if all the deployments succeeded' do\n    it 'works without arguments' do\n      lambda { @whiskey_disk.success? }.should.not.raise(ArgumentError)\n    end\n    \n    it 'does not allow arguments' do\n      lambda { @whiskey_disk.success?(:foo) }.should.raise(ArgumentError)\n    end\n    \n    it 'returns true if there are no results recorded' do\n      @whiskey_disk.success?.should.be.true\n    end\n    \n    it 'returns true if all recorded results have true statuses' do\n      @whiskey_disk.record_result('1', true)\n      @whiskey_disk.record_result('2', true)\n      @whiskey_disk.record_result('3', true)\n      @whiskey_disk.success?.should.be.true\n    end\n    \n    it 'returns false if any recorded result has a false status' do\n      @whiskey_disk.record_result('1', true)\n      @whiskey_disk.record_result('2', false)\n      @whiskey_disk.record_result('3', true)\n      @whiskey_disk.success?.should.be.false      \n    end\n  end\n  \n  describe 'summarizing the results of a run' do\n    before do\n      @whiskey_disk.stub!(:puts)\n    end\n    \n    it 'works without arguments' do\n      lambda { @whiskey_disk.summarize }.should.not.raise(ArgumentError)\n    end\n    \n    it 'does not allow arguments' do\n      lambda { @whiskey_disk.summarize(:foo) }.should.raise(ArgumentError)      \n    end\n    \n    it 'outputs a no runs message when no results are recorded' do\n      @whiskey_disk.should.receive(:puts).with('No deployments to report.')\n      @whiskey_disk.summarize\n    end\n    \n    describe 'and there are results recorded' do\n      before do\n        @whiskey_disk.record_result('foo@bar.com', false)\n        @whiskey_disk.record_result('ogc@ogtastic.com', true)\n        @whiskey_disk.record_result('user@example.com', true)\n      end\n      \n      it 'outputs a status line for each recorded deployment run' do\n        @whiskey_disk.should.receive(:puts).with('foo@bar.com => failed.')\n        @whiskey_disk.should.receive(:puts).with('ogc@ogtastic.com => succeeded.')\n        @whiskey_disk.should.receive(:puts).with('user@example.com => succeeded.')\n        @whiskey_disk.summarize\n      end\n    \n      it 'outputs a summary line including the total runs, count of failures and count of successes.' do\n        @whiskey_disk.should.receive(:puts).with('Total: 3 deployments, 2 successes, 1 failure.')        \n        @whiskey_disk.summarize\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "tasks/deploy.rake",
    "content": "require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'whiskey_disk', 'rake'))\n\n"
  },
  {
    "path": "whiskey_disk.gemspec",
    "content": "# Generated by jeweler\n# DO NOT EDIT THIS FILE DIRECTLY\n# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'\n# -*- encoding: utf-8 -*-\n\nGem::Specification.new do |s|\n  s.name = \"whiskey_disk\"\n  s.version = \"0.6.24\"\n\n  s.required_rubygems_version = Gem::Requirement.new(\">= 0\") if s.respond_to? :required_rubygems_version=\n  s.authors = [\"Rick Bradley\"]\n  s.date = \"2011-10-05\"\n  s.description = \"Opinionated gem for doing fast git-based server deployments.\"\n  s.email = \"rick@rickbradley.com\"\n  s.executables = [\"wd_role\", \"wd\"]\n  s.extra_rdoc_files = [\n    \"README.integration_specs\",\n    \"README.markdown\"\n  ]\n  s.files = [\n    \"CHANGELOG\",\n    \"MIT-LICENSE\",\n    \"README.integration_specs\",\n    \"README.markdown\",\n    \"Rakefile\",\n    \"VERSION\",\n    \"WHY.txt\",\n    \"bin/wd\",\n    \"bin/wd_role\",\n    \"examples/deploy-configs.yml\",\n    \"examples/deploy-local.yml\",\n    \"examples/deploy-multiple-remotes.yml\",\n    \"examples/deploy-staging.yml\",\n    \"examples/deploy.rake\",\n    \"examples/deploy.yml\",\n    \"init.rb\",\n    \"install.rb\",\n    \"lib/whiskey_disk.rb\",\n    \"lib/whiskey_disk/config.rb\",\n    \"lib/whiskey_disk/config/abstract_filter.rb\",\n    \"lib/whiskey_disk/config/filter.rb\",\n    \"lib/whiskey_disk/config/filters/add_environment_name_filter.rb\",\n    \"lib/whiskey_disk/config/filters/add_project_name_filter.rb\",\n    \"lib/whiskey_disk/config/filters/check_for_duplicate_domains_filter.rb\",\n    \"lib/whiskey_disk/config/filters/convert_role_strings_to_list_filter.rb\",\n    \"lib/whiskey_disk/config/filters/default_config_target_filter.rb\",\n    \"lib/whiskey_disk/config/filters/default_domain_filter.rb\",\n    \"lib/whiskey_disk/config/filters/drop_empty_domain_roles_filter.rb\",\n    \"lib/whiskey_disk/config/filters/environment_scope_filter.rb\",\n    \"lib/whiskey_disk/config/filters/hashify_domain_entries_filter.rb\",\n    \"lib/whiskey_disk/config/filters/localize_domains_filter.rb\",\n    \"lib/whiskey_disk/config/filters/modules/scope_helper.rb\",\n    \"lib/whiskey_disk/config/filters/normalize_ssh_options_filter.rb\",\n    \"lib/whiskey_disk/config/filters/project_scope_filter.rb\",\n    \"lib/whiskey_disk/config/filters/select_project_and_environment_filter.rb\",\n    \"lib/whiskey_disk/config/filters/stringify_hash_keys_filter.rb\",\n    \"lib/whiskey_disk/helpers.rb\",\n    \"lib/whiskey_disk/rake.rb\",\n    \"scenarios/git_repositories/config.git/HEAD\",\n    \"scenarios/git_repositories/config.git/config\",\n    \"scenarios/git_repositories/config.git/description\",\n    \"scenarios/git_repositories/config.git/git-daemon-export-ok\",\n    \"scenarios/git_repositories/config.git/hooks/applypatch-msg.sample\",\n    \"scenarios/git_repositories/config.git/hooks/commit-msg.sample\",\n    \"scenarios/git_repositories/config.git/hooks/post-commit.sample\",\n    \"scenarios/git_repositories/config.git/hooks/post-receive.sample\",\n    \"scenarios/git_repositories/config.git/hooks/post-update.sample\",\n    \"scenarios/git_repositories/config.git/hooks/pre-applypatch.sample\",\n    \"scenarios/git_repositories/config.git/hooks/pre-commit.sample\",\n    \"scenarios/git_repositories/config.git/hooks/pre-rebase.sample\",\n    \"scenarios/git_repositories/config.git/hooks/prepare-commit-msg.sample\",\n    \"scenarios/git_repositories/config.git/hooks/update.sample\",\n    \"scenarios/git_repositories/config.git/info/exclude\",\n    \"scenarios/git_repositories/config.git/objects/0d/b14dd6ddc54017c0a11960dcda82ed802cde69\",\n    \"scenarios/git_repositories/config.git/objects/0e/e781f5ce80d64db32a74a7aae7b5248dafe112\",\n    \"scenarios/git_repositories/config.git/objects/17/6bf54cf17d1d1c24556dc059c4144a5df230e8\",\n    \"scenarios/git_repositories/config.git/objects/20/e9ff3feaa8ede30f707e5f1b4356e3c02bb7ec\",\n    \"scenarios/git_repositories/config.git/objects/45/117b1c775f0de415478dbf08ed9d667ab17d13\",\n    \"scenarios/git_repositories/config.git/objects/51/3954c9aca090e6ce40359f0e9fde30ea78eb8c\",\n    \"scenarios/git_repositories/config.git/objects/66/947a7a11a6f5d3d561fe95de284ced3010819a\",\n    \"scenarios/git_repositories/config.git/objects/6b/bc79311bfac47d3ed724aa82a4814e0dda4c67\",\n    \"scenarios/git_repositories/config.git/objects/71/eb5df52676e8e6efba471050b46978173af110\",\n    \"scenarios/git_repositories/config.git/objects/84/17d2fe3e8fcc0825249c517b29b0f9ea8b8b31\",\n    \"scenarios/git_repositories/config.git/objects/8b/384fcfcf7c0dee7c3c1d5636bee9e645d9cf38\",\n    \"scenarios/git_repositories/config.git/objects/bb/59da633ba74296b0c2f9ff70784ac155ddb599\",\n    \"scenarios/git_repositories/config.git/objects/cc/b86b26189afbf45d8eb9165812ab86dbdfca63\",\n    \"scenarios/git_repositories/config.git/objects/d1/0bcd51fec41f854001e4d61f99d9e282a695d3\",\n    \"scenarios/git_repositories/config.git/objects/d8/a8b0f5b1fd66844efb141d9544965ea0065f2d\",\n    \"scenarios/git_repositories/config.git/objects/e6/b02c66ad632e6b8535c4630cb8fe07732a72fc\",\n    \"scenarios/git_repositories/config.git/objects/e8/b8bfeeba735c0a1a873082554cb4d7256ac125\",\n    \"scenarios/git_repositories/config.git/objects/f9/0181466a1a60b793ca9cc9abd584c18d4e3887\",\n    \"scenarios/git_repositories/config.git/objects/f9/49d5d8a4f12c91471e34d4e277239c35ebd10d\",\n    \"scenarios/git_repositories/config.git/refs/heads/master\",\n    \"scenarios/git_repositories/project.git/HEAD\",\n    \"scenarios/git_repositories/project.git/config\",\n    \"scenarios/git_repositories/project.git/description\",\n    \"scenarios/git_repositories/project.git/git-daemon-export-ok\",\n    \"scenarios/git_repositories/project.git/hooks/applypatch-msg.sample\",\n    \"scenarios/git_repositories/project.git/hooks/commit-msg.sample\",\n    \"scenarios/git_repositories/project.git/hooks/post-commit.sample\",\n    \"scenarios/git_repositories/project.git/hooks/post-receive.sample\",\n    \"scenarios/git_repositories/project.git/hooks/post-update.sample\",\n    \"scenarios/git_repositories/project.git/hooks/pre-applypatch.sample\",\n    \"scenarios/git_repositories/project.git/hooks/pre-commit.sample\",\n    \"scenarios/git_repositories/project.git/hooks/pre-rebase.sample\",\n    \"scenarios/git_repositories/project.git/hooks/prepare-commit-msg.sample\",\n    \"scenarios/git_repositories/project.git/hooks/update.sample\",\n    \"scenarios/git_repositories/project.git/info/exclude\",\n    \"scenarios/git_repositories/project.git/objects/04/26e152e66c8cd42974279bdcae09be9839c172\",\n    \"scenarios/git_repositories/project.git/objects/04/f4de85eaf72ef1631dc6d7424045c0a749b757\",\n    \"scenarios/git_repositories/project.git/objects/06/13fe277280cbcdb2856e1eefc70bdaff011b20\",\n    \"scenarios/git_repositories/project.git/objects/06/7aca89b86265eee211387434c3e50f37ccf009\",\n    \"scenarios/git_repositories/project.git/objects/09/445dacc4822722612d60833c9948219ecdd8f5\",\n    \"scenarios/git_repositories/project.git/objects/11/c4ec64326de35462f4e79d0f4229bf8e26e0c5\",\n    \"scenarios/git_repositories/project.git/objects/20/1c7641c2e42b0b904e5c1f793489d8b858e4da\",\n    \"scenarios/git_repositories/project.git/objects/23/979639da60d2d31e9744468df1c1221b101e64\",\n    \"scenarios/git_repositories/project.git/objects/27/a3fff2c4c45ab5513a405f694c0a042cb5d417\",\n    \"scenarios/git_repositories/project.git/objects/2c/0c33cfba8e1af15df88522c0db2b10a6a94138\",\n    \"scenarios/git_repositories/project.git/objects/38/b574660305ecb5fec6b2daa7ee1e0dbf1b6003\",\n    \"scenarios/git_repositories/project.git/objects/4a/57abb5e4e426cfc9101b3af22ac83ccbd8e2ad\",\n    \"scenarios/git_repositories/project.git/objects/4c/77ebdd985e57afe7988480720c5dc77ec525c9\",\n    \"scenarios/git_repositories/project.git/objects/51/c94da6f1b8aa9d2346088d3d362475b60c7f32\",\n    \"scenarios/git_repositories/project.git/objects/5b/a96acf9cc9b87babe37c032676f53bf1ba9ae7\",\n    \"scenarios/git_repositories/project.git/objects/5d/f555601d60f1c2a84d2364af0ad640612c3ba5\",\n    \"scenarios/git_repositories/project.git/objects/71/03b5ac94940d596c2160a5cfcd55ca4ccac41f\",\n    \"scenarios/git_repositories/project.git/objects/73/3fc331098b03523f414f3509b9ae6e637c6866\",\n    \"scenarios/git_repositories/project.git/objects/80/26076649ceccbe96a6292f2432652f08483035\",\n    \"scenarios/git_repositories/project.git/objects/86/d1ef0976be4567de562224e1b51fbf9820c53a\",\n    \"scenarios/git_repositories/project.git/objects/87/a9d8b09b3401d21b23d90253332d6b28b47db2\",\n    \"scenarios/git_repositories/project.git/objects/8b/030ba688255c917d189ae3f87d7c5ccd226bc2\",\n    \"scenarios/git_repositories/project.git/objects/95/c9d5ad9b1c90e4c805516783105fc2037dedeb\",\n    \"scenarios/git_repositories/project.git/objects/95/d82d043af35a80eabfd56c0d705abfa3488787\",\n    \"scenarios/git_repositories/project.git/objects/96/0bf34bb0b46d0aeb0be87f688f4ef06a4b35e1\",\n    \"scenarios/git_repositories/project.git/objects/a3/860106dc1d148c7831cd45ae38829b4ed47702\",\n    \"scenarios/git_repositories/project.git/objects/a8/506d6439b71784a72ac72d284b2ad53088f573\",\n    \"scenarios/git_repositories/project.git/objects/ad/22ea6c7563777936ecfbe50d8e2cf8120fd525\",\n    \"scenarios/git_repositories/project.git/objects/ae/3900de54aff557c61c81146d00f9d38e55a265\",\n    \"scenarios/git_repositories/project.git/objects/bf/5e3740d52b80abb0378b3f85f93a53b1294521\",\n    \"scenarios/git_repositories/project.git/objects/bf/b59811cdbc069418dee14b171e6e7e979784b7\",\n    \"scenarios/git_repositories/project.git/objects/cc/5ac0afb24e727d5de344cc26a425f4fb7fd17d\",\n    \"scenarios/git_repositories/project.git/objects/d1/091aa2dd76885108461110c639e6b33a297fce\",\n    \"scenarios/git_repositories/project.git/objects/d8/913f6650eb2b7bf2a633732d8452008ca23dcb\",\n    \"scenarios/git_repositories/project.git/objects/db/d1b9667f1b26b13331ac0c321dced8be1aeab0\",\n    \"scenarios/git_repositories/project.git/objects/e4/3b9107e9b1908ce415025e64eb83a493d329b7\",\n    \"scenarios/git_repositories/project.git/objects/ef/2a88894d5421920b9dfe67a9a4d8043830e62e\",\n    \"scenarios/git_repositories/project.git/objects/f4/0123a1ff20c65d8dc15a38a83222647908e6f7\",\n    \"scenarios/git_repositories/project.git/objects/f5/0af315b75ca0b12c720dec6d916b76b968c319\",\n    \"scenarios/git_repositories/project.git/objects/f6/0215709b7b23f3738e9cbaf634b1c86bbd376a\",\n    \"scenarios/git_repositories/project.git/refs/heads/bad_rakefile\",\n    \"scenarios/git_repositories/project.git/refs/heads/hook_with_changed\",\n    \"scenarios/git_repositories/project.git/refs/heads/master\",\n    \"scenarios/git_repositories/project.git/refs/heads/no_rake_hooks\",\n    \"scenarios/git_repositories/project.git/refs/heads/post_rake_tasks\",\n    \"scenarios/invalid/deploy.yml\",\n    \"scenarios/local/deploy.yml.erb\",\n    \"scenarios/remote/deploy.yml\",\n    \"scenarios/setup/vagrant/.gitignore\",\n    \"scenarios/setup/vagrant/Vagrantfile\",\n    \"scenarios/setup/vagrant/manifests/integration.pp\",\n    \"scenarios/setup/vagrant/pids/.gitignore\",\n    \"spec/.bacon\",\n    \"spec/init_spec.rb\",\n    \"spec/install_spec.rb\",\n    \"spec/integration/branch_switching_spec.rb\",\n    \"spec/integration/deployment_failures_spec.rb\",\n    \"spec/integration/helper_spec.rb\",\n    \"spec/integration/invalid_configuration_spec.rb\",\n    \"spec/integration/local_deployments_spec.rb\",\n    \"spec/integration/post_rake_tasks_spec.rb\",\n    \"spec/integration/post_scripts_spec.rb\",\n    \"spec/integration/remote_deployments_spec.rb\",\n    \"spec/integration/staleness_checks_spec.rb\",\n    \"spec/spec_helper.rb\",\n    \"spec/wd_command_spec.rb\",\n    \"spec/wd_role_command_spec.rb\",\n    \"spec/whiskey_disk/config/filter_spec.rb\",\n    \"spec/whiskey_disk/config/filters/add_environment_name_filter_spec.rb\",\n    \"spec/whiskey_disk/config/filters/add_project_name_filter_spec.rb\",\n    \"spec/whiskey_disk/config/filters/check_for_duplicate_domains_filter_spec.rb\",\n    \"spec/whiskey_disk/config/filters/convert_role_strings_to_list_filter_spec.rb\",\n    \"spec/whiskey_disk/config/filters/default_config_target_filter_spec.rb\",\n    \"spec/whiskey_disk/config/filters/default_domain_filter_spec.rb\",\n    \"spec/whiskey_disk/config/filters/drop_empty_domain_roles_filter_spec.rb\",\n    \"spec/whiskey_disk/config/filters/environment_scope_filter_spec.rb\",\n    \"spec/whiskey_disk/config/filters/hashify_domain_entries_filter_spec.rb\",\n    \"spec/whiskey_disk/config/filters/localize_domains_filter_spec.rb\",\n    \"spec/whiskey_disk/config/filters/normalize_ssh_options_filter_spec.rb\",\n    \"spec/whiskey_disk/config/filters/project_scope_filter_spec.rb\",\n    \"spec/whiskey_disk/config/filters/select_project_and_environment_filter_spec.rb\",\n    \"spec/whiskey_disk/config/filters/stringify_hash_keys_filter_spec.rb\",\n    \"spec/whiskey_disk/config_spec.rb\",\n    \"spec/whiskey_disk/helpers_spec.rb\",\n    \"spec/whiskey_disk/rake_spec.rb\",\n    \"spec/whiskey_disk_spec.rb\",\n    \"tasks/deploy.rake\",\n    \"whiskey_disk.gemspec\"\n  ]\n  s.homepage = \"http://github.com/flogic/whiskey_disk\"\n  s.require_paths = [\"lib\"]\n  s.rubygems_version = \"1.8.10\"\n  s.summary = \"embarrassingly fast deployments.\"\n\n  if s.respond_to? :specification_version then\n    s.specification_version = 3\n\n    if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then\n      s.add_runtime_dependency(%q<rake>, [\">= 0\"])\n    else\n      s.add_dependency(%q<rake>, [\">= 0\"])\n    end\n  else\n    s.add_dependency(%q<rake>, [\">= 0\"])\n  end\nend\n\n"
  }
]