@@ -557,21 +557,38 @@ def as_pretty_string(self) -> str:
557557 return self .as_raw_string ().decode ("utf-8" , "replace" )
558558
559559 def set_raw_string (
560- self , text : bytes , sha : ObjectID | RawObjectID | None = None
560+ self ,
561+ text : bytes ,
562+ sha : ObjectID | RawObjectID | None = None ,
563+ * ,
564+ verify_sha : ObjectID | RawObjectID | None = None ,
561565 ) -> None :
562566 """Set the contents of this object from a serialized string."""
563567 if not isinstance (text , bytes ):
564568 raise TypeError (f"Expected bytes for text, got { text !r} " )
565- self .set_raw_chunks ([text ], sha )
569+ self .set_raw_chunks ([text ], sha , verify_sha = verify_sha )
566570
567571 def set_raw_chunks (
568572 self ,
569573 chunks : list [bytes ],
570574 sha : ObjectID | RawObjectID | None = None ,
571575 * ,
572576 object_format : ObjectFormat | None = None ,
577+ verify_sha : ObjectID | RawObjectID | None = None ,
573578 ) -> None :
574- """Set the contents of this object from a list of chunks."""
579+ """Set the contents of this object from a list of chunks.
580+
581+ Args:
582+ chunks: The raw uncompressed contents.
583+ sha: Optional known, trusted sha for the object. Cached without
584+ being checked against the contents.
585+ object_format: Optional hash algorithm for the object.
586+ verify_sha: Optional sha that the contents are checked against;
587+ raises ChecksumMismatch if the object does not hash to it. On
588+ success it is cached like ``sha``. Mutually exclusive with ``sha``.
589+ """
590+ if sha is not None and verify_sha is not None :
591+ raise ValueError ("sha and verify_sha are mutually exclusive" )
575592 self ._chunked_text = chunks
576593 # Set hash algorithm if provided
577594 if object_format is not None :
@@ -583,6 +600,11 @@ def set_raw_chunks(
583600 self ._sha = FixedSha (sha )
584601 self ._deserialize (chunks )
585602 self ._needs_serialization = False
603+ if verify_sha is not None :
604+ got = self .get_id (self .object_format )
605+ if got != verify_sha :
606+ raise ChecksumMismatch (verify_sha , got )
607+ self ._sha = FixedSha (verify_sha )
586608
587609 @staticmethod
588610 def _parse_object_header (
@@ -690,22 +712,25 @@ def from_raw_string(
690712 sha : ObjectID | RawObjectID | None = None ,
691713 * ,
692714 object_format : ObjectFormat | None = None ,
715+ verify_sha : ObjectID | RawObjectID | None = None ,
693716 ) -> "ShaFile" :
694717 """Creates an object of the indicated type from the raw string given.
695718
696719 Args:
697720 type_num: The numeric type of the object.
698721 string: The raw uncompressed contents.
699- sha: Optional known sha for the object
722+ sha: Optional known, trusted sha for the object.
700723 object_format: Optional hash algorithm for the object
724+ verify_sha: Optional sha to check the contents against; raises
725+ ChecksumMismatch on mismatch. Mutually exclusive with ``sha``.
701726 """
702727 cls = object_class (type_num )
703728 if cls is None :
704729 raise AssertionError (f"unsupported class type num: { type_num } " )
705730 obj = cls ()
706731 if object_format is not None :
707732 obj .object_format = object_format
708- obj .set_raw_string (string , sha )
733+ obj .set_raw_string (string , sha , verify_sha = verify_sha )
709734 return obj
710735
711736 @staticmethod
0 commit comments