如何在不诉诸替代策略的情况下将 Expect 与 Git 交互式 CLI 结合使用?

如何在不诉诸替代策略的情况下将 Expect 与 Git 交互式 CLI 结合使用?

通常,我可以使用后面跟着expect的机制。然而,对于的交互式 shell,这不起作用,我必须使用.expectsendgitputs

有什么技巧可以恢复shell的正常使用吗?或者这可能是 Mac 上的跨平台问题,而如果我在 Linux 机器上则不会存在?

#!/usr/bin/expect

# get the expected count
set ct [exec git status | grep -e {deleted by us:} | awk {END{print NR}}]
puts "expect count = $ct"

spawn bash
send "git mergetool\r"
for {set i 0} {$i < $ct} {incr i} {
  expect -re "^.*local.: (.*)$"
  set choice $expect_out(1,string)
  set choice_letter [string index $choice 0]
  expect -re ".*Use.*\?.*" { puts "$choice_letter\r" }  # here I have to use puts, weird
}

这是一些奇怪的 mac 事情,还是我已经学会了正常的、常规的期望行为并且正确使用puts而不是send在这个自动脚本中?

答案1

我最终通过录制了一个期望宏autoexpect。尽管结果autoexpect非常字面化且脆弱,但我认为它会使发送机制正确。

#!/usr/bin/expect

# get the expected count
set ct [exec git status | awk {BEGIN{count=0} /deleted by us:|added by them:/{count++} END{print count}}]
if { $ct < 1 } { exit 0 }

# set write mode on all of the files
exec git status | grep -e {deleted by us:} -e {added by them:} | cut -d: -f 2 | xargs -n 1 chmod +w

set favor local
puts "favor: $favor"
puts "Deleted file count = $ct"
spawn bash
send "git mergetool\r"
for {set i 0} {$i < $ct} {incr i} {
  expect -re "^.*$favor.: (\[a-z\]+)" {
      set choice $expect_out(1,string) ;
      set choice_letter [string index $choice 0] ;
  }
  expect -re "Use.*\? "
  send "d\r"
  expect "d\r"
}
expect -re ".*"
send -- "^D"
expect eof

新添加的内容在最后:

  ...
  expect -re "Use.*\? "
  send "d\r"

  # this line caused things to start working
  expect "d\r"
}
expect -re ".*". # expect the prompt here. 
# The lack of specificity introduces a rare bug, 
# ...but it is also simple and mostly works. 

# this was in the autoexpect recording, and I left it in
# ...probably unnecessary
send -- "^D"

# this was also in autoexpect recording; might be important
expect eof

我的猜测是 git CLI 能够将操作限制在最后一秒,如果托管它的终端关闭,则操作实际上不会发生。因此,通过额外的调用等待结果expect可能会确保操作发生。

在极少数情况下(我正在重新调整大约 2000 个与主分支历史记录断开的提交,因此大约 1/200),git 有一些替代输出,它会附加在其合并提示符的末尾,从而破坏自动化。

这是由于(.*)下一行提示的预期匹配。

相关内容