git-p4: detect/prevent infinite loop in gitCommitByP4Change()
Under certain circumstances, gitCommitByP4Change() can enter an infinite
loop resulting in `git p4 sync` hanging forever.
The problem is that
`git rev-list --bisect <latest> ^<earliest>` can return `<latest>`,
which would result in reinspecting <latest> and potentially an infinite loop.
This can happen when importing just a subset of P4 repository
and/or with explicit "--changesfile" option.
A real-life example:
"""
looking in ref refs/remotes/p4/mybranch for change 26894 using bisect...
Reading pipe: git rev-parse refs/remotes/p4/mybranch
trying: earliest latest
4daff81c520a82678e1ef347f2b5e97258101ae1
Reading pipe: git rev-list --bisect
4daff81c520a82678e1ef347f2b5e97258101ae1
Reading pipe: git cat-file commit
147f5d3292af2e1cc4a56a7b96db845144c68486
current change 25339
trying: earliest ^
147f5d3292af2e1cc4a56a7b96db845144c68486 latest
4daff81c520a82678e1ef347f2b5e97258101ae1
Reading pipe: git rev-list --bisect
4daff81c520a82678e1ef347f2b5e97258101ae1 ^
147f5d3292af2e1cc4a56a7b96db845144c68486
Reading pipe: git cat-file commit
51db83df9d588010d0bd995641c85aa0408a5bb9
current change 25420
trying: earliest ^
51db83df9d588010d0bd995641c85aa0408a5bb9 latest
4daff81c520a82678e1ef347f2b5e97258101ae1
Reading pipe: git rev-list --bisect
4daff81c520a82678e1ef347f2b5e97258101ae1 ^
51db83df9d588010d0bd995641c85aa0408a5bb9
Reading pipe: git cat-file commit
e8f83909ceb570f5a7e48c2853f3c5d8207cea52
current change 25448
trying: earliest ^
e8f83909ceb570f5a7e48c2853f3c5d8207cea52 latest
4daff81c520a82678e1ef347f2b5e97258101ae1
Reading pipe: git rev-list --bisect
4daff81c520a82678e1ef347f2b5e97258101ae1 ^
e8f83909ceb570f5a7e48c2853f3c5d8207cea52
Reading pipe: git cat-file commit
09a48eb7acd594dce52e06681be9c366e1844d66
current change 25521
trying: earliest ^
09a48eb7acd594dce52e06681be9c366e1844d66 latest
4daff81c520a82678e1ef347f2b5e97258101ae1
Reading pipe: git rev-list --bisect
4daff81c520a82678e1ef347f2b5e97258101ae1 ^
09a48eb7acd594dce52e06681be9c366e1844d66
Reading pipe: git cat-file commit
4daff81c520a82678e1ef347f2b5e97258101ae1
current change 26907
trying: earliest ^
09a48eb7acd594dce52e06681be9c366e1844d66 latest
4daff81c520a82678e1ef347f2b5e97258101ae1
Reading pipe: git rev-list --bisect
4daff81c520a82678e1ef347f2b5e97258101ae1 ^
09a48eb7acd594dce52e06681be9c366e1844d66
Reading pipe: git cat-file commit
4daff81c520a82678e1ef347f2b5e97258101ae1
current change 26907
trying: earliest ^
09a48eb7acd594dce52e06681be9c366e1844d66 latest
4daff81c520a82678e1ef347f2b5e97258101ae1
Reading pipe: git rev-list --bisect
4daff81c520a82678e1ef347f2b5e97258101ae1 ^
09a48eb7acd594dce52e06681be9c366e1844d66
Reading pipe: git cat-file commit
4daff81c520a82678e1ef347f2b5e97258101ae1
current change 26907
...
"""
The fix is two-fold:
* detect an infinite loop and die right away
instead of looping forever;
* make sure, `git rev-list --bisect` can't return "latestCommit" again
by excluding it from the rev-list range explicitly.
Signed-off-by: Andrey Mazo <amazo@checkvideo.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>