Q: How can a Rake task know the caller's directory?

I'm increasingly using rake files for common system tasks. Since Rake will search up a directory tree until it finds a Rakefile, I can have one in my home directory and call tasks from anyplace below that.

But tasks that need to know something about the current directory have me stymied. Calling Dir.pwd in a task reflects the directory of the Rakefile.

Is there a rake method that returns the path of where the Rakefile search began?

E.g., if I'm in /home/james/foo/bar, and the nearest Rakefile is in /home/james, with task :whereami, and I call

  $ rake whereami

what does :whereami have to do to return '/home/james/foo/bar' ?

Thanks!

···

--
James Britt

James Britt wrote:

I'm increasingly using rake files for common system tasks. Since Rake will search up a directory tree until it finds a Rakefile, I can have one in my home directory and call tasks from anyplace below that.

But tasks that need to know something about the current directory have me stymied. Calling Dir.pwd in a task reflects the directory of the Rakefile.

Is there a rake method that returns the path of where the Rakefile search began?

E.g., if I'm in /home/james/foo/bar, and the nearest Rakefile is in /home/james, with task :whereami, and I call

$ rake whereami

what does :whereami have to do to return '/home/james/foo/bar' ?

No idea. One possible solution is to put a "stub" rakefile in the dir, and the stub requires the main rakefile. Then (IIRC) the pwd during the rake tasks will be that of the stub. But maybe you don't want to scatter stubs all over the place.

···

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

James Britt wrote:

I'm increasingly using rake files for common system tasks. Since Rake will search up a directory tree until it finds a Rakefile, I can have one in my home directory and call tasks from anyplace below that.

But tasks that need to know something about the current directory have me stymied. Calling Dir.pwd in a task reflects the directory of the Rakefile.

Is there a rake method that returns the path of where the Rakefile search began?

E.g., if I'm in /home/james/foo/bar, and the nearest Rakefile is in /home/james, with task :whereami, and I call

$ rake whereami

what does :whereami have to do to return '/home/james/foo/bar' ?

Thanks!

Modify rake to log the initial working directory before doing anything else. You could do this by putting the line to log the dir in the file bin/rake. Take advantage of ruby's openness.

