add initial SvnRunner.run_svn()
This commit is contained in:
parent
c6be5a46a2
commit
9188bb42e2
@ -1,4 +1,91 @@
|
||||
module Svi
|
||||
module SvnRunner
|
||||
|
||||
# Exception class to indicate an error with executing svn.
|
||||
class SvnExecError < RuntimeError; end
|
||||
|
||||
# Run Subversion and yield results linewise.
|
||||
#
|
||||
# @param subcommand [String, nil]
|
||||
# The svn subcommand to execute (e.g. "ls").
|
||||
# @param args [Array<String>]
|
||||
# The svn subcommand arguments.
|
||||
# @param options [Hash]
|
||||
# Optional arguments.
|
||||
# @option options [Array<String>] :global_args
|
||||
# Global svn arguments to place before the subcommand.
|
||||
#
|
||||
# @yield [line]
|
||||
# If a block is given, each line that the Subversion command writes to
|
||||
# standard output will be yielded to the calling block.
|
||||
# @yieldparam line [String]
|
||||
# Line of standard output.
|
||||
# @return [String]
|
||||
# The standard output from svn.
|
||||
# @raise [SvnExecError]
|
||||
# If the svn command errors out this exception is raised.
|
||||
def run_svn(subcommand, args, options = {}, &block)
|
||||
command = [
|
||||
"svn",
|
||||
*(options[:global_args] || []),
|
||||
subcommand,
|
||||
*args,
|
||||
].compact
|
||||
|
||||
# Create pipes for standard output and standard error.
|
||||
stdout_rd, stdout_wr = IO.pipe
|
||||
stderr_rd, stderr_wr = IO.pipe
|
||||
|
||||
# Launch the svn subprocess using the pipes.
|
||||
spawn_options = {
|
||||
out: stdout_wr,
|
||||
err: stderr_wr,
|
||||
close_others: true,
|
||||
}
|
||||
spawn_options[:in] = :close unless options[:allow_interactive]
|
||||
svn_pid = Process.spawn(*command, spawn_options)
|
||||
|
||||
# Close write side of the pipes in the parent process.
|
||||
stdout_wr.close
|
||||
stderr_wr.close
|
||||
|
||||
stdout = ""
|
||||
stderr = ""
|
||||
stdout_yield = ""
|
||||
|
||||
loop do
|
||||
so = stdout_rd.read_nonblock(exception: false)
|
||||
if so.is_a?(String)
|
||||
stdout += so
|
||||
stdout_yield += so
|
||||
end
|
||||
se = stderr_rd.read_nonblock(exception: false)
|
||||
if se.is_a?(String)
|
||||
stderr += se
|
||||
end
|
||||
if so.nil? and se.nil?
|
||||
break
|
||||
end
|
||||
if block
|
||||
loop do
|
||||
index = stdout_yield.index("\n")
|
||||
break unless index
|
||||
line = stdout_yield[0, index]
|
||||
block[line]
|
||||
stdout_yield = stdout_yield[index + 1, stdout_yield.size]
|
||||
end
|
||||
end
|
||||
IO.select([stdout_rd, stderr_rd])
|
||||
end
|
||||
|
||||
Process.waitpid(svn_pid)
|
||||
|
||||
if stderr != ""
|
||||
raise SvnExecError.new(stderr)
|
||||
end
|
||||
|
||||
stdout
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user