Mercurial HG_NODE hook variable on windows - windows

I'm currently testing mercurial hooks on windows and it seems like I cannot access hook variables....
here's hgrc content :
[hooks] prechangegroup = ruby prechangegroup.rb test1 test2 $HG_NODE
I also tried with %HG_NODE%
Here's prechangegroup.rb content
ARGV.each do|a|
puts "Argument: #{a}"
end
It prints out:
Argument: test1
Argument: test2
Argument: $HG_NODE$
Followed by the normal push output...
Any idea? (probably something stupid but, I can't seem to find it)
Thanks

HG_NODE is an environmental variable. You don't have to use it as arguments on the command line. Instead, you should be able to use it as puts ENV['HG_NODE'] (found through search engine as I'm not a ruby guy)

OK, I found a good documentation right on mercurial's website.
http://www.selenic.com/mercurial/hgrc.5.html#hooks
I tried with a variable other than %HG_NODE% like %HG_URL% and the variable worked.
So it probably means that the variable is inaccessible from that hook.

Related

Ruby Project - Prevent a ruby file from directly being called from OS command line

I am doing a demo command line project in Ruby. The structure is like this:
/ROOT_DIR
init.rb
/SCRIPT_DIR
(other scripts and files)
I want users to only go into the application using init.rb, but as it stands, anyone can go into the sub-folder and call other ruby scripts directly.
Questions:
What ways can above scenario be prevented?
If I was to use directory permissions, would it get reset when running the code from a Windows machine to on Linux machine?
Is there anything that can be included in Ruby files itself to prevent it from being directly called from OS command line?
You can't do this with file permissions, since the user needs to read the files; removing the read permission means you can't include it either. Removing the execute permission is useful to signal that these file aren't intended to be executed, but won't prevent people from typing ruby incl.rb.
The easiest way is probably to set a global variable in the init.rb script:
#!/usr/bin/env ruby
FROM_INIT = true
require './incl.rb'
puts 'This is init!'
And then check if this variable is defined in the included incl.rb file:
unless defined? FROM_INIT
puts 'Must be called from init.rb'
exit 0
end
puts 'This is incl!'
A second method might be checking the value of $PROGRAM_NAME in incl.rb; this stores the current program name (like argv[0] in many other languages):
unless $PROGRAM_NAME.end_with? 'init.rb'
puts 'Must be called from init.rb'
exit 0
end
I don't recommend this though, as it's not very future-proof; what if you want to rename init.rb or make a second script?

Ruby - Running rb file from script [duplicate]

