Question

I am trying to run git add -p from ruby. The problem is that this command displays portions of files and waits for user input, potentially opening the git editor. The regular Kernel methods to execute system commands won't work for this reason. I tried to use open3 and here is what I got so far:

require "open3"
Open3.popen3("\git add -p #{files_to_add.join(" ")}") do |stdin, stdout, stderr, wait_thr|
end

I don't know what to put in the block though, and can't find any clues on the interwebs.

Any ideas how I can solve this problem?

NOTE: I DO NOT want to use ANY gems

EDIT: open3 is not working. I am now experimenting with pty. Here is what I've got:

require "pty"
begin
  PTY.spawn("\git add -p #{files_to_add.join(" ")}") do |r, w, pid|
    begin
      r.each { |line| print line }
    rescue Errno::EIO
    end
  end
rescue PTY::ChildExited => e
  puts "The child process exited!"
end

This code prints the first chunk to patch, but then the "question" git asks (in other words, the standard input prompt) does not appear. I am obviously not printing it in the code above, but I can't seem to find out how to do that. Any ideas?

Was it helpful?

Solution

Inside the pty standard library module (no gems needed here) is an inner module you can require called expect. It will add an expect method to IO.

You probably want something like this:

require 'pty'
require 'expect'

PTY.spawn "git add -p" do |r, w, pid|
  w.sync = true
  r.expect ']? ' do |got|
    puts got
    puts 'responding with q'
    w.write "q\r"
    puts r.expect "\n", 9
  end
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top