Edgewall Software
Modify

Opened 8 months ago

Closed 8 months ago

#13747 closed defect (fixed)

IndexError raised from GitRepository.normalize_rev('FFFF') if the repository has 5000+ revisions

Reported by: Jun Omae Owned by: Jun Omae
Priority: normal Milestone: 1.6.1
Component: plugin/git Version: 1.0.20
Severity: normal Keywords:
Cc: Branch:
Release Notes:

Fixed IndexError raised from GitRepository.normalize_rev('FFFF') if the repository has 5,000+ revisions.

API Changes:
Internal Changes:

Description

Traceback (most recent call last):
  File "/venv/lib/python2.7/site-packages/trac/timeline/web_ui.py", line 198, in process_request
    filters) or []:
  File "/venv/lib/python2.7/site-packages/trac/versioncontrol/web_ui/changeset.py", line 917, in get_timeline_events
    for event in generate_changesets(repos):
  File "/venv/lib/python2.7/site-packages/trac/versioncontrol/web_ui/changeset.py", line 892, in generate_changesets
    for cset in changesets:
  File "/venv/lib/python2.7/site-packages/tracopt/versioncontrol/git/git_fs.py", line 72, in get_changesets
    csets = list(csets)
  File "/venv/lib/python2.7/site-packages/trac/versioncontrol/cache.py", line 82, in get_changesets
    yield self.get_changeset(rev)
  File "/venv/lib/python2.7/site-packages/tracopt/versioncontrol/git/git_fs.py", line 85, in get_changeset
    return GitCachedChangeset(self, self.normalize_rev(rev), self.env)
  File "/venv/lib/python2.7/site-packages/tracopt/versioncontrol/git/git_fs.py", line 56, in normalize_rev
    normrev = self.repos.git.verifyrev(rev)
  File "/venv/lib/python2.7/site-packages/tracopt/versioncontrol/git/PyGIT.py", line 710, in verifyrev
    fullrev = self.fullrev(rev)
  File "/venv/lib/python2.7/site-packages/tracopt/versioncontrol/git/PyGIT.py", line 780, in fullrev
    srevs = _rev_cache.srev_dict[self.__rev_key(srev)]
IndexError: list index out of range

git-data.sh

#! /bin/sh
n="$1"
echo 'blob'
echo 'mark :1'
echo 'data 0'
echo
echo 'reset refs/heads/master'
for i in $(seq 1 "$n"); do
    ts=$((999999999 + $i))
    echo 'commit refs/heads/master'
    echo 'mark :2'
    echo "author Joe <joe@example.com> $ts +0000"
    echo "committer Joe <joe@example.com> $ts +0000"
    echo 'data 2'
    echo '.'
    echo 'M 100644 :1 .gitignore'
    echo
done

Creating test repository with 5,500 revisions

$ git init --bare /dev/shm/git-repos
$ /dev/shm/git-data.sh 5500 | git --git-dir /dev/shm/git-repos fast-import
$ git --git-dir /dev/shm/git-repos rev-list --all | wc -l
5500
$ git --git-dir /dev/shm/git-repos rev-list --all | sed -e 's/^\(....\).*/\1/' | sort -u | wc -l
5272
$ git --git-dir /dev/shm/git-repos rev-list --all | sed -e 's/^\(....\).*/\1/' | sort -u | tail -1
fff9

Trying GitRepository.normalize_rev('FFFF')

$ (cd / && ~/venv/trac/1.6/bin/python)
Python 3.11.9 (main, Apr  6 2024, 17:59:24) [GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from trac.test import EnvironmentStub
>>> from tracopt.versioncontrol.git.git_fs import GitConnector
>>> env = EnvironmentStub()
>>> connector = GitConnector(env)
>>> repos = connector.get_repository('git', '/dev/shm/git-repos', {'id': 42, 'name': ''})
>>> repos.git.rev_cache
RevCache(youngest_rev=b'39f74414152cc0645367502e8d05a83e34f9c084', oldest_rev=b'86989f7deb1be18dcb970f221d017c58417c56a2', rev_dict=5500 entries, refs_dict=2 entries, srev_dict=65530 entries)
>>> type(repos.git.rev_cache.srev_dict)
<class 'list'>
>>> repos.normalize_rev('FFFF')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/jun66j5/venv/trac/1.6/lib/python3.11/site-packages/tracopt/versioncontrol/git/git_fs.py", line 569, in normalize_rev
    normrev = self.git.verifyrev(rev)
              ^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/jun66j5/venv/trac/1.6/lib/python3.11/site-packages/tracopt/versioncontrol/git/PyGIT.py", line 796, in verifyrev
    result = get_verifyrev(self._fs_from_unicode(rev))
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/jun66j5/venv/trac/1.6/lib/python3.11/site-packages/tracopt/versioncontrol/git/PyGIT.py", line 771, in get_verifyrev
    fullrev = self.fullrev(rev)
              ^^^^^^^^^^^^^^^^^
  File "/home/jun66j5/venv/trac/1.6/lib/python3.11/site-packages/tracopt/versioncontrol/git/PyGIT.py", line 847, in fullrev
    srevs = _rev_cache.srev_dict[self.__rev_key(rev)]
            ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
IndexError: list index out of range
>>> repos.normalize_rev('FFF9')
'fff9a43563e57b091ed4a44ffa3e244082f51175'
>>> repos.git.rev_cache.srev_dict[0xFFF9]
(b'fff9a43563e57b091ed4a44ffa3e244082f51175',)

Patch

  • tracopt/versioncontrol/git/PyGIT.py

    diff --git a/tracopt/versioncontrol/git/PyGIT.py b/tracopt/versioncontrol/git/PyGIT.py
    index e1e660b19..62f0a4bf0 100644
    a b class Storage(object):  
    845845
    846846        try:
    847847            srevs = _rev_cache.srev_dict[self.__rev_key(rev)]
    848         except KeyError:
     848        except (KeyError, IndexError):
    849849            return None
    850850
    851851        resolved = None

Attachments (0)

Change History (1)

comment:1 by Jun Omae, 8 months ago

Release Notes: modified (diff)
Resolution: fixed
Status: assignedclosed

Fixed in [17769] and merged in [17770].

Modify Ticket

Change Properties
Set your email in Preferences
Action
as closed The owner will remain Jun Omae.
The resolution will be deleted. Next status will be 'reopened'.
to The owner will be changed from Jun Omae to the specified user.

Add Comment


E-mail address and name can be saved in the Preferences .
 
Note: See TracTickets for help on using tickets.