Sorry, answering my own question again. Rather than doing
Kernel#caller, you can just check to see if you've defined get_cmd, so
the whole at_once method looks like:

def at_once(joiner=' && ')
  nested = respond_to?(:get_cmd)
  unless nested
    cmds ||= Array.new
    self.class.send(:define_method, :get_cmd) {|c|cmds << c}
    alias old_run run
    alias run get_cmd
  end
  yield
  unless nested
    alias run old_run
    run cmds.join(joiner)
  end
end

On Jan 9, 4:54 pm, "Ian Smith-Heisters" <[EMAIL PROTECTED]> wrote:
> Yes, but that wasn't flexible or elegant enough ;)
>
> This is what I've ended up with, which seems to be working as desired.
> I'd be very interested if someone has something better for the line
> where I call Kernel#caller.
>
> def at_once(joiner=' && ')
>  nested = caller.any?{|c|c =~ /config\/deploy\.rb.+at_once'$/}
>  unless nested
>    cmds ||= Array.new
>    self.class.send(:define_method, :get_cmd) {|c|cmds << c}
>    alias old_run run
>    alias run get_cmd
>  end
>  yield
>  unless nested
>    alias run old_run
>    run cmds.join(joiner)
>  end
> end
>
> namespace :env do
>  task :init do
>    at_once do
>      run "cd #{deploy_to}"
>      run "eval `#{deploy_to}/bin/env.sh`"
>    end
>  end
>
>  task :sandbox do
>    set :current_envronment, :sandbox
>    set :rails_env, :sandbox
>    set :deploy_to, "/var/www/#{application}-sandbox"
>  end
>
>  task :echo do
>    at_once do
>      init
>      run 'echo $RAILS_ENV'
>      run 'which ruby'
>      run 'which gem'
>    end
> end
>
> $ cap env:sandbox env:echo
>  * executing `env:sandbox'
>  * executing `env:echo'
>  * executing `env:init'
>  * executing "cd /var/www/myapp-sandbox && eval
> `/var/www/myapp-sandbox/bin/env.sh` && echo $RAILS_ENV && which ruby
> && which gem"
>    servers: ["example.com"]
>    [example.com] executing command
>  ** [out :: example.com]
>  ** [out :: example.com] /var/www/myapp-sandbox/usr/bin/ruby
>  ** [out :: example.com] /var/www/myapp-sandbox/usr/bin/gem
>    command finished
>
> -Ian
>
> On 1/9/08, Jamis Buck <[EMAIL PROTECTED]> wrote:
>
> > The easiest thing to do is probably going to be something like this:
>
> >    run "x && y"
>
> > If x is something you always want to run for all of your commands,
> > then you can do something like this:
>
> >    def run_with_x(y)
> >      run "x && #{y}"
> >    end
>
> >    run_with_x("y")
>
> > - Jamis
>
> > On Jan 9, 2008, at 4:44 PM, Ian Smith-Heisters wrote:
>
> > > Ok, that's what I was beginning to suspect.
>
> > > So I thought I'd be clever and write a little helper method that would
> > > help me string together a bunch of commands with, say, ' && ':
>
> > >>> def run(cmd); puts "I have yer #{cmd}"; end
> > > => nil
> > >>> def at_once(joiner=' && ')
> > >>>  cmds = Array.new
> > >>>  Object.define_method(:get_cmd) {|c|cmds << c}
> > >>>  alias :old_run :run
> > >>>  alias :run :get_cmd
> > >>>  yield
> > >>>  alias :run :old_run
> > >>>  run cmds.join(joiner)
> > >>> end
> > > => nil
> > >>> at_once{run('x');run('y')}
> > > I have yer x && y
> > > => nil
> > >>> run 'x'
> > > I have yer x
> > > => nil
> > >>> run 'y'
> > > I have yer y
> > > => nil
>
> > > Which works fine on the console. Unfortunately, when I stick the
> > > at_once definition at the top of my deploy.rb script, it runs into all
> > > kinds of problems like "`method_missing': undefined method `at_once'
> > > for #<Capistrano::Configuration::Namespaces::Namespace:0xb7859b18>"
> > > when I try to use it.
>
> > > Any ideas on how to get that to work?
>
> > > Thanks,
> > > Ian
>
> > > On 1/9/08, Jamis Buck <[EMAIL PROTECTED]> wrote:
> > >> Each invocation of run() or sudo() is done in a brand new SSH
> > >> channel.
> > >> Running commands via capistrano is not at all like executing commands
> > >> in a shell like bash--environment settings do not stick from one
> > >> command to the next. If you have setup that you want done on each
> > >> run(), you will need to do as you said and create a wrapper method
> > >> that prepends the setup you want done to each command.
>
> > >> - Jamis
>
> > >> On Jan 8, 2008, at 5:29 PM, I. E. Smith-Heisters wrote:
>
> > >>> Hi all,
>
> > >>> I have a bunch of staging servers, all of which have their own,
> > >>> custom
> > >>> compiled ruby and gem versions. In order to work with a given server
> > >>> instance, a user is supposed to eval a script that sets up their
> > >>> bash
> > >>> environment. Like this:
>
> > >>> $ cd /var/www/staging-x
> > >>> $ eval `bin/env.sh`
> > >>> $ which ruby
> > >>> /var/www/staging-x/usr/bin/ruby
> > >>> $ which gem
> > >>> /var/www/staging-x/usr/bin/gem
>
> > >>> When I use Cap to run "eval `bin/env.sh`", the variables it exports
> > >>> are not persisted:
>
> > >>> namespace :env do
> > >>> task :init do
> > >>>   run "cd #{deploy_to}"
> > >>>   run "eval `#{deploy_to}/bin/env.sh`"
> > >>> end
>
> > >>> task :sandbox do
> > >>>   set :rails_env, :sandbox
> > >>>   set :deploy_to, "/var/www/#{application}-sandbox"
> > >>>   init
> > >>> end
>
> > >>> task :echo do
> > >>>   run 'echo $RAILS_ENV'
> > >>>   run 'which ruby'
> > >>>   run 'which gem'
> > >>> end
> > >>> end
>
> > >>> $ cap env:sandbox env:echo
> > >>> <snip>
> > >>> * executing `env:echo'
> > >>> * executing "echo $RAILS_ENV"
> > >>>   servers: ["example.com"]
> > >>>   [example.com] executing command
> > >>> ** [out :: example.com]
> > >>>   command finished
> > >>> * executing "which ruby"
> > >>>   servers: ["example.com"]
> > >>>   [example.com] executing command
> > >>> ** [out :: example.com] /usr/bin/ruby
> > >>>   command finished
> > >>> * executing "which gem"
> > >>>   servers: ["example.com"]
> > >>>   [example.com] executing command
> > >>> *** [err :: example.com] which: no gem in (/usr/kerberos/bin:/usr/
> > >>> local/bin:/bin:/usr/bin)
> > >>>   command finished
> > >>> command "which gem" failed on example.com
>
> > >>> As you can see, the PATH variable still points to the system version
> > >>> of ruby, and since the system doesn't have gem installed, "which
> > >>> gem"
> > >>> kills the script outright.
>
> > >>> I've been looking around and I see lots of problems surrounding
> > >>> people's bashrc files being read and other ssh configuration issues,
> > >>> but this really seems to be something to do with how Capistrano is
> > >>> executing each command and the persistence of the environment
> > >>> between
> > >>> them. A colleague suggested I do something like
>
> > >>> run "eval `bin/env.sh` && foobar"
>
> > >>> which I guess is a possibility, but hardly an elegant solution,
> > >>> since
> > >>> I'd have to prefix each command with the eval statement (probably
> > >>> best
> > >>> accomplished by extending "run").
>
> > >>> Thanks in advance for any help you might be able to offer.
>
> > >>> -Ian
--~--~---------~--~----~------------~-------~--~----~
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/capistrano
-~----------~----~----~----~------~----~------~--~---

Reply via email to