2

I am trying to cherry-pick gerrit reviews using a python script. I already have the string required to cherry-pick a review. I have used pexpect to automate the password input step.

Here is an example. For each review I have to execute the following 2 commands:

  1. git fetch "ssh://myusername@my-gerrit.server.net:34343/project" refs/changes/45/255645/38
  2. git cherry-pick FETCH_HEAD

Only the first command asks for a password. Here is the code i have written:

child = pexpect.spawn('git fetch "ssh://myusername@my-gerrit.server.net:34343/project" refs/changes/45/255645/38')
child.logfile_read = sys.stdout
child.expect(r'Enter passphrase for key(.*?):', timeout=10)
child.sendline('mypwd')
child.expect([pexpect.TIMEOUT, 'host$', pexpect.EOF])

child.sendline('git cherry-pick FETCH_HEAD')
child.expect([pexpect.TIMEOUT, 'host$', pexpect.EOF])

When i run the script i dont see any error. However the second command (git cherry-pick FETCH_HEAD) doesnt seem to be executed. I say this because when i run these commands manually the second command throws a git merge conflict. When i run the script i dont see cherry-pick in progress (git status shows all clean). I tried some variants but cannot get it to work. Please help.

Thanks in advance

  • Any time some sort of expect-based thing isn't working right, the debug path is always "add more logging" because it's almost certainly something you have wrong in your expectations of what is going to show up at the expect script, resulting in the wrong data being sent to the program at the wrong time (e.g., too soon, so that it gets discarded). But really any tool that requires using `expect` to drive it from some other program needs work so that it can be driven by machine. – torek May 14 '22 at 18:20
  • after `spawn(git fetch)`, all `sendline() / expect()` are interacting with `git fetch`. it makes no sense to send `git cherry-pick` to the spawned `git fetch`. you need to `spawn(git cherry-pick)` again after you are done with `git fetch`. – sexpect - Expect for Shells May 15 '22 at 07:51
  • Thanks a ton!! This fixed the issue. I am new to pexpect. I have been following other scripts which usually do a ssh session (spawn) to a remote box & continue to send commands using "sendline". So i thought this might work here too. Why/when should i use spawn for another command? Can you please elaborate a little? – nn_user1982 May 16 '22 at 12:15

1 Answers1

0

In order to add logs without modifying your script, use GIT_TRACE2 environment variables for tracing events.

export GIT_TRACE2=1
export GIT_TRACE2_EVENT=1

(or set, if you are on Windows)

Make also sure to launch your script with the same account you used to do manual testing.


If the second command does not seem to be executed, check if, as in this thread, the prompt is the issue:

It seems the problem was with the prompt I expected back.
If I change the expect to "child.expect('$ .*', timeout=15)", it works.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • @nn_user1982 The second command might not be executed because of the spawned script. Check https://pexpect.readthedocs.io/en/stable/commonissues.html. – VonC May 15 '22 at 07:29
  • Thanks. After enabling these i collected traces from manual run & through the script. On comparison, its clear that the second command is not triggered via the script. The text block below is the only difference between the 2 runs. I tried introducing sleep or using a different regex in the child.expect() after the first command but still cant get it to work. ``` start git cherry-pick FETCH_HEAD worktree /ws/myuser/latest_master cmd_name cherry-pick (cherry-pick) error could not apply 5b46561ad66... changes to my-module exit elapsed:1.399258 code:1 atexit elapsed:1.399299 code:1 ``` – nn_user1982 May 15 '22 at 07:39
  • Tried with "child.delaybeforesend = 10", still no luck. – nn_user1982 May 15 '22 at 07:54
  • I see these logs on stdout, which suggest the second command is indeed sent but for some reason isnt executed. Enter passphrase for key '/users/myuser/.ssh/id_rsa': From myusername@my-gerrit.server.net:29418/halon * branch refs/changes/45/255645/38 -> FETCH_HEAD git cherry-pick FETCH_HEAD – nn_user1982 May 15 '22 at 07:56
  • @nn_user1982 If FETCH_HEAD changes (for instance, its modification date is updated), then the fetch has been executed. It might not be visible because of the spawned shell. – VonC May 15 '22 at 10:48
  • The way i know for sure that it executed the first command is by inspecting ".git/FETCH_HEAD". I see it points to the right change ID/refspec. However if it were to execute the "git cherry-pick FETCH_HEAD" command it would result in a cherry-pick failure (due to merge conflict). I don't see that when i do a "git status" in the branch after the script is done. "git status" shows all clean. – nn_user1982 May 15 '22 at 10:55
  • @nn_user1982 Check the prompt that you `expect`: see my edited answer. – VonC May 15 '22 at 15:40