This question already has answers here:
Running another ruby script from a ruby script
(7 answers)
Closed 7 years ago.
I'd like to write a ruby script that then calls another ruby script.
Example, I'd like to run the "test1.rb" from my script.
The test1.rb has been simplified to just do this:
print "1"
Then get the result (-> 1).
I tried to complete this problem with backticks or another executing command (%x[#{"test1.rb"}], system("test1.rb") etc.), but it didn't work.
So any idea how I call one script that then calls another script (either relinquishing total control or forking), and get the results?
Thanks
You can simply require the file, which would load the code and execute it:
require_relative "path/test1"
For the sake of having controll over the the run code, I would advice to place your script in a method:
# In test1.rb
def exec_my_script
puts 1
end
# In your main script
require_relative "path/test1"
exec_my_script
EDIT: Ok, since this does not seem to work for your usecase, you can read the file as string and eval the string as so:
result = eval(File.read("path/test1.rb"))
# do something with result
I do NOT like this approach, because it feels kinda "hacky" and is by all means insecure and it will only work if the last thing called in your test1 script returns the result you need...
You may want to use open3
require 'open3'
cmd = 'ruby test1.rb'
#You may change the contents of cmd like you would run it from the command line; like ruby [directory]/filename
Open3.popen3(cmd) do |stdin, stdout|
var = stdout.read
puts var
end
system('ruby test1.rb') # should do the trick
You can also make test1 executable (with chmod) and add the shebang line on top of test1.
You then can call
system("./test1.rb")
Ok, the system('ruby test1.rb') and system("ruby", "test1.rb") command worked.
And now, I like to set the returning value ("1") to a variable.
How I do it? It's possible to do that with backticks?

How to prevent capistrano replacing newlines?

I want to run some shell scripts remotely as part of my capistrano setup. To test that functionality, I use this code:
execute <<SHELL
cat <<TEST
something
TEST
SHELL
However, that is actually running /usr/bin/env cat <<TEST; something; TEST which is obviously not going to work. How do I tell capistrano to execute the heredoc as I have written it, without converting the newlines into semicolons?
I have Capistrano Version: 3.2.1 (Rake Version: 10.3.2) and do not know ruby particularly well, so there might be something obvious I missed.
I think it might work to just specify the arguments to cat as a second, er, argument to execute:
cat_args = <<SHELL
<<TEST
something
TEST
SHELL
execute "cat", cat_args
From the code #DavidGrayson posted, it looks like only the command (the first argument to execute) is sanitized.
I agree with David, though, that the simpler way might be to put the data in a file, which is what the SSHKit documentation suggests:
Upload a file from a stream
on hosts do |host|
file = File.open('/config/database.yml')
io = StringIO.new(....)
upload! file, '/opt/my_project/shared/database.yml'
upload! io, '/opt/my_project/shared/io.io.io'
end
The IO streaming is useful for uploading something rather than "cat"ing it, for example
on hosts do |host|
contents = StringIO.new('ALL ALL = (ALL) NOPASSWD: ALL')
upload! contents, '/etc/sudoers.d/yolo'
end
This spares one from having to figure out the correct escaping sequences for something like "echo(:cat, '...?...', '> /etc/sudoers.d/yolo')".
This seems like it would work perfectly for your use case.
The code responsible for this sanitization can be found in SSHKit::Command#sanitize_command!, which is called by that class's initialize method. You can see the source code here:
https://github.com/capistrano/sshkit/blob/9ac8298c6a62582455b1b55b5e742fd9e948cefe/lib/sshkit/command.rb#L216-226
You might consider monkeypatching it to do nothing by adding something like this to the top of your Rakefile:
SSHKit::Command # force the class to load so we can re-open it
class SSHKit::Command
def sanitize_command!
return if some_condition
super
end
end
This is risky and could introduce problems in other places; for example there might be parts of Capistrano that assume that the command has no newlines.
You are probably better off making a shell script that contains the heredoc or putting the heredoc in a file somewhere.
Ok, so this is the solution I figured out myself, in case it's useful for someone else:
str = %x(
base64 <<TEST
some
thing
TEST
).delete("\n")
execute "echo #{str} | base64 -d | cat -"
As you can see, I'm base64 encoding my command, sending it through, then decoding it on the server side where it can be evaluated intact. This works, but it's a real ugly hack - I hope someone can come up with a better solution.

How to pass command line parameters to capistrano

I am using Capistrano v2.9.0.
I run this command:
cap deploy:tryout -S testvar=thing
and my deploy.rb contains this:
namespace :deploy do
task :tryout do
if defined? testvar
puts "param: #{testvar}\n"
else
puts "no branch!\n"
end
end
end
The output is "no branch!". How do I pass values from the command line? I tried looking into the code, and I can see options.rb where it adds the passed parameter to options[:pre_vars], but that seems to be an instance variable, and I can't figure out how to access it from my deploy script.
Solution:
The options can be accessed via #parent.variables hash, so if the command line string is testvar=thing, then #parent.variables[:testvar] has the value string.
This seems really ugly and hacky, but it works.
Edit:
Turns out it is also available locally via variables[:testvar]

Ruby - Is there a way to overwrite the __FILE__ variable?

I'm doing some unit testing, and some of the code is checking to see if files exist based on the relative path of the currently-executing script by using the FILE variable. I'm doing something like this:
if File.directory?(File.join(File.dirname(__FILE__),'..','..','directory'))
blah blah blah ...
else
raise "Can't find directory"
end
I'm trying to find a way to make it fail in the unit tests without doing anything drastic. Being able to overwrite the __ FILE __ variable would be easiest, but as far as I can tell, it's impossible.
Any tips?
My tip? Refactor!
I didn't mark this as the real answer, since refactoring would be the best way to go about doing it. However, I did get it to work:
wd = Dir.getwd
# moves us up two directories, also assuming Dir.getwd
# returns a path of the form /folder/folder2/folder3/folder4...
Dir.chdir(wd.scan(/\/.*?(?=[\/]|$)/)[0..-3].join)
...run tests...
Dir.chdir(wd)
I had tried to do it using Dir.chdir('../../'), but when I changed back, File.expand_path(File.dirname(__ FILE __)) resolved to something different than what it was originally.
Programming Ruby 1.9 says on page 330 that __FILE__ is read only. It also describes it as a "execution environment variable".
However, you can define __FILE__ within an instance_eval. I don't think that'd help with your problem.

Resources