Ticket #2198: base-src-port1.0-portchecksum.tcl.diff

File base-src-port1.0-portchecksum.tcl.diff, 6.1 KB (added by opendarwin.org@…, 20 years ago)

better portchecksum.tcl changes

  • src/port1.0/portchecksum.tcl

    old new  
    4545
    4646set_ui_prefix
    4747
    48 # dmd5
     48# get_checksum
    4949#
    50 # Returns the expected checksum for the given file.
    51 # If no checksum is found, returns -1.
     50# Returns the expected md5/sha1/etc. checksum for the given file.
     51# If no md5/sha1/etc. checksum is found, returns -1.
    5252#
    53 proc dmd5 {file} {
    54         foreach {name type sum} [option checksums] {
     53proc get_checksum {file want_sum port_checksums} {
     54        foreach {name type sum} $port_checksums {
    5555                if {[string equal $name $file]} {
    56                         return $sum
     56                        if {[string equal $type $want_sum]} {
     57                                return $sum
     58                        }
    5759                }
    5860        }
    5961
     
    7779proc checksum_main {args} {
    7880        global UI_PREFIX all_dist_files
    7981
     82        # list of known checksum types as an
     83        # array of string in portfile and function we'll call.
     84        # The string and the function are currently the same, but no
     85        # guarantees that it will remain so.
     86        array set checksum_types { \
     87                "md5"   md5 \
     88                "sha1"  sha1 \
     89        }
     90
    8091        # If no files have been downloaded, there is nothing to checksum.
    8192        if {![info exists all_dist_files]} {
    8293                return 0
    8394        }
    8495
    8596        # Optimization for the two-argument case for checksums.
    86         if {[llength [option checksums]] == 2 && [llength $all_dist_files] == 1} {
    87                 option checksums [linsert [option checksums] 0 $all_dist_files]
     97        ## See if the checksum type from the Portfile matches a known
     98        ## checksum type.  If it does and we only have 1 distfile,
     99        ## insert the distfilename ahead of the checksum type and result
     100        ## from the Portfile.
     101        ## If the type doesn't match a known type and we only have 1 distfile,
     102        ## then its an unknown checksum type, so we barf on it.
     103        ## ELACKSGRACE:  if a Portfile only has 1 distfile *and* the two-arg
     104        ## optimization is not used (i.e. checksum line is <distfile> <type> <sum>)
     105        ## this code thinks that <distfile> is the <type> and barfs on it.
     106        ## I'm not seeing a way around that right now, as the Portfile checksum
     107        ## info comes to us as a list of items.
     108        ##
     109        set port_checksums ""
     110        foreach {type sum} [option checksums] {
     111                ## see if $type is one of our known checksum types.  If it is,
     112                ## we assume we don't have our dist file name.  Check that
     113                ## we only expect 1 dist file as well...  If we have only
     114                ## one dist file and $type is a checksum_type, the add the
     115                ## $all_dist_files to the start of the checksum list.
     116
     117                if {[lsearch -exact [array names checksum_types] $type] != -1 && \
     118                        [llength $all_dist_files] == 1} {
     119                        set port_checksums [linsert $port_checksums 0 $all_dist_files $type $sum]
     120                } else {
     121                        if {[llength $all_dist_files] == 1} {
     122                                return -code error "[format [msgcat::mc "Unknown checksum type '%s'"] $type]"
     123                        }
     124                }
     125        }
     126        ## if we didn't do the above filename insertions, we have an empty $port_checksums,
     127        ## so copy over the [option checksums] and use $port_checksums from here out
     128        if {[llength $port_checksums] == 0} {
     129                set port_checksums [option checksums]
    88130        }
    89131
    90132        set fail no
    91133
    92134        foreach distfile $all_dist_files {
    93135                ui_info "$UI_PREFIX [format [msgcat::mc "Checksumming %s"] $distfile]"
     136                set distfile_chksum_success 0
    94137
    95                 # Calculate the distfile's checksum.
    96                 set checksum [md5 file [file join [option distpath] $distfile]]
    97 
    98                 # Find the expected checksum.
    99                 set dchecksum [dmd5 $distfile]
    100 
    101                 # Check for missing checksum or a mismatch.
    102                 if {$dchecksum == -1} {
    103                         ui_error "[format [msgcat::mc "No checksum set for %s"] $distfile]"
    104                 } elseif {![string equal $checksum $dchecksum]} {
    105                         ui_error "[format [msgcat::mc "Checksum mismatch for %s"] $distfile]"
    106                 } else {
    107                         continue
     138                ## XYZZY: as I look at this again, I'm thinking maybe we're doing
     139                ## it backwards - rather than calculate the checksum then go look for
     140                ## it, we should find the checksums we do have, then calculate those
     141                ## and compare, and note our successes.  We can then show those
     142                ## checksum types we know about that were not in the Portfile, and
     143                ## make mention of it.
     144                foreach chksum_type [array names checksum_types] {
     145                        # Find the expected checksum.
     146                        set dchecksum [get_checksum $distfile $chksum_type $port_checksums]
     147
     148                        # Check for missing checksum
     149                        if {$dchecksum == -1} {
     150                                ui_info "$UI_PREFIX [format [msgcat::mc "No %s checksum set for %s"] $chksum_type $distfile]"
     151                                ## and lets try the next one...
     152                                continue
     153                        }
     154                        ## sanity check - Do we actually have checksum routine?
     155                        if {[string length [info commands $checksum_types($chksum_type)]]} {
     156                                # Calculate the distfile's checksum.
     157                                set checksum [$checksum_types($chksum_type) file [file join [option distpath] $distfile]]
     158                        } else {
     159                                ## explode catch fire?  Just throw a warning and continue? Hmmm.
     160                                ui_error "$UI_PREFIX [format [msgcat::mc "Can't find checksum routine '%s' for checksum type '%s'"] $checksum_types($chksum_type) $chksum_type]"
     161                                continue
     162                        }
     163
     164                        # Check for checksum mismatch.
     165                        if {![string equal $checksum $dchecksum]} {
     166                                ui_error "$UI_PREFIX [format [msgcat::mc "%s checksum mismatch for '%s':"] $chksum_type $distfile]"
     167                                ui_error "$UI_PREFIX [format [msgcat::mc "wanted '%s',"] $dchecksum]"
     168                                ui_error "$UI_PREFIX [format [msgcat::mc "   got '%s'"] $checksum]"
     169                                # Raise the failure flag
     170                                set fail yes
     171                        } else {
     172                                set distfile_chksum_success [expr $distfile_chksum_success + 1]
     173                        }
     174       
     175                        if {[tbool fail]} {
     176                                return -code error "[format [msgcat::mc "Unable to verify %s checksum"] $chksum_type]"
     177                        }
     178                        ## else just fall to the next checksum...
     179       
     180                        if {$dchecksum != -1} {
     181                                # Post file checksum
     182                                ui_info "$UI_PREFIX [format [msgcat::mc "Correct %s checksum: %s %s %s"] $chksum_type ${distfile} $chksum_type ${checksum}]"
     183                        }
    108184                }
    109185
    110                 # Post file checksum
    111                 ui_info "[format [msgcat::mc "Correct checksum: %s %s %s"] ${distfile} md5 ${checksum}]"
    112 
    113                 # Raise the failure flag
    114                 set fail yes
    115         }
    116 
    117         if {[tbool fail]} {
    118                 return -code error "[msgcat::mc "Unable to verify file checksums"]"
     186                if {$distfile_chksum_success == 0} {
     187                        ## oh bother, no successful checksum for this dist file, bailage
     188                        return -code error "[format [msgcat::mc "No checksums set for %s"] $distfile]"
     189                }
    119190        }
    120191
    121192        return 0