Alternatively, you could put a file in a dir on your PATH (let's say rake2) to log the dir and then delegate to rake, and just call rake2 instead of rake from the command line.

James Britt wrote:

I'm increasingly using rake files for common system tasks. Since Rake
will search up a directory tree until it finds a Rakefile, I can have
one in my home directory and call tasks from anyplace below that.

But tasks that need to know something about the current directory have
me stymied. Calling Dir.pwd in a task reflects the directory of the
Rakefile.

Is there a rake method that returns the path of where the Rakefile
search began?

E.g., if I'm in /home/james/foo/bar, and the nearest Rakefile is in
/home/james, with task :whereami, and I call

  $ rake whereami

what does :whereami have to do to return '/home/james/foo/bar' ?

Thanks!

task :whereami do
  puts Rake.original_dir
end

-- Jim Weirich

···

--
Posted via http://www.ruby-forum.com/\.

Mike Harris wrote:

James Britt wrote:

E.g., if I'm in /home/james/foo/bar, and the nearest Rakefile is in /home/james, with task :whereami, and I call

$ rake whereami

what does :whereami have to do to return '/home/james/foo/bar' ?

Thanks!

Modify rake to log the initial working directory before doing anything else. You could do this by putting the line to log the dir in the file bin/rake. Take advantage of ruby's openness.

I've hacked ruby apps in this manner before, but they are prone to "gem update <name_of_gem>" stomping.

So any mods to rake itself have to happen via by a plugin that will survive library updates.

Alternatively, you could put a file in a dir on your PATH (let's say rake2) to log the dir and then delegate to rake, and just call rake2 instead of rake from the command line.

Too hackish, even for me. I'd rather see about a cleaner way for any arbitrary rake task to know the initial calling directory.

···

--
James Britt

"I have the uncomfortable feeling that others are making a religion
out of it, as if the conceptual problems of programming could be
solved by a single trick, by a simple form of coding discipline!"
  - Edsger Dijkstra

Joel VanderWerf wrote:

No idea. One possible solution is to put a "stub" rakefile in the dir, and the stub requires the main rakefile. Then (IIRC) the pwd during the rake tasks will be that of the stub. But maybe you don't want to scatter stubs all over the place.

Right, that's the whole point. For example, I have a Rake task that will do an svn commit. I've also aliased rake to r , so I can do this to commit code:

  $ r com This is my log message

and the :com task knows how to grab the message, do the commit, and run a few other things (like svn status to alert if I missed adding any new files).

Very handy, except as at stands, the invoked rake file thinks everything happens relative where it lives, so I have to create a Rakefile everyplace I want to use a location-Dependant task.

(Someone else mentioned using a "rake2" delegate; since I'm already using 'r' as my rake invocation, maybe having a real r.rb that stores the calling directory in ENV might work. That rake tasks that need the caller dir can look for the value in ENV; these tasks could then assume a default dir if this environment variable is empty.)

···

--
James Britt

"I have the uncomfortable feeling that others are making a religion
out of it, as if the conceptual problems of programming could be
solved by a single trick, by a simple form of coding discipline!"
  - Edsger Dijkstra

Mike Harris wrote:

Alternatively, you could put a file in a dir on your PATH (let's say rake2) to log the dir and then delegate to rake, and just call rake2 instead of rake from the command line.

I've tried that out, and it works quite well.

I had already aliased 'r' to 'rake' to save tying those extra three characters. I now have a real script 'r' (well, "r.rb", which is now the new r alias):

   #!/usr/local/bin/ruby
   ENV['cwd'] = Dir.pwd
   puts `rake #{ARGV.join( ' ')}`

Tasks that need the caller's working directory now use

    ENV['cwd'] || Dir.pwd

Thanks!

···

--
James Britt

"Take eloquence and wring its neck."
  - Paul Verlaine

task :whereami do
  puts Rake.original_dir
end

-- Jim Weirich

Checkmate, Mr. Weirich. I looked in run/load_rakefile, but neglected to
look in initialize (or the changelog). Thanks.

···

--
Posted via http://www.ruby-forum.com/\.

Jim Weirich wrote:
!

task :whereami do
  puts Rake.original_dir
end

Perfect. Thanks!

James

Jim Weirich wrote:

James Britt wrote:

I'm increasingly using rake files for common system tasks. Since Rake
will search up a directory tree until it finds a Rakefile, I can have
one in my home directory and call tasks from anyplace below that.

But tasks that need to know something about the current directory have
me stymied. Calling Dir.pwd in a task reflects the directory of the
Rakefile.

Is there a rake method that returns the path of where the Rakefile
search began?

E.g., if I'm in /home/james/foo/bar, and the nearest Rakefile is in
/home/james, with task :whereami, and I call

  $ rake whereami

what does :whereami have to do to return '/home/james/foo/bar' ?

Thanks!

task :whereami do
  puts Rake.original_dir
end

I had looked for such a method in ri and the Rake rdocs, but saw nothing that looked like what I wanted.

$ ri Rake
------------------------------------------------------------ Class: Rake
      (no description...)

···

------------------------------------------------------------------------

I could not find the originaL_dir method listed in the rdoc either, until I walked through the source code.

Because of the way this method is defined it Rake, rdoc will not correctly process it as a class method on Rake itself:

# in lib/rake.rb

  #
   class << self
     # Current Rake Application
     def application
       @application ||= Rake::Application.new
     end

     # Set the current Rake application object.
     def application=(app)
       @application = app
     end

     # Return the original directory where the Rake application was
     # started.
     def original_dir
       application.original_dir
     end

   end

And in the rdoc for Rake::Application, the method is not listed in the list of methods because it gets rdoc'ed as an "attribute".

One has to already know where to look, and what to look for, to find the behavior.

--
James Britt

"I never dispute another person's delusions, just their facts."
   - Len Bullard

James Britt wrote:

Joel VanderWerf wrote:
>
> No idea. One possible solution is to put a "stub" rakefile in the dir,
> and the stub requires the main rakefile. Then (IIRC) the pwd during the
> rake tasks will be that of the stub. But maybe you don't want to scatter
> stubs all over the place.

Right, that's the whole point. For example, I have a Rake task that
will do an svn commit. I've also aliased rake to r , so I can do this
to commit code:

  $ r com This is my log message

how are you accessing "This is my log message" in your task?

t.

Mike Harris wrote:

Checkmate, Mr. Weirich. I looked in run/load_rakefile, but neglected to
look in initialize (or the changelog). Thanks.

You can thank Jim Freeze for suggesting this feature.

-- Jim Weirich

···

--
Posted via http://www.ruby-forum.com/\.

Trans wrote:

James Britt wrote:

Joel VanderWerf wrote:

No idea. One possible solution is to put a "stub" rakefile in the dir,
and the stub requires the main rakefile. Then (IIRC) the pwd during the
rake tasks will be that of the stub. But maybe you don't want to scatter
stubs all over the place.

Right, that's the whole point. For example, I have a Rake task that
will do an svn commit. I've also aliased rake to r , so I can do this
to commit code:

  $ r com This is my log message

how are you accessing "This is my log message" in your task?

ARGV.shift # remove the task name
ARGV.join( ' ') # Get everything else on the command line

Sadly, rake still thinks that there are more tasks on the command line; even calling ARGV.clear doesn't help.

(I looked for the command to flush the Rake task call queue, but couldn't find it, so I live with the error it raises at the end. :frowning: )

···

--
James Britt

http://www.ruby-doc.org - Ruby Help & Documentation
Ruby Code & Style - The Journal By & For Rubyists
http://www.rubystuff.com - The Ruby Store for Ruby Stuff

James Britt wrote:

Trans wrote:

  $ r com This is my log message

how are you accessing "This is my log message" in your task?

ARGV.shift # remove the task name
ARGV.join( ' ') # Get everything else on the command line

Sadly, rake still thinks that there are more tasks on the command line;
even calling ARGV.clear doesn't help.

(I looked for the command to flush the Rake task call queue, but
couldn't find it, so I live with the error it raises at the end. :frowning: )

You could do:

  rake com MSG="This is my log message"

Inside of your Rakefile, ENV['MSG'] will contain your log message.

Sadly, more typing that what you have, but it works with rake instead of
against it.

-- Jim Weirich

···

--
Posted via http://www.ruby-forum.com/\.

Jim Weirich wrote:

James Britt wrote:
> Trans wrote:
>>> $ r com This is my log message
>>
>> how are you accessing "This is my log message" in your task?
>
> ARGV.shift # remove the task name
> ARGV.join( ' ') # Get everything else on the command line
>
> Sadly, rake still thinks that there are more tasks on the command line;
> even calling ARGV.clear doesn't help.
>
> (I looked for the command to flush the Rake task call queue, but
> couldn't find it, so I live with the error it raises at the end. :frowning: )

You could do:

  rake com MSG="This is my log message"

Inside of your Rakefile, ENV['MSG'] will contain your log message.

Sadly, more typing that what you have, but it works with rake instead of
against it.

why did you choose to use environment vars here. isn't that sort of
like using globals? also, these don't work in my case becuase i can't
differentiate the env vars set by rake from the "real" env vars.

t.

Jim Weirich wrote:

You could do:

  rake com MSG="This is my log message"

Inside of your Rakefile, ENV['MSG'] will contain your log message.

Right, but too much effort for the user. Leaves too much room for James to forget a quote or mistype the var name.

Sadly, more typing that what you have, but it works with rake instead of against it.

But isn't there a way to tell Rake to ignore any additional tasks it thinks are queued up?

When I run

  $rake com This is my message

it works fine, but at the very end rake complains that it doesn't know anything about task 'This'.

Thanks,

···

--
James Britt

Trans wrote:

why did you choose to use environment vars here. isn't that sort of
like using globals? also, these don't work in my case becuase i can't
differentiate the env vars set by rake from the "real" env vars.

The fact they look like environment variables is delibrate. This allows
you to pass information to Rake via environment variables or by command
line and Rake doesn't care. You can put a default value in your
environment and then easily override it on the command line. It is also
the way that the original make program worked.

-- Jim Weirich

···

--
Posted via http://www.ruby-forum.com/\.

Sure you can. Just introduce a little pragmatic namespacing:

   rake com RAKE_MSG="This is my log message"

James Edward Gray II

···

On Jan 15, 2007, at 9:57 PM, Trans wrote:

Jim Weirich wrote:

James Britt wrote:

Trans wrote:

  $ r com This is my log message

how are you accessing "This is my log message" in your task?

ARGV.shift # remove the task name
ARGV.join( ' ') # Get everything else on the command line

Sadly, rake still thinks that there are more tasks on the command line;
even calling ARGV.clear doesn't help.

(I looked for the command to flush the Rake task call queue, but
couldn't find it, so I live with the error it raises at the end. :frowning: )

You could do:

  rake com MSG="This is my log message"

Inside of your Rakefile, ENV['MSG'] will contain your log message.

Sadly, more typing that what you have, but it works with rake instead of
against it.

why did you choose to use environment vars here. isn't that sort of
like using globals? also, these don't work in my case becuase i can't
differentiate the env vars set by rake from the "real" env vars.

James Britt <james.britt@gmail.com> writes:

When I run

$rake com This is my message

it works fine, but at the very end rake complains that it doesn't know
anything about task 'This'.

Not perfect, but you could make your 'r' shell alias a shell function
something like this (bash-wise example):

    function r() { task="$1"; shift; rake "$task" RAKEOPT="$*"; }

This will give you:

    $ set -x
    $ r com This is my message
    + r com This is my message
    + task=com
    + shift
    + rake com 'RAKEOPT=This is my message'

-Marshall

James Edward Gray II wrote:

Sure you can. Just introduce a little pragmatic namespacing:

   rake com RAKE_MSG="This is my log message"

Hmm... maybe. Think I'll just use a single env var and parse that I
guess:

  rake com RAKEOPTS="This is my log message"

in my case

  rake sign RAKEOPTS="--digest=sha256"

personally, it would cooler if Rake took some of Ara's kung-fu and used
someting like a - to separate task from options.

T.