2626import typing
2727import warnings
2828from dataclasses import dataclass
29+ from os import PathLike
2930
3031# Import from pygit2
31- from ._pygit2 import Diff , Oid , Tree
32+ from ._pygit2 import Diff , Oid , Repository , Tree
3233from .enums import DiffOption , FileMode
3334from .errors import check_error
3435from .ffi import C , ffi
@@ -41,7 +42,7 @@ class Index:
4142 # a proper implementation in some places: e.g. checking the index type
4243 # from C code (see Tree_diff_to_index)
4344
44- def __init__ (self , path : str | None = None ) -> None :
45+ def __init__ (self , path : str | PathLike [ str ] | None = None ) -> None :
4546 """Create a new Index
4647
4748 If path is supplied, the read and write methods will use that path
@@ -116,16 +117,16 @@ def read(self, force=True):
116117 err = C .git_index_read (self ._index , force )
117118 check_error (err , io = True )
118119
119- def write (self ):
120+ def write (self ) -> None :
120121 """Write the contents of the Index to disk."""
121122 err = C .git_index_write (self ._index )
122123 check_error (err , io = True )
123124
124- def clear (self ):
125+ def clear (self ) -> None :
125126 err = C .git_index_clear (self ._index )
126127 check_error (err )
127128
128- def read_tree (self , tree ) :
129+ def read_tree (self , tree : Oid | Tree | str ) -> None :
129130 """Replace the contents of the Index with those of the given tree,
130131 expressed either as a <Tree> object or as an oid (string or <Oid>).
131132
@@ -134,6 +135,8 @@ def read_tree(self, tree):
134135 """
135136 repo = self ._repo
136137 if isinstance (tree , str ):
138+ if repo is None :
139+ raise TypeError ('id given but no associated repository' )
137140 tree = repo [tree ]
138141
139142 if isinstance (tree , Oid ):
@@ -142,14 +145,14 @@ def read_tree(self, tree):
142145
143146 tree = repo [tree ]
144147 elif not isinstance (tree , Tree ):
145- raise TypeError ('argument must be Oid or Tree ' )
148+ raise TypeError ('argument must be Oid, Tree or str ' )
146149
147150 tree_cptr = ffi .new ('git_tree **' )
148151 ffi .buffer (tree_cptr )[:] = tree ._pointer [:]
149152 err = C .git_index_read_tree (self ._index , tree_cptr [0 ])
150153 check_error (err )
151154
152- def write_tree (self , repo = None ):
155+ def write_tree (self , repo : Repository | None = None ) -> Oid :
153156 """Create a tree out of the Index. Return the <Oid> object of the
154157 written tree.
155158
@@ -172,23 +175,23 @@ def write_tree(self, repo=None):
172175 check_error (err )
173176 return Oid (raw = bytes (ffi .buffer (coid )[:]))
174177
175- def remove (self , path , level = 0 ) :
178+ def remove (self , path : PathLike [ str ] | str , level : int = 0 ) -> None :
176179 """Remove an entry from the Index."""
177180 err = C .git_index_remove (self ._index , to_bytes (path ), level )
178181 check_error (err , io = True )
179182
180- def remove_directory (self , path , level = 0 ) :
183+ def remove_directory (self , path : PathLike [ str ] | str , level : int = 0 ) -> None :
181184 """Remove a directory from the Index."""
182185 err = C .git_index_remove_directory (self ._index , to_bytes (path ), level )
183186 check_error (err , io = True )
184187
185- def remove_all (self , pathspecs ) :
188+ def remove_all (self , pathspecs : typing . Sequence [ str | PathLike [ str ]]) -> None :
186189 """Remove all index entries matching pathspecs."""
187190 with StrArray (pathspecs ) as arr :
188191 err = C .git_index_remove_all (self ._index , arr .ptr , ffi .NULL , ffi .NULL )
189192 check_error (err , io = True )
190193
191- def add_all (self , pathspecs = None ):
194+ def add_all (self , pathspecs : None | list [ str | PathLike [ str ]] = None ) -> None :
192195 """Add or update index entries matching files in the working directory.
193196
194197 If pathspecs are specified, only files matching those pathspecs will
@@ -199,7 +202,7 @@ def add_all(self, pathspecs=None):
199202 err = C .git_index_add_all (self ._index , arr .ptr , 0 , ffi .NULL , ffi .NULL )
200203 check_error (err , io = True )
201204
202- def add (self , path_or_entry ) :
205+ def add (self , path_or_entry : 'IndexEntry | str | PathLike[str]' ) -> None :
203206 """Add or update an entry in the Index.
204207
205208 If a path is given, that file will be added. The path must be relative
@@ -217,11 +220,13 @@ def add(self, path_or_entry):
217220 path = path_or_entry
218221 err = C .git_index_add_bypath (self ._index , to_bytes (path ))
219222 else :
220- raise TypeError ('argument must be string or IndexEntry' )
223+ raise TypeError ('argument must be string, Path or IndexEntry' )
221224
222225 check_error (err , io = True )
223226
224- def add_conflict (self , ancestor , ours , theirs ):
227+ def add_conflict (
228+ self , ancestor : 'IndexEntry' , ours : 'IndexEntry' , theirs : 'IndexEntry | None'
229+ ) -> None :
225230 """
226231 Add or update index entries to represent a conflict. Any staged entries that
227232 exist at the given paths will be removed.
@@ -243,7 +248,9 @@ def add_conflict(self, ancestor, ours, theirs):
243248 if theirs and not isinstance (theirs , IndexEntry ):
244249 raise TypeError ('theirs has to be an instance of IndexEntry or None' )
245250
246- centry_ancestor = centry_ours = centry_theirs = ffi .NULL
251+ centry_ancestor : ffi .NULL_TYPE | ffi .GitIndexEntryC = ffi .NULL
252+ centry_ours : ffi .NULL_TYPE | ffi .GitIndexEntryC = ffi .NULL
253+ centry_theirs : ffi .NULL_TYPE | ffi .GitIndexEntryC = ffi .NULL
247254 if ancestor is not None :
248255 centry_ancestor , _ = ancestor ._to_c ()
249256 if ours is not None :
@@ -418,7 +425,7 @@ def _from_c(cls, centry):
418425
419426
420427class IndexEntry :
421- path : str
428+ path : str | PathLike [ str ]
422429 'The path of this entry'
423430
424431 id : Oid
@@ -427,7 +434,9 @@ class IndexEntry:
427434 mode : FileMode
428435 'The mode of this entry, a FileMode value'
429436
430- def __init__ (self , path , object_id : Oid , mode : FileMode ):
437+ def __init__ (
438+ self , path : str | PathLike [str ], object_id : Oid , mode : FileMode
439+ ) -> None :
431440 self .path = path
432441 self .id = object_id
433442 self .mode = mode
@@ -459,7 +468,7 @@ def __eq__(self, other):
459468 self .path == other .path and self .id == other .id and self .mode == other .mode
460469 )
461470
462- def _to_c (self ):
471+ def _to_c (self ) -> tuple [ 'ffi.GitIndexEntryC' , 'ffi.ArrayC[ffi.char]' ] :
463472 """Convert this entry into the C structure
464473
465474 The first returned arg is the pointer, the second is the reference to
0 commit comments