You've already forked macports-base
mirror of
https://github.com/macports/macports-base.git
synced 2026-07-12 18:18:43 -07:00
Split port1.0 targets a-d
See 0b375d0669
This commit is contained in:
@@ -13,6 +13,9 @@ SRCS= port.tcl portchecksum.tcl portconfigure.tcl portextract.tcl \
|
||||
portdeactivate.tcl portstartupitem.tcl porttrace.tcl portlivecheck.tcl \
|
||||
portdistcheck.tcl portmirror.tcl portload.tcl portunload.tcl portreload.tcl \
|
||||
portdistfiles.tcl fetch_common.tcl portsandbox.tcl \
|
||||
portactivate_run.tcl portbuild_run.tcl portbump_run.tcl portchecksum_run.tcl \
|
||||
portclean_run.tcl portconfigure_run.tcl portdeactivate_run.tcl \
|
||||
portdestroot_run.tcl portdistcheck_run.tcl portdistfiles_run.tcl \
|
||||
portfetch_run.tcl
|
||||
|
||||
include $(srcdir)/../../Mk/macports.subdir.mk
|
||||
|
||||
@@ -1,40 +1,8 @@
|
||||
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
|
||||
# portactivate.tcl
|
||||
#
|
||||
# Copyright (c) 2005, 2007, 2009-2011 The MacPorts Project
|
||||
# Copyright (c) 2004 Robert Shaw <rshaw@opendarwin.org>
|
||||
# Copyright (c) 2002 - 2003 Apple Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of Apple Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
# the 'activate' target is provided by this package
|
||||
|
||||
package provide portactivate 1.0
|
||||
package require portutil 1.0
|
||||
|
||||
set org.macports.activate [target_new org.macports.activate portactivate::activate_main]
|
||||
target_runtype ${org.macports.activate} always
|
||||
@@ -43,66 +11,7 @@ target_provides ${org.macports.activate} activate
|
||||
target_requires ${org.macports.activate} main archivefetch fetch checksum extract patch configure build destroot install
|
||||
target_prerun ${org.macports.activate} portactivate::activate_start
|
||||
target_postrun ${org.macports.activate} portactivate::activate_finish
|
||||
|
||||
namespace eval portactivate {
|
||||
}
|
||||
target_runpkg ${org.macports.activate} portactivate_run
|
||||
|
||||
options activate.asroot
|
||||
default activate.asroot no
|
||||
|
||||
proc portactivate::activate_start {args} {
|
||||
global prefix_frozen
|
||||
if {![file writable $prefix_frozen] || ([getuid] == 0 && [geteuid] != 0)} {
|
||||
# if install location is not writable, need root privileges
|
||||
elevateToRoot "activate"
|
||||
}
|
||||
}
|
||||
|
||||
proc portactivate::activate_main {args} {
|
||||
global subport _inregistry_version _inregistry_revision _inregistry_variants prefix user_options
|
||||
foreach {var backup} {_inregistry_version version _inregistry_revision revision _inregistry_variants portvariants} {
|
||||
if {![info exists $var]} {
|
||||
set $var [option $backup]
|
||||
}
|
||||
}
|
||||
|
||||
set reg_options [dict create {*}[array get user_options]]
|
||||
set renames [dict create]
|
||||
portstartupitem::foreach_startupitem {
|
||||
if {$si_install} {
|
||||
dict set renames ${prefix}/etc/${si_location}/${si_plist} /Library/${si_location}/${si_plist}
|
||||
} else {
|
||||
dict set renames /Library/${si_location}/${si_plist} ${prefix}/etc/${si_location}/${si_plist}
|
||||
}
|
||||
}
|
||||
dict set reg_options portactivate_rename_files $renames
|
||||
|
||||
registry_activate $subport $_inregistry_version $_inregistry_revision $_inregistry_variants $reg_options
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
proc portactivate::activate_finish {args} {
|
||||
global subport PortInfo startupitem_autostart
|
||||
|
||||
# Do this _after_ activate_main, because post-activate hooks might create
|
||||
# the files needed for this
|
||||
# The option from macports.conf can override the portfile here.
|
||||
if {[tbool startupitem_autostart]} {
|
||||
global portstartupitem::autostart_only
|
||||
set autostart_only yes
|
||||
if {[eval_targets "load"]} {
|
||||
ui_error [format [msgcat::mc "Failed to load %s"] $subport]
|
||||
unset autostart_only
|
||||
return 1
|
||||
}
|
||||
unset autostart_only
|
||||
}
|
||||
|
||||
# Save notes for display by the port client
|
||||
if {[info exists PortInfo(notes)] && [llength $PortInfo(notes)] > 0} {
|
||||
ui_notifications_append $subport $PortInfo(notes)
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
|
||||
#
|
||||
# Copyright (c) 2005, 2007, 2009-2011 The MacPorts Project
|
||||
# Copyright (c) 2004 Robert Shaw <rshaw@opendarwin.org>
|
||||
# Copyright (c) 2002 - 2003 Apple Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of Apple Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package provide portactivate_run 1.0
|
||||
package require portstartupitem 1.0
|
||||
package require portutil 1.0
|
||||
|
||||
namespace eval portactivate {
|
||||
|
||||
proc activate_start {args} {
|
||||
global prefix_frozen
|
||||
if {![file writable $prefix_frozen] || ([getuid] == 0 && [geteuid] != 0)} {
|
||||
# if install location is not writable, need root privileges
|
||||
elevateToRoot "activate"
|
||||
}
|
||||
}
|
||||
|
||||
proc activate_main {args} {
|
||||
global subport _inregistry_version _inregistry_revision _inregistry_variants prefix user_options
|
||||
foreach {var backup} {_inregistry_version version _inregistry_revision revision _inregistry_variants portvariants} {
|
||||
if {![info exists $var]} {
|
||||
set $var [option $backup]
|
||||
}
|
||||
}
|
||||
|
||||
set reg_options [dict create {*}[array get user_options]]
|
||||
set renames [dict create]
|
||||
portstartupitem::foreach_startupitem {
|
||||
if {$si_install} {
|
||||
dict set renames ${prefix}/etc/${si_location}/${si_plist} /Library/${si_location}/${si_plist}
|
||||
} else {
|
||||
dict set renames /Library/${si_location}/${si_plist} ${prefix}/etc/${si_location}/${si_plist}
|
||||
}
|
||||
}
|
||||
dict set reg_options portactivate_rename_files $renames
|
||||
|
||||
registry_activate $subport $_inregistry_version $_inregistry_revision $_inregistry_variants $reg_options
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
proc activate_finish {args} {
|
||||
global subport PortInfo startupitem_autostart
|
||||
|
||||
# Do this _after_ activate_main, because post-activate hooks might create
|
||||
# the files needed for this
|
||||
# The option from macports.conf can override the portfile here.
|
||||
if {[tbool startupitem_autostart]} {
|
||||
global portstartupitem::autostart_only
|
||||
set autostart_only yes
|
||||
if {[eval_targets "load"]} {
|
||||
ui_error [format [msgcat::mc "Failed to load %s"] $subport]
|
||||
unset autostart_only
|
||||
return 1
|
||||
}
|
||||
unset autostart_only
|
||||
}
|
||||
|
||||
# Save notes for display by the port client
|
||||
if {[info exists PortInfo(notes)] && [llength $PortInfo(notes)] > 0} {
|
||||
ui_notifications_append $subport $PortInfo(notes)
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
}
|
||||
@@ -31,13 +31,12 @@
|
||||
#
|
||||
|
||||
package provide portbuild 1.0
|
||||
package require portutil 1.0
|
||||
package require portprogress 1.0
|
||||
|
||||
set org.macports.build [target_new org.macports.build portbuild::build_main]
|
||||
target_provides ${org.macports.build} build
|
||||
target_requires ${org.macports.build} main fetch checksum extract patch configure
|
||||
target_prerun ${org.macports.build} portbuild::build_start
|
||||
target_runpkg ${org.macports.build} portbuild_run
|
||||
|
||||
namespace eval portbuild {
|
||||
}
|
||||
@@ -63,8 +62,6 @@ default build.target all
|
||||
default build.type default
|
||||
default use_parallel_build yes
|
||||
|
||||
set_ui_prefix
|
||||
|
||||
# Automatically called from macports1.0 after evaluating the Portfile. If
|
||||
# ${build.type} == bsd, ensures bsdmake is present by adding a bin:-style
|
||||
# dependency.
|
||||
@@ -200,28 +197,3 @@ proc portbuild::build_getjobsarg {args} {
|
||||
}
|
||||
return " -j$jobs"
|
||||
}
|
||||
|
||||
proc portbuild::build_start {args} {
|
||||
global UI_PREFIX subport
|
||||
|
||||
ui_notice "$UI_PREFIX [format [msgcat::mc "Building %s"] ${subport}]"
|
||||
|
||||
global portconfigure::no_default_compiler_allowed
|
||||
if {$no_default_compiler_allowed} {
|
||||
ui_warn_once no_default_compiler_allowed "All compilers are either blacklisted or unavailable; defaulting to first fallback option"
|
||||
}
|
||||
}
|
||||
|
||||
proc portbuild::build_main {args} {
|
||||
global build.cmd build.jobs_arg
|
||||
|
||||
if {${build.cmd} eq ""} {
|
||||
error "No build command found"
|
||||
}
|
||||
|
||||
set realcmd ${build.cmd}
|
||||
append build.cmd ${build.jobs_arg}
|
||||
command_exec -callback portprogress::target_progress_callback build
|
||||
set build.cmd ${realcmd}
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package provide portbuild_run 1.0
|
||||
package require portutil 1.0
|
||||
package require portprogress 1.0
|
||||
|
||||
namespace eval portbuild {
|
||||
|
||||
proc build_start {args} {
|
||||
global UI_PREFIX subport
|
||||
|
||||
ui_notice "$UI_PREFIX [format [msgcat::mc "Building %s"] ${subport}]"
|
||||
|
||||
global portconfigure::no_default_compiler_allowed
|
||||
if {$no_default_compiler_allowed} {
|
||||
ui_warn_once no_default_compiler_allowed "All compilers are either blacklisted or unavailable; defaulting to first fallback option"
|
||||
}
|
||||
}
|
||||
|
||||
proc build_main {args} {
|
||||
global build.cmd build.jobs_arg
|
||||
|
||||
if {${build.cmd} eq ""} {
|
||||
error "No build command found"
|
||||
}
|
||||
|
||||
set realcmd ${build.cmd}
|
||||
append build.cmd ${build.jobs_arg}
|
||||
command_exec -callback portprogress::target_progress_callback build
|
||||
set build.cmd ${realcmd}
|
||||
return 0
|
||||
}
|
||||
|
||||
}
|
||||
+1
-368
@@ -1,377 +1,10 @@
|
||||
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
|
||||
# portbump.tcl
|
||||
#
|
||||
# Copyright (c) 2019 The MacPorts Project
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of Apple Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package provide portbump 1.0
|
||||
package require portutil 1.0
|
||||
package require portchecksum 1.0
|
||||
|
||||
set org.macports.bump [target_new org.macports.bump portbump::bump_main]
|
||||
target_provides ${org.macports.bump} bump
|
||||
target_runtype ${org.macports.bump} always
|
||||
target_requires ${org.macports.bump} main fetch
|
||||
target_prerun ${org.macports.bump} portbump::bump_start
|
||||
|
||||
namespace eval portbump {
|
||||
}
|
||||
|
||||
# replace_checksums
|
||||
#
|
||||
# Replace old checksum hash values with new ones in a list of lines.
|
||||
# Returns a list of two elements: the modified lines and a list of
|
||||
# line indices where replacements were made.
|
||||
#
|
||||
# Checksum values (hex hashes and integer sizes) are matched as whole
|
||||
# words using \y word-boundary anchors (Tcl ARE syntax), so a size
|
||||
# like 123 cannot accidentally match inside a larger value such as
|
||||
# 12345. All checksum values are alphanumeric ([0-9a-f]+ or [0-9]+)
|
||||
# and contain no regex metacharacters, so they are safe to interpolate
|
||||
# directly into the pattern.
|
||||
#
|
||||
# lines - list of Portfile lines
|
||||
# both_checksums - list of {type old_sum new_sum} triples
|
||||
proc portbump::replace_checksums {lines both_checksums} {
|
||||
set checksum_lines [list]
|
||||
foreach {type sum calculated_sum} $both_checksums {
|
||||
if {$sum eq $calculated_sum} {
|
||||
continue
|
||||
}
|
||||
for {set i 0} {$i < [llength $lines]} {incr i} {
|
||||
set line [lindex $lines $i]
|
||||
if {[regsub -all "\\y${sum}\\y" $line $calculated_sum new_line]} {
|
||||
lset lines $i $new_line
|
||||
lappend checksum_lines $i
|
||||
}
|
||||
}
|
||||
}
|
||||
return [list $lines $checksum_lines]
|
||||
}
|
||||
|
||||
# find_revision_line
|
||||
#
|
||||
# Find the line index of the revision that should be reset for the
|
||||
# given subport. Handles Portfiles with multiple revision lines across
|
||||
# subport blocks, conditional branches, or inline subport declarations
|
||||
# (e.g. "subport foo { revision 3 }").
|
||||
#
|
||||
# Strategy:
|
||||
# 1. If the current subport has an inline revision on its subport
|
||||
# declaration line, use that.
|
||||
# 2. Otherwise, use the standalone revision line nearest to the
|
||||
# anchor (typically the first checksum line that was modified).
|
||||
# When bumping the parent port, revision lines inside subport { }
|
||||
# blocks are excluded.
|
||||
#
|
||||
# lines - list of Portfile lines
|
||||
# subport - current subport name
|
||||
# portname - parent port name
|
||||
# anchor - line index to measure proximity from
|
||||
#
|
||||
# Returns: line index, or -1 if no revision line found
|
||||
proc portbump::find_revision_line {lines subport portname anchor} {
|
||||
# For a subport, prefer an inline revision on its subport declaration line
|
||||
# (e.g. "subport clang-16 { revision 9 }").
|
||||
if {$subport ne $portname} {
|
||||
set escaped_subport [string map {\\ \\\\ . \\. * \\* + \\+ ? \\? ( \\( ) \\) \{ \\\{ \} \\\} \[ \\\[ \] \\\]} $subport]
|
||||
for {set i 0} {$i < [llength $lines]} {incr i} {
|
||||
if {[regexp "^\\s*subport\\s+\\S*${escaped_subport}\\S*\\s+.*revision\\s+\\d+" [lindex $lines $i]]} {
|
||||
return $i
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# When bumping the parent port, build an exclusion set of lines inside
|
||||
# subport { } blocks so their revision lines are not mistakenly targeted.
|
||||
set in_subport_block [dict create]
|
||||
if {$subport eq $portname} {
|
||||
set brace_depth 0
|
||||
set in_subport 0
|
||||
for {set i 0} {$i < [llength $lines]} {incr i} {
|
||||
set line [lindex $lines $i]
|
||||
if {!$in_subport && [regexp {^\s*subport\s+} $line]} {
|
||||
set in_subport 1
|
||||
set opens [regexp -all {\{} $line]
|
||||
set closes [regexp -all {\}} $line]
|
||||
set brace_depth [expr {$opens - $closes}]
|
||||
dict set in_subport_block $i 1
|
||||
if {$brace_depth <= 0} {
|
||||
set in_subport 0
|
||||
set brace_depth 0
|
||||
}
|
||||
} elseif {$in_subport} {
|
||||
dict set in_subport_block $i 1
|
||||
set opens [regexp -all {\{} $line]
|
||||
set closes [regexp -all {\}} $line]
|
||||
incr brace_depth [expr {$opens - $closes}]
|
||||
if {$brace_depth <= 0} {
|
||||
set in_subport 0
|
||||
set brace_depth 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Find the nearest standalone revision line, skipping any inside subport blocks.
|
||||
set best_line -1
|
||||
set best_dist 2147483647
|
||||
for {set i 0} {$i < [llength $lines]} {incr i} {
|
||||
if {[regexp {^\s*revision\s+\d+} [lindex $lines $i]]} {
|
||||
if {[dict exists $in_subport_block $i]} {
|
||||
continue
|
||||
}
|
||||
set dist [expr {abs($i - $anchor)}]
|
||||
if {$dist < $best_dist} {
|
||||
set best_dist $dist
|
||||
set best_line $i
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $best_line
|
||||
}
|
||||
|
||||
# reset_revision
|
||||
#
|
||||
# Reset the revision value to 0 on the specified line.
|
||||
# Returns the modified list of lines.
|
||||
#
|
||||
# lines - list of Portfile lines
|
||||
# line_idx - index of the line to modify
|
||||
proc portbump::reset_revision {lines line_idx} {
|
||||
set old_line [lindex $lines $line_idx]
|
||||
set new_line [regsub {(revision\s+)\d+} $old_line {\10}]
|
||||
if {$old_line ne $new_line} {
|
||||
lset lines $line_idx $new_line
|
||||
}
|
||||
return $lines
|
||||
}
|
||||
|
||||
# bump_start
|
||||
#
|
||||
# Target prerun procedure; simply prints a message about what we're doing.
|
||||
#
|
||||
proc portbump::bump_start {args} {
|
||||
global UI_PREFIX subport
|
||||
|
||||
ui_notice "$UI_PREFIX [format [msgcat::mc "Bumping checksums for %s"] ${subport}]"
|
||||
}
|
||||
|
||||
# bump_main
|
||||
#
|
||||
# Target main procedure. Bumps the checksums for distfiles.
|
||||
#
|
||||
proc portbump::bump_main {args} {
|
||||
global UI_PREFIX all_dist_files checksums_array portpath ports_bump_patch
|
||||
|
||||
set portfile "${portpath}/Portfile"
|
||||
|
||||
# If no files have been downloaded, there is nothing to bump.
|
||||
if {![info exists all_dist_files]} {
|
||||
return 0
|
||||
}
|
||||
|
||||
# So far, no mismatches yet.
|
||||
set mismatch no
|
||||
set wrong_mimetype no
|
||||
|
||||
# Read the declared checksums from the port options.
|
||||
set checksums_str [option checksums]
|
||||
|
||||
# If everything is fine with the syntax, keep on and check the checksum of
|
||||
# the distfiles.
|
||||
if {[portchecksum::parse_checksums $checksums_str] eq "yes"} {
|
||||
global distpath
|
||||
|
||||
set both_checksums [list]
|
||||
foreach distfile $all_dist_files {
|
||||
ui_info "$UI_PREFIX [format [msgcat::mc "Checksumming %s"] $distfile]"
|
||||
|
||||
# Get the full path of the distfile.
|
||||
set fullpath [file join $distpath $distfile]
|
||||
if {![file isfile $fullpath]} {
|
||||
return -code error "$distfile does not exist in $distpath"
|
||||
}
|
||||
|
||||
# Check that there is at least one checksum for the distfile.
|
||||
if {![info exists checksums_array($distfile)] || [llength $checksums_array($distfile)] < 1} {
|
||||
ui_error "[format [msgcat::mc "No checksum set for %s"] $distfile]"
|
||||
set mismatch yes
|
||||
} else {
|
||||
# Retrieve the list of types/values from the array.
|
||||
set portfile_checksums $checksums_array($distfile)
|
||||
|
||||
# Iterate on this list to check the actual values.
|
||||
foreach {type sum} $portfile_checksums {
|
||||
set calculated_sum [portchecksum::calc_$type $fullpath]
|
||||
lappend both_checksums $type $sum $calculated_sum
|
||||
|
||||
if {$sum eq $calculated_sum} {
|
||||
ui_debug "[format [msgcat::mc "Correct (%s) bump for %s"] $type $distfile]"
|
||||
} else {
|
||||
ui_info "[format [msgcat::mc "Portfile bump: %s %s %s"] $distfile $type $sum]"
|
||||
ui_info "[format [msgcat::mc "Distfile bump: %s %s %s"] $distfile $type $calculated_sum]"
|
||||
|
||||
# Raise the failure flag
|
||||
set mismatch yes
|
||||
}
|
||||
}
|
||||
|
||||
if {![regexp {\.html?$} ${distfile}] &&
|
||||
![catch {strsed [exec [findBinary file $::portutil::autoconf::file_path] $fullpath --brief --mime] {s/;.*$//}} mimetype]
|
||||
&& "text/html" eq $mimetype} {
|
||||
# file --mime-type would be preferable to file --mime and strsed, but is only available as of Snow Leopard
|
||||
set wrong_mimetype yes
|
||||
set htmlfile_path ${fullpath}.html
|
||||
file rename -force $fullpath $htmlfile_path
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
# Something went wrong with the syntax.
|
||||
return -code error "[msgcat::mc "Unable to verify file checksums"]"
|
||||
}
|
||||
|
||||
if {![tbool mismatch]} {
|
||||
ui_msg "No changes needed."
|
||||
return 0
|
||||
}
|
||||
|
||||
if {[tbool wrong_mimetype]} {
|
||||
# We got an HTML file, though the distfile name does not suggest that one was
|
||||
# expected. Probably a helpful DNS server sent us to its search results page
|
||||
# instead of admitting that the server we asked for doesn't exist, or a mirror that
|
||||
# no longer has the file served its error page with a 200 response.
|
||||
ui_notice "***"
|
||||
ui_notice "The non-matching file appears to be HTML. See this page for possible reasons"
|
||||
ui_notice "for the bump mismatch:"
|
||||
ui_notice "<https://trac.macports.org/wiki/MisbehavingServers>"
|
||||
ui_notice "***"
|
||||
ui_notice "The file has been moved to: $htmlfile_path"
|
||||
|
||||
return -code error "[msgcat::mc "Unable to verify file checksums"]"
|
||||
} else {
|
||||
global version subport
|
||||
|
||||
ui_msg "We will bump these:"
|
||||
foreach {type sum calculated_sum} $both_checksums {
|
||||
if {$sum eq $calculated_sum} {
|
||||
continue
|
||||
}
|
||||
ui_msg [format "Old %-8s %s" ${type}: $sum]
|
||||
ui_msg [format "New %-8s %s" ${type}: $calculated_sum]
|
||||
}
|
||||
|
||||
# Get the uid of Portfile owner
|
||||
set owneruid [name_to_uid [file attributes ${portfile} -owner]]
|
||||
|
||||
# root -> owner id
|
||||
exec_as_uid $owneruid {
|
||||
# Read the Portfile
|
||||
set fd [open $portfile r]
|
||||
set lines [split [read $fd] \n]
|
||||
close $fd
|
||||
|
||||
# Get Portfile attributes
|
||||
set attributes [file attributes $portfile]
|
||||
|
||||
lassign [portbump::replace_checksums $lines $both_checksums] lines checksum_lines
|
||||
foreach cl $checksum_lines {
|
||||
ui_debug "Replaced checksum on line [expr {$cl + 1}]"
|
||||
}
|
||||
|
||||
if {[llength $checksum_lines] > 0} {
|
||||
set rev_line [portbump::find_revision_line $lines $subport [option name] [lindex $checksum_lines 0]]
|
||||
if {$rev_line >= 0} {
|
||||
set old_rev [lindex $lines $rev_line]
|
||||
set lines [portbump::reset_revision $lines $rev_line]
|
||||
if {[lindex $lines $rev_line] ne $old_rev} {
|
||||
ui_debug "Reset revision to 0 on line [expr {$rev_line + 1}]"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set new_content [join $lines \n]
|
||||
|
||||
if {[tbool ports_bump_patch]} {
|
||||
# Patch mode
|
||||
if {[catch {set tmpfd [file tempfile tmpfile ${portpath}/Portfile.bump]} error]} {
|
||||
ui_debug $::errorInfo
|
||||
ui_error "file tempfile: $error"
|
||||
return -code error "file tempfile failed"
|
||||
}
|
||||
puts -nonewline $tmpfd $new_content
|
||||
close $tmpfd
|
||||
|
||||
set patchfile "${portpath}/Portfile.patch"
|
||||
set patchfd [open $patchfile w]
|
||||
|
||||
# Construct diff command
|
||||
set diffcmd [list]
|
||||
lappend diffcmd $::portutil::autoconf::diff_path -u --label old/Portfile --label new/Portfile
|
||||
lappend diffcmd $portfile $tmpfile >@$patchfd
|
||||
|
||||
# Create and write diff to Portfile.patch
|
||||
if {[catch {exec -ignorestderr -- {*}$diffcmd} error]} {
|
||||
file attributes $patchfile {*}$attributes
|
||||
ui_msg "Portfile.patch successfully created at $patchfile"
|
||||
} else {
|
||||
ui_msg "No changes needed."
|
||||
file delete "$patchfile"
|
||||
close $patchfd
|
||||
}
|
||||
|
||||
file delete "$tmpfile"
|
||||
} else {
|
||||
# Overwrite mode
|
||||
if {[catch {set tmpfd [file tempfile tmpfile ${portpath}/Portfile.bump]} error]} {
|
||||
ui_debug $::errorInfo
|
||||
ui_error "file tempfile: $error"
|
||||
return -code error "file tempfile failed"
|
||||
}
|
||||
puts -nonewline $tmpfd $new_content
|
||||
close $tmpfd
|
||||
|
||||
if {[catch {move -force $tmpfile $portfile} error]} {
|
||||
ui_debug $::errorInfo
|
||||
ui_error "bump: $error"
|
||||
file delete "$tmpfile"
|
||||
return -code error "bump overwrite failed"
|
||||
}
|
||||
|
||||
# Restore Portfile attributes
|
||||
file attributes $portfile {*}$attributes
|
||||
|
||||
ui_msg "Checksums successfully bumped. Suggested commit message:"
|
||||
ui_msg [format "%-8s%s: update to %s" "" ${subport} $version]
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
}
|
||||
target_runpkg ${org.macports.bump} portbump_run
|
||||
|
||||
@@ -0,0 +1,373 @@
|
||||
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
|
||||
# Copyright (c) 2019 The MacPorts Project
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of Apple Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package provide portbump_run 1.0
|
||||
package require portutil 1.0
|
||||
package require portchecksum 1.0
|
||||
|
||||
namespace eval portbump {
|
||||
|
||||
# replace_checksums
|
||||
#
|
||||
# Replace old checksum hash values with new ones in a list of lines.
|
||||
# Returns a list of two elements: the modified lines and a list of
|
||||
# line indices where replacements were made.
|
||||
#
|
||||
# Checksum values (hex hashes and integer sizes) are matched as whole
|
||||
# words using \y word-boundary anchors (Tcl ARE syntax), so a size
|
||||
# like 123 cannot accidentally match inside a larger value such as
|
||||
# 12345. All checksum values are alphanumeric ([0-9a-f]+ or [0-9]+)
|
||||
# and contain no regex metacharacters, so they are safe to interpolate
|
||||
# directly into the pattern.
|
||||
#
|
||||
# lines - list of Portfile lines
|
||||
# both_checksums - list of {type old_sum new_sum} triples
|
||||
proc replace_checksums {lines both_checksums} {
|
||||
set checksum_lines [list]
|
||||
foreach {type sum calculated_sum} $both_checksums {
|
||||
if {$sum eq $calculated_sum} {
|
||||
continue
|
||||
}
|
||||
for {set i 0} {$i < [llength $lines]} {incr i} {
|
||||
set line [lindex $lines $i]
|
||||
if {[regsub -all "\\y${sum}\\y" $line $calculated_sum new_line]} {
|
||||
lset lines $i $new_line
|
||||
lappend checksum_lines $i
|
||||
}
|
||||
}
|
||||
}
|
||||
return [list $lines $checksum_lines]
|
||||
}
|
||||
|
||||
# find_revision_line
|
||||
#
|
||||
# Find the line index of the revision that should be reset for the
|
||||
# given subport. Handles Portfiles with multiple revision lines across
|
||||
# subport blocks, conditional branches, or inline subport declarations
|
||||
# (e.g. "subport foo { revision 3 }").
|
||||
#
|
||||
# Strategy:
|
||||
# 1. If the current subport has an inline revision on its subport
|
||||
# declaration line, use that.
|
||||
# 2. Otherwise, use the standalone revision line nearest to the
|
||||
# anchor (typically the first checksum line that was modified).
|
||||
# When bumping the parent port, revision lines inside subport { }
|
||||
# blocks are excluded.
|
||||
#
|
||||
# lines - list of Portfile lines
|
||||
# subport - current subport name
|
||||
# portname - parent port name
|
||||
# anchor - line index to measure proximity from
|
||||
#
|
||||
# Returns: line index, or -1 if no revision line found
|
||||
proc find_revision_line {lines subport portname anchor} {
|
||||
# For a subport, prefer an inline revision on its subport declaration line
|
||||
# (e.g. "subport clang-16 { revision 9 }").
|
||||
if {$subport ne $portname} {
|
||||
set escaped_subport [string map {\\ \\\\ . \\. * \\* + \\+ ? \\? ( \\( ) \\) \{ \\\{ \} \\\} \[ \\\[ \] \\\]} $subport]
|
||||
for {set i 0} {$i < [llength $lines]} {incr i} {
|
||||
if {[regexp "^\\s*subport\\s+\\S*${escaped_subport}\\S*\\s+.*revision\\s+\\d+" [lindex $lines $i]]} {
|
||||
return $i
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# When bumping the parent port, build an exclusion set of lines inside
|
||||
# subport { } blocks so their revision lines are not mistakenly targeted.
|
||||
set in_subport_block [dict create]
|
||||
if {$subport eq $portname} {
|
||||
set brace_depth 0
|
||||
set in_subport 0
|
||||
for {set i 0} {$i < [llength $lines]} {incr i} {
|
||||
set line [lindex $lines $i]
|
||||
if {!$in_subport && [regexp {^\s*subport\s+} $line]} {
|
||||
set in_subport 1
|
||||
set opens [regexp -all {\{} $line]
|
||||
set closes [regexp -all {\}} $line]
|
||||
set brace_depth [expr {$opens - $closes}]
|
||||
dict set in_subport_block $i 1
|
||||
if {$brace_depth <= 0} {
|
||||
set in_subport 0
|
||||
set brace_depth 0
|
||||
}
|
||||
} elseif {$in_subport} {
|
||||
dict set in_subport_block $i 1
|
||||
set opens [regexp -all {\{} $line]
|
||||
set closes [regexp -all {\}} $line]
|
||||
incr brace_depth [expr {$opens - $closes}]
|
||||
if {$brace_depth <= 0} {
|
||||
set in_subport 0
|
||||
set brace_depth 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Find the nearest standalone revision line, skipping any inside subport blocks.
|
||||
set best_line -1
|
||||
set best_dist 2147483647
|
||||
for {set i 0} {$i < [llength $lines]} {incr i} {
|
||||
if {[regexp {^\s*revision\s+\d+} [lindex $lines $i]]} {
|
||||
if {[dict exists $in_subport_block $i]} {
|
||||
continue
|
||||
}
|
||||
set dist [expr {abs($i - $anchor)}]
|
||||
if {$dist < $best_dist} {
|
||||
set best_dist $dist
|
||||
set best_line $i
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $best_line
|
||||
}
|
||||
|
||||
# reset_revision
|
||||
#
|
||||
# Reset the revision value to 0 on the specified line.
|
||||
# Returns the modified list of lines.
|
||||
#
|
||||
# lines - list of Portfile lines
|
||||
# line_idx - index of the line to modify
|
||||
proc reset_revision {lines line_idx} {
|
||||
set old_line [lindex $lines $line_idx]
|
||||
set new_line [regsub {(revision\s+)\d+} $old_line {\10}]
|
||||
if {$old_line ne $new_line} {
|
||||
lset lines $line_idx $new_line
|
||||
}
|
||||
return $lines
|
||||
}
|
||||
|
||||
# bump_start
|
||||
#
|
||||
# Target prerun procedure; simply prints a message about what we're doing.
|
||||
#
|
||||
proc bump_start {args} {
|
||||
global UI_PREFIX subport
|
||||
|
||||
ui_notice "$UI_PREFIX [format [msgcat::mc "Bumping checksums for %s"] ${subport}]"
|
||||
}
|
||||
|
||||
# bump_main
|
||||
#
|
||||
# Target main procedure. Bumps the checksums for distfiles.
|
||||
#
|
||||
proc bump_main {args} {
|
||||
global UI_PREFIX all_dist_files checksums_array portpath ports_bump_patch
|
||||
|
||||
set portfile "${portpath}/Portfile"
|
||||
|
||||
# If no files have been downloaded, there is nothing to bump.
|
||||
if {![info exists all_dist_files]} {
|
||||
return 0
|
||||
}
|
||||
|
||||
package require portchecksum_run
|
||||
|
||||
# So far, no mismatches yet.
|
||||
set mismatch no
|
||||
set wrong_mimetype no
|
||||
|
||||
# Read the declared checksums from the port options.
|
||||
set checksums_str [option checksums]
|
||||
|
||||
# If everything is fine with the syntax, keep on and check the checksum of
|
||||
# the distfiles.
|
||||
if {[portchecksum::parse_checksums $checksums_str] eq "yes"} {
|
||||
global distpath
|
||||
|
||||
set both_checksums [list]
|
||||
foreach distfile $all_dist_files {
|
||||
ui_info "$UI_PREFIX [format [msgcat::mc "Checksumming %s"] $distfile]"
|
||||
|
||||
# Get the full path of the distfile.
|
||||
set fullpath [file join $distpath $distfile]
|
||||
if {![file isfile $fullpath]} {
|
||||
return -code error "$distfile does not exist in $distpath"
|
||||
}
|
||||
|
||||
# Check that there is at least one checksum for the distfile.
|
||||
if {![info exists checksums_array($distfile)] || [llength $checksums_array($distfile)] < 1} {
|
||||
ui_error "[format [msgcat::mc "No checksum set for %s"] $distfile]"
|
||||
set mismatch yes
|
||||
} else {
|
||||
# Retrieve the list of types/values from the array.
|
||||
set portfile_checksums $checksums_array($distfile)
|
||||
|
||||
# Iterate on this list to check the actual values.
|
||||
foreach {type sum} $portfile_checksums {
|
||||
set calculated_sum [portchecksum::calc_$type $fullpath]
|
||||
lappend both_checksums $type $sum $calculated_sum
|
||||
|
||||
if {$sum eq $calculated_sum} {
|
||||
ui_debug "[format [msgcat::mc "Correct (%s) bump for %s"] $type $distfile]"
|
||||
} else {
|
||||
ui_info "[format [msgcat::mc "Portfile bump: %s %s %s"] $distfile $type $sum]"
|
||||
ui_info "[format [msgcat::mc "Distfile bump: %s %s %s"] $distfile $type $calculated_sum]"
|
||||
|
||||
# Raise the failure flag
|
||||
set mismatch yes
|
||||
}
|
||||
}
|
||||
|
||||
if {![regexp {\.html?$} ${distfile}] &&
|
||||
![catch {strsed [exec [findBinary file $::portutil::autoconf::file_path] $fullpath --brief --mime] {s/;.*$//}} mimetype]
|
||||
&& "text/html" eq $mimetype} {
|
||||
# file --mime-type would be preferable to file --mime and strsed, but is only available as of Snow Leopard
|
||||
set wrong_mimetype yes
|
||||
set htmlfile_path ${fullpath}.html
|
||||
file rename -force $fullpath $htmlfile_path
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
# Something went wrong with the syntax.
|
||||
return -code error "[msgcat::mc "Unable to verify file checksums"]"
|
||||
}
|
||||
|
||||
if {![tbool mismatch]} {
|
||||
ui_msg "No changes needed."
|
||||
return 0
|
||||
}
|
||||
|
||||
if {[tbool wrong_mimetype]} {
|
||||
# We got an HTML file, though the distfile name does not suggest that one was
|
||||
# expected. Probably a helpful DNS server sent us to its search results page
|
||||
# instead of admitting that the server we asked for doesn't exist, or a mirror that
|
||||
# no longer has the file served its error page with a 200 response.
|
||||
ui_notice "***"
|
||||
ui_notice "The non-matching file appears to be HTML. See this page for possible reasons"
|
||||
ui_notice "for the bump mismatch:"
|
||||
ui_notice "<https://trac.macports.org/wiki/MisbehavingServers>"
|
||||
ui_notice "***"
|
||||
ui_notice "The file has been moved to: $htmlfile_path"
|
||||
|
||||
return -code error "[msgcat::mc "Unable to verify file checksums"]"
|
||||
} else {
|
||||
global version subport
|
||||
|
||||
ui_msg "We will bump these:"
|
||||
foreach {type sum calculated_sum} $both_checksums {
|
||||
if {$sum eq $calculated_sum} {
|
||||
continue
|
||||
}
|
||||
ui_msg [format "Old %-8s %s" ${type}: $sum]
|
||||
ui_msg [format "New %-8s %s" ${type}: $calculated_sum]
|
||||
}
|
||||
|
||||
# Get the uid of Portfile owner
|
||||
set owneruid [name_to_uid [file attributes ${portfile} -owner]]
|
||||
|
||||
# root -> owner id
|
||||
exec_as_uid $owneruid {
|
||||
# Read the Portfile
|
||||
set fd [open $portfile r]
|
||||
set lines [split [read $fd] \n]
|
||||
close $fd
|
||||
|
||||
# Get Portfile attributes
|
||||
set attributes [file attributes $portfile]
|
||||
|
||||
lassign [replace_checksums $lines $both_checksums] lines checksum_lines
|
||||
foreach cl $checksum_lines {
|
||||
ui_debug "Replaced checksum on line [expr {$cl + 1}]"
|
||||
}
|
||||
|
||||
if {[llength $checksum_lines] > 0} {
|
||||
set rev_line [find_revision_line $lines $subport [option name] [lindex $checksum_lines 0]]
|
||||
if {$rev_line >= 0} {
|
||||
set old_rev [lindex $lines $rev_line]
|
||||
set lines [reset_revision $lines $rev_line]
|
||||
if {[lindex $lines $rev_line] ne $old_rev} {
|
||||
ui_debug "Reset revision to 0 on line [expr {$rev_line + 1}]"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set new_content [join $lines \n]
|
||||
|
||||
if {[tbool ports_bump_patch]} {
|
||||
# Patch mode
|
||||
if {[catch {set tmpfd [file tempfile tmpfile ${portpath}/Portfile.bump]} error]} {
|
||||
ui_debug $::errorInfo
|
||||
ui_error "file tempfile: $error"
|
||||
return -code error "file tempfile failed"
|
||||
}
|
||||
puts -nonewline $tmpfd $new_content
|
||||
close $tmpfd
|
||||
|
||||
set patchfile "${portpath}/Portfile.patch"
|
||||
set patchfd [open $patchfile w]
|
||||
|
||||
# Construct diff command
|
||||
set diffcmd [list]
|
||||
lappend diffcmd $::portutil::autoconf::diff_path -u --label old/Portfile --label new/Portfile
|
||||
lappend diffcmd $portfile $tmpfile >@$patchfd
|
||||
|
||||
# Create and write diff to Portfile.patch
|
||||
if {[catch {exec -ignorestderr -- {*}$diffcmd} error]} {
|
||||
file attributes $patchfile {*}$attributes
|
||||
ui_msg "Portfile.patch successfully created at $patchfile"
|
||||
} else {
|
||||
ui_msg "No changes needed."
|
||||
file delete "$patchfile"
|
||||
close $patchfd
|
||||
}
|
||||
|
||||
file delete "$tmpfile"
|
||||
} else {
|
||||
# Overwrite mode
|
||||
if {[catch {set tmpfd [file tempfile tmpfile ${portpath}/Portfile.bump]} error]} {
|
||||
ui_debug $::errorInfo
|
||||
ui_error "file tempfile: $error"
|
||||
return -code error "file tempfile failed"
|
||||
}
|
||||
puts -nonewline $tmpfd $new_content
|
||||
close $tmpfd
|
||||
|
||||
if {[catch {move -force $tmpfile $portfile} error]} {
|
||||
ui_debug $::errorInfo
|
||||
ui_error "bump: $error"
|
||||
file delete "$tmpfile"
|
||||
return -code error "bump overwrite failed"
|
||||
}
|
||||
|
||||
# Restore Portfile attributes
|
||||
file attributes $portfile {*}$attributes
|
||||
|
||||
ui_msg "Checksums successfully bumped. Suggested commit message:"
|
||||
ui_msg [format "%-8s%s: update to %s" "" ${subport} $version]
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,43 +1,12 @@
|
||||
# et:ts=4
|
||||
# portchecksum.tcl
|
||||
#
|
||||
# Copyright (c) 2002 - 2004 Apple Inc.
|
||||
# Copyright (c) 2004 - 2005 Paul Guyot <pguyot@kallisys.net>
|
||||
# Copyright (c) 2006 - 2012, 2014 - 2016, 2018 The MacPorts Project
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of Apple Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
|
||||
|
||||
package provide portchecksum 1.0
|
||||
package require portutil 1.0
|
||||
|
||||
set org.macports.checksum [target_new org.macports.checksum portchecksum::checksum_main]
|
||||
target_provides ${org.macports.checksum} checksum
|
||||
target_requires ${org.macports.checksum} main fetch
|
||||
target_prerun ${org.macports.checksum} portchecksum::checksum_start
|
||||
target_runpkg ${org.macports.checksum} portchecksum_run
|
||||
|
||||
namespace eval portchecksum {
|
||||
|
||||
@@ -57,346 +26,3 @@ options checksums checksum.skip
|
||||
# Defaults
|
||||
default checksums {}
|
||||
default checksum.skip false
|
||||
|
||||
set_ui_prefix
|
||||
|
||||
# verify_checksum_format
|
||||
#
|
||||
# Given a checksum type as string and the actual checksum:
|
||||
#
|
||||
# - return 1 if the value has the expected format
|
||||
# - return 0 if the value does not look as expected
|
||||
# - return -1 if the checksum type is unrecognized
|
||||
proc portchecksum::verify_checksum_format {type value} {
|
||||
set result 0
|
||||
|
||||
switch [string tolower $type] {
|
||||
sha256 -
|
||||
blake3 {
|
||||
set result [regexp {^[0-9a-f]{64}$} $value]
|
||||
}
|
||||
rmd160 -
|
||||
sha1 {
|
||||
set result [regexp {^[0-9a-f]{40}$} $value]
|
||||
}
|
||||
md5 {
|
||||
set result [regexp {^[0-9a-f]{32}$} $value]
|
||||
}
|
||||
size {
|
||||
set result [regexp {^\d+$} $value]
|
||||
}
|
||||
default {
|
||||
# unrecognized checksum type
|
||||
set result -1
|
||||
}
|
||||
}
|
||||
|
||||
return $result
|
||||
}
|
||||
|
||||
# Using global all_dist_files, parse the checksums and store them into the
|
||||
# global array checksums_array.
|
||||
#
|
||||
# There are two formats:
|
||||
# type value [type value [type value]] for a single file
|
||||
# file1 type value [type value [type value]] [file2 ...] for multiple files.
|
||||
#
|
||||
# Portfile is in format #1 if:
|
||||
# (1) There is only one distfile.
|
||||
# (2) There are an even number of words in checksums (i.e. "md5 cksum sha1 cksum" = 4 words).
|
||||
# (3) There are no more checksums specified than $portchecksum::checksum_types contains.
|
||||
# (4) first word is one of the checksums types.
|
||||
#
|
||||
# return yes if the syntax was correct, no if there was a problem.
|
||||
proc portchecksum::parse_checksums {checksums_str} {
|
||||
global checksums_array all_dist_files
|
||||
variable checksum_types
|
||||
|
||||
# Parse the string of checksums.
|
||||
set nb_checksum [llength $checksums_str]
|
||||
|
||||
if {[llength $all_dist_files] == 1
|
||||
&& [expr {$nb_checksum % 2}] == 0
|
||||
&& [expr {$nb_checksum / 2}] <= [llength $checksum_types]
|
||||
&& [lindex $checksums_str 0] in $checksum_types} {
|
||||
# Convert to format #2
|
||||
set checksums_str [linsert $checksums_str 0 [lindex $all_dist_files 0]]
|
||||
# We increased the size.
|
||||
incr nb_checksum
|
||||
}
|
||||
|
||||
# Create the array with the checksums.
|
||||
array set checksums_array {}
|
||||
|
||||
set result yes
|
||||
|
||||
# Catch out of bounds errors (they're syntax errors).
|
||||
if {[catch {
|
||||
# Parse the string as if it was in format #2.
|
||||
for {set ix_checksum 0} {$ix_checksum < $nb_checksum} {incr ix_checksum} {
|
||||
# first word is the file.
|
||||
set checksum_filename [lindex $checksums_str $ix_checksum]
|
||||
|
||||
# retrieve the list of values we already know for this file.
|
||||
set checksum_values {}
|
||||
if {[info exists checksums_array($checksum_filename)]} {
|
||||
set checksum_values $checksums_array($checksum_filename)
|
||||
}
|
||||
|
||||
# append the new value
|
||||
incr ix_checksum
|
||||
while {1} {
|
||||
set checksum_type [lindex $checksums_str $ix_checksum]
|
||||
if {$checksum_type in $checksum_types} {
|
||||
# append the type and the value.
|
||||
incr ix_checksum
|
||||
set checksum_value [lindex $checksums_str $ix_checksum]
|
||||
incr ix_checksum
|
||||
|
||||
lappend checksum_values $checksum_type
|
||||
lappend checksum_values $checksum_value
|
||||
} else {
|
||||
# this wasn't a type but the next dist file.
|
||||
incr ix_checksum -1
|
||||
break
|
||||
}
|
||||
|
||||
# stop if we exhausted all the items in the list.
|
||||
if {$ix_checksum == $nb_checksum} {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
# set the values in the array.
|
||||
set checksums_array($checksum_filename) $checksum_values
|
||||
}
|
||||
} error]} {
|
||||
# An error occurred.
|
||||
ui_debug $::errorInfo
|
||||
ui_error "Couldn't parse checksum line ($checksums_str) [$error]"
|
||||
|
||||
# Something wrong happened.
|
||||
set result no
|
||||
}
|
||||
|
||||
return $result
|
||||
}
|
||||
|
||||
# calc_md5
|
||||
#
|
||||
# Calculate the md5 checksum for the given file.
|
||||
# Return the checksum.
|
||||
#
|
||||
proc portchecksum::calc_md5 {file} {
|
||||
return [md5 file $file]
|
||||
}
|
||||
|
||||
# calc_sha1
|
||||
#
|
||||
# Calculate the sha1 checksum for the given file.
|
||||
# Return the checksum.
|
||||
#
|
||||
proc portchecksum::calc_sha1 {file} {
|
||||
return [sha1 file $file]
|
||||
}
|
||||
|
||||
# calc_rmd160
|
||||
#
|
||||
# Calculate the rmd160 checksum for the given file.
|
||||
# Return the checksum.
|
||||
#
|
||||
proc portchecksum::calc_rmd160 {file} {
|
||||
return [rmd160 file $file]
|
||||
}
|
||||
|
||||
# calc_sha256
|
||||
#
|
||||
# Calculate the sha256 checksum for the given file.
|
||||
# Return the checksum.
|
||||
#
|
||||
proc portchecksum::calc_sha256 {file} {
|
||||
return [sha256 file $file]
|
||||
}
|
||||
|
||||
# calc_blake3
|
||||
#
|
||||
# Calculate the blake3 checksum for the given file.
|
||||
# Return the checksum.
|
||||
#
|
||||
proc portchecksum::calc_blake3 {file} {
|
||||
return [blake3 file $file]
|
||||
}
|
||||
|
||||
# calc_size
|
||||
#
|
||||
# Get the size of the given file.
|
||||
# Return the size.
|
||||
#
|
||||
proc portchecksum::calc_size {file} {
|
||||
return [file size $file]
|
||||
}
|
||||
|
||||
# checksum_start
|
||||
#
|
||||
# Target prerun procedure; simply prints a message about what we're doing.
|
||||
#
|
||||
proc portchecksum::checksum_start {args} {
|
||||
global UI_PREFIX
|
||||
|
||||
ui_notice "$UI_PREFIX [format [msgcat::mc "Verifying checksums for %s"] [option subport]]"
|
||||
}
|
||||
|
||||
# checksum_main
|
||||
#
|
||||
# Target main procedure. Verifies the checksums of all distfiles.
|
||||
#
|
||||
proc portchecksum::checksum_main {args} {
|
||||
global UI_PREFIX all_dist_files checksums_array checksum.skip distpath
|
||||
|
||||
# If no files have been downloaded, there is nothing to checksum.
|
||||
if {![info exists all_dist_files]} {
|
||||
return 0
|
||||
}
|
||||
|
||||
# Completely bypass checksumming if checksum.skip=yes
|
||||
# This should be considered an extreme measure
|
||||
if {[tbool checksum.skip]} {
|
||||
ui_info "$UI_PREFIX Skipping checksum phase"
|
||||
return 0
|
||||
}
|
||||
|
||||
# so far, everything went fine.
|
||||
set fail no
|
||||
|
||||
# Set the list of checksums as the option checksums.
|
||||
set checksums_str [option checksums]
|
||||
|
||||
# store the calculated checksums to avoid repeated calculations
|
||||
array set calculated_checksums_array {}
|
||||
|
||||
# if everything is fine with the syntax, keep on and check the checksum of
|
||||
# the distfiles.
|
||||
if {[parse_checksums $checksums_str] eq "yes"} {
|
||||
|
||||
foreach distfile $all_dist_files {
|
||||
ui_info "$UI_PREFIX [format [msgcat::mc "Checksumming %s"] $distfile]"
|
||||
|
||||
# get the full path of the distfile.
|
||||
set fullpath [file join $distpath $distfile]
|
||||
if {![file isfile $fullpath]} {
|
||||
return -code error "$distfile does not exist in $distpath"
|
||||
}
|
||||
|
||||
# check that there is at least one checksum for the distfile.
|
||||
if {![info exists checksums_array($distfile)] || [llength $checksums_array($distfile)] < 1} {
|
||||
ui_error "[format [msgcat::mc "No checksum set for %s"] $distfile]"
|
||||
set fail yes
|
||||
} else {
|
||||
# retrieve the list of types/values from the array.
|
||||
set portfile_checksums $checksums_array($distfile)
|
||||
set calculated_checksums [list]
|
||||
|
||||
# iterate on this list to check the actual values.
|
||||
foreach {type sum} $portfile_checksums {
|
||||
set calculated_sum [calc_$type $fullpath]
|
||||
lappend calculated_checksums $type
|
||||
lappend calculated_checksums $calculated_sum
|
||||
|
||||
# Used for regression testing
|
||||
ui_debug "[format [msgcat::mc "Calculated (%s) is %s"] $type $calculated_sum]"
|
||||
|
||||
if {$sum eq $calculated_sum} {
|
||||
ui_debug "[format [msgcat::mc "Correct (%s) checksum for %s"] $type $distfile]"
|
||||
} else {
|
||||
ui_error "[format [msgcat::mc "Checksum (%s) mismatch for %s"] $type $distfile]"
|
||||
ui_info "[format [msgcat::mc "Portfile checksum: %s %s %s"] $distfile $type $sum]"
|
||||
ui_info "[format [msgcat::mc "Distfile checksum: %s %s %s"] $distfile $type $calculated_sum]"
|
||||
|
||||
# Raise the failure flag
|
||||
set fail yes
|
||||
}
|
||||
}
|
||||
|
||||
# Save our calculated checksums in case we need them later
|
||||
set calculated_checksums_array($distfile) $calculated_checksums
|
||||
|
||||
if {[tbool fail] && ![regexp {\.html?$} ${distfile}] &&
|
||||
![catch {strsed [exec [findBinary file $::portutil::autoconf::file_path] $fullpath --brief --mime] {s/;.*$//}} mimetype]
|
||||
&& "text/html" eq $mimetype} {
|
||||
# file --mime-type would be preferable to file --mime and strsed, but is only available as of Snow Leopard
|
||||
set wrong_mimetype yes
|
||||
set htmlfile_path ${fullpath}.html
|
||||
file rename -force $fullpath $htmlfile_path
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
# Something went wrong with the syntax.
|
||||
set fail yes
|
||||
}
|
||||
|
||||
if {[tbool fail]} {
|
||||
|
||||
if {[tbool wrong_mimetype]} {
|
||||
# We got an HTML file, though the distfile name does not suggest that one was
|
||||
# expected. Probably a helpful DNS server sent us to its search results page
|
||||
# instead of admitting that the server we asked for doesn't exist, or a mirror that
|
||||
# no longer has the file served its error page with a 200 response.
|
||||
ui_notice "***"
|
||||
ui_notice "The non-matching file appears to be HTML. See this page for possible reasons"
|
||||
ui_notice "for the checksum mismatch:"
|
||||
ui_notice "<https://trac.macports.org/wiki/MisbehavingServers>"
|
||||
ui_notice "***"
|
||||
ui_notice "The file has been moved to: $htmlfile_path"
|
||||
} else {
|
||||
# Show the desired checksum line for easy cut-paste
|
||||
# based on the previously calculated values, plus our default types
|
||||
set sums [list]
|
||||
variable default_checksum_types
|
||||
|
||||
foreach distfile $all_dist_files {
|
||||
if {[llength $all_dist_files] > 1} {
|
||||
lappend sums $distfile
|
||||
}
|
||||
|
||||
set missing_types $default_checksum_types
|
||||
|
||||
# Append the string for the calculated types and note any of
|
||||
# our default types that were already calculated
|
||||
if {[info exists calculated_checksums_array($distfile)] && [llength $calculated_checksums_array($distfile)]} {
|
||||
set calculated_checksums $calculated_checksums_array($distfile)
|
||||
foreach {type sum} $calculated_checksums {
|
||||
lappend sums [format "%-8s%s" $type $sum]
|
||||
|
||||
set found [lsearch -exact ${missing_types} ${type}]
|
||||
if { ${found} != -1} {
|
||||
lpop missing_types ${found}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Append the string for any of our default types that were
|
||||
# note previously calculated
|
||||
if {[llength $missing_types]} {
|
||||
# get the full path of the distfile.
|
||||
set fullpath [file join $distpath $distfile]
|
||||
if {![file isfile $fullpath]} {
|
||||
return -code error "$distfile does not exist in $distpath"
|
||||
}
|
||||
|
||||
foreach type $missing_types {
|
||||
lappend sums [format "%-8s%s" $type [calc_$type $fullpath]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui_info "The correct checksum line may be:"
|
||||
ui_info [format "%-20s%s" "checksums" [join $sums [format " \\\n%-20s" ""]]]
|
||||
}
|
||||
|
||||
return -code error "[msgcat::mc "Unable to verify file checksums"]"
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -0,0 +1,345 @@
|
||||
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
|
||||
#
|
||||
# Copyright (c) 2002 - 2004 Apple Inc.
|
||||
# Copyright (c) 2004 - 2005 Paul Guyot <pguyot@kallisys.net>
|
||||
# Copyright (c) 2006 - 2012, 2014 - 2016, 2018 The MacPorts Project
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of Apple Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package provide portchecksum_run 1.0
|
||||
package require portutil 1.0
|
||||
package require Pextlib 1.0
|
||||
|
||||
namespace eval portchecksum {
|
||||
|
||||
# Using global all_dist_files, parse the checksums and store them into the
|
||||
# global array checksums_array.
|
||||
#
|
||||
# There are two formats:
|
||||
# type value [type value [type value]] for a single file
|
||||
# file1 type value [type value [type value]] [file2 ...] for multiple files.
|
||||
#
|
||||
# Portfile is in format #1 if:
|
||||
# (1) There is only one distfile.
|
||||
# (2) There are an even number of words in checksums (i.e. "md5 cksum sha1 cksum" = 4 words).
|
||||
# (3) There are no more checksums specified than $portchecksum::checksum_types contains.
|
||||
# (4) first word is one of the checksums types.
|
||||
#
|
||||
# return yes if the syntax was correct, no if there was a problem.
|
||||
proc parse_checksums {checksums_str} {
|
||||
global checksums_array all_dist_files
|
||||
variable checksum_types
|
||||
|
||||
# Parse the string of checksums.
|
||||
set nb_checksum [llength $checksums_str]
|
||||
|
||||
if {[llength $all_dist_files] == 1
|
||||
&& [expr {$nb_checksum % 2}] == 0
|
||||
&& [expr {$nb_checksum / 2}] <= [llength $checksum_types]
|
||||
&& [lindex $checksums_str 0] in $checksum_types} {
|
||||
# Convert to format #2
|
||||
set checksums_str [linsert $checksums_str 0 [lindex $all_dist_files 0]]
|
||||
# We increased the size.
|
||||
incr nb_checksum
|
||||
}
|
||||
|
||||
# Create the array with the checksums.
|
||||
array set checksums_array {}
|
||||
|
||||
set result yes
|
||||
|
||||
# Catch out of bounds errors (they're syntax errors).
|
||||
if {[catch {
|
||||
# Parse the string as if it was in format #2.
|
||||
for {set ix_checksum 0} {$ix_checksum < $nb_checksum} {incr ix_checksum} {
|
||||
# first word is the file.
|
||||
set checksum_filename [lindex $checksums_str $ix_checksum]
|
||||
|
||||
# retrieve the list of values we already know for this file.
|
||||
set checksum_values {}
|
||||
if {[info exists checksums_array($checksum_filename)]} {
|
||||
set checksum_values $checksums_array($checksum_filename)
|
||||
}
|
||||
|
||||
# append the new value
|
||||
incr ix_checksum
|
||||
while {1} {
|
||||
set checksum_type [lindex $checksums_str $ix_checksum]
|
||||
if {$checksum_type in $checksum_types} {
|
||||
# append the type and the value.
|
||||
incr ix_checksum
|
||||
set checksum_value [lindex $checksums_str $ix_checksum]
|
||||
incr ix_checksum
|
||||
|
||||
lappend checksum_values $checksum_type
|
||||
lappend checksum_values $checksum_value
|
||||
} else {
|
||||
# this wasn't a type but the next dist file.
|
||||
incr ix_checksum -1
|
||||
break
|
||||
}
|
||||
|
||||
# stop if we exhausted all the items in the list.
|
||||
if {$ix_checksum == $nb_checksum} {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
# set the values in the array.
|
||||
set checksums_array($checksum_filename) $checksum_values
|
||||
}
|
||||
} error]} {
|
||||
# An error occurred.
|
||||
ui_debug $::errorInfo
|
||||
ui_error "Couldn't parse checksum line ($checksums_str) [$error]"
|
||||
|
||||
# Something wrong happened.
|
||||
set result no
|
||||
}
|
||||
|
||||
return $result
|
||||
}
|
||||
|
||||
# calc_md5
|
||||
#
|
||||
# Calculate the md5 checksum for the given file.
|
||||
# Return the checksum.
|
||||
#
|
||||
proc calc_md5 {file} {
|
||||
return [md5 file $file]
|
||||
}
|
||||
|
||||
# calc_sha1
|
||||
#
|
||||
# Calculate the sha1 checksum for the given file.
|
||||
# Return the checksum.
|
||||
#
|
||||
proc calc_sha1 {file} {
|
||||
return [sha1 file $file]
|
||||
}
|
||||
|
||||
# calc_rmd160
|
||||
#
|
||||
# Calculate the rmd160 checksum for the given file.
|
||||
# Return the checksum.
|
||||
#
|
||||
proc calc_rmd160 {file} {
|
||||
return [rmd160 file $file]
|
||||
}
|
||||
|
||||
# calc_sha256
|
||||
#
|
||||
# Calculate the sha256 checksum for the given file.
|
||||
# Return the checksum.
|
||||
#
|
||||
proc calc_sha256 {file} {
|
||||
return [sha256 file $file]
|
||||
}
|
||||
|
||||
# calc_blake3
|
||||
#
|
||||
# Calculate the blake3 checksum for the given file.
|
||||
# Return the checksum.
|
||||
#
|
||||
proc calc_blake3 {file} {
|
||||
return [blake3 file $file]
|
||||
}
|
||||
|
||||
# calc_size
|
||||
#
|
||||
# Get the size of the given file.
|
||||
# Return the size.
|
||||
#
|
||||
proc calc_size {file} {
|
||||
return [file size $file]
|
||||
}
|
||||
|
||||
# checksum_start
|
||||
#
|
||||
# Target prerun procedure; simply prints a message about what we're doing.
|
||||
#
|
||||
proc checksum_start {args} {
|
||||
global UI_PREFIX
|
||||
|
||||
ui_notice "$UI_PREFIX [format [msgcat::mc "Verifying checksums for %s"] [option subport]]"
|
||||
}
|
||||
|
||||
# checksum_main
|
||||
#
|
||||
# Target main procedure. Verifies the checksums of all distfiles.
|
||||
#
|
||||
proc checksum_main {args} {
|
||||
global UI_PREFIX all_dist_files checksums_array checksum.skip distpath
|
||||
|
||||
# If no files have been downloaded, there is nothing to checksum.
|
||||
if {![info exists all_dist_files]} {
|
||||
return 0
|
||||
}
|
||||
|
||||
# Completely bypass checksumming if checksum.skip=yes
|
||||
# This should be considered an extreme measure
|
||||
if {[tbool checksum.skip]} {
|
||||
ui_info "$UI_PREFIX Skipping checksum phase"
|
||||
return 0
|
||||
}
|
||||
|
||||
# so far, everything went fine.
|
||||
set fail no
|
||||
|
||||
# Set the list of checksums as the option checksums.
|
||||
set checksums_str [option checksums]
|
||||
|
||||
# store the calculated checksums to avoid repeated calculations
|
||||
array set calculated_checksums_array {}
|
||||
|
||||
# if everything is fine with the syntax, keep on and check the checksum of
|
||||
# the distfiles.
|
||||
if {[parse_checksums $checksums_str] eq "yes"} {
|
||||
|
||||
foreach distfile $all_dist_files {
|
||||
ui_info "$UI_PREFIX [format [msgcat::mc "Checksumming %s"] $distfile]"
|
||||
|
||||
# get the full path of the distfile.
|
||||
set fullpath [file join $distpath $distfile]
|
||||
if {![file isfile $fullpath]} {
|
||||
return -code error "$distfile does not exist in $distpath"
|
||||
}
|
||||
|
||||
# check that there is at least one checksum for the distfile.
|
||||
if {![info exists checksums_array($distfile)] || [llength $checksums_array($distfile)] < 1} {
|
||||
ui_error "[format [msgcat::mc "No checksum set for %s"] $distfile]"
|
||||
set fail yes
|
||||
} else {
|
||||
# retrieve the list of types/values from the array.
|
||||
set portfile_checksums $checksums_array($distfile)
|
||||
set calculated_checksums [list]
|
||||
|
||||
# iterate on this list to check the actual values.
|
||||
foreach {type sum} $portfile_checksums {
|
||||
set calculated_sum [calc_$type $fullpath]
|
||||
lappend calculated_checksums $type
|
||||
lappend calculated_checksums $calculated_sum
|
||||
|
||||
# Used for regression testing
|
||||
ui_debug "[format [msgcat::mc "Calculated (%s) is %s"] $type $calculated_sum]"
|
||||
|
||||
if {$sum eq $calculated_sum} {
|
||||
ui_debug "[format [msgcat::mc "Correct (%s) checksum for %s"] $type $distfile]"
|
||||
} else {
|
||||
ui_error "[format [msgcat::mc "Checksum (%s) mismatch for %s"] $type $distfile]"
|
||||
ui_info "[format [msgcat::mc "Portfile checksum: %s %s %s"] $distfile $type $sum]"
|
||||
ui_info "[format [msgcat::mc "Distfile checksum: %s %s %s"] $distfile $type $calculated_sum]"
|
||||
|
||||
# Raise the failure flag
|
||||
set fail yes
|
||||
}
|
||||
}
|
||||
|
||||
# Save our calculated checksums in case we need them later
|
||||
set calculated_checksums_array($distfile) $calculated_checksums
|
||||
|
||||
if {[tbool fail] && ![regexp {\.html?$} ${distfile}] &&
|
||||
![catch {strsed [exec [findBinary file $::portutil::autoconf::file_path] $fullpath --brief --mime] {s/;.*$//}} mimetype]
|
||||
&& "text/html" eq $mimetype} {
|
||||
# file --mime-type would be preferable to file --mime and strsed, but is only available as of Snow Leopard
|
||||
set wrong_mimetype yes
|
||||
set htmlfile_path ${fullpath}.html
|
||||
file rename -force $fullpath $htmlfile_path
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
# Something went wrong with the syntax.
|
||||
set fail yes
|
||||
}
|
||||
|
||||
if {[tbool fail]} {
|
||||
|
||||
if {[tbool wrong_mimetype]} {
|
||||
# We got an HTML file, though the distfile name does not suggest that one was
|
||||
# expected. Probably a helpful DNS server sent us to its search results page
|
||||
# instead of admitting that the server we asked for doesn't exist, or a mirror that
|
||||
# no longer has the file served its error page with a 200 response.
|
||||
ui_notice "***"
|
||||
ui_notice "The non-matching file appears to be HTML. See this page for possible reasons"
|
||||
ui_notice "for the checksum mismatch:"
|
||||
ui_notice "<https://trac.macports.org/wiki/MisbehavingServers>"
|
||||
ui_notice "***"
|
||||
ui_notice "The file has been moved to: $htmlfile_path"
|
||||
} else {
|
||||
# Show the desired checksum line for easy cut-paste
|
||||
# based on the previously calculated values, plus our default types
|
||||
set sums [list]
|
||||
variable default_checksum_types
|
||||
|
||||
foreach distfile $all_dist_files {
|
||||
if {[llength $all_dist_files] > 1} {
|
||||
lappend sums $distfile
|
||||
}
|
||||
|
||||
set missing_types $default_checksum_types
|
||||
|
||||
# Append the string for the calculated types and note any of
|
||||
# our default types that were already calculated
|
||||
if {[info exists calculated_checksums_array($distfile)] && [llength $calculated_checksums_array($distfile)]} {
|
||||
set calculated_checksums $calculated_checksums_array($distfile)
|
||||
foreach {type sum} $calculated_checksums {
|
||||
lappend sums [format "%-8s%s" $type $sum]
|
||||
|
||||
set found [lsearch -exact ${missing_types} ${type}]
|
||||
if { ${found} != -1} {
|
||||
lpop missing_types ${found}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Append the string for any of our default types that were
|
||||
# note previously calculated
|
||||
if {[llength $missing_types]} {
|
||||
# get the full path of the distfile.
|
||||
set fullpath [file join $distpath $distfile]
|
||||
if {![file isfile $fullpath]} {
|
||||
return -code error "$distfile does not exist in $distpath"
|
||||
}
|
||||
|
||||
foreach type $missing_types {
|
||||
lappend sums [format "%-8s%s" $type [calc_$type $fullpath]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui_info "The correct checksum line may be:"
|
||||
ui_info [format "%-20s%s" "checksums" [join $sums [format " \\\n%-20s" ""]]]
|
||||
}
|
||||
|
||||
return -code error "[msgcat::mc "Unable to verify file checksums"]"
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
}
|
||||
+1
-287
@@ -1,40 +1,8 @@
|
||||
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
|
||||
#
|
||||
# Copyright (c) 2005-2007, 2009-2011, 2013 The MacPorts Project
|
||||
# Copyright (c) 2004 Robert Shaw <rshaw@opendarwin.org>
|
||||
# Copyright (c) 2002 - 2003 Apple Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of Apple Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
# the 'clean' target is provided by this package
|
||||
|
||||
package provide portclean 1.0
|
||||
package require portutil 1.0
|
||||
package require Pextlib 1.0
|
||||
|
||||
set org.macports.clean [target_new org.macports.clean portclean::clean_main]
|
||||
target_runtype ${org.macports.clean} always
|
||||
@@ -42,258 +10,4 @@ target_state ${org.macports.clean} no
|
||||
target_provides ${org.macports.clean} clean
|
||||
target_requires ${org.macports.clean} main
|
||||
target_prerun ${org.macports.clean} portclean::clean_start
|
||||
|
||||
namespace eval portclean {
|
||||
}
|
||||
|
||||
set_ui_prefix
|
||||
|
||||
proc portclean::clean_start {args} {
|
||||
global UI_PREFIX
|
||||
|
||||
ui_notice "$UI_PREFIX [format [msgcat::mc "Cleaning %s"] [option subport]]"
|
||||
|
||||
if {[getuid] == 0 && [geteuid] != 0} {
|
||||
elevateToRoot "clean"
|
||||
}
|
||||
}
|
||||
|
||||
proc portclean::clean_main {args} {
|
||||
global UI_PREFIX ports_clean_dist ports_clean_work ports_clean_logs \
|
||||
ports_clean_archive ports_clean_all keeplogs
|
||||
|
||||
if {[info exists ports_clean_all] && $ports_clean_all eq "yes" || \
|
||||
[info exists ports_clean_dist] && $ports_clean_dist eq "yes"} {
|
||||
ui_info "$UI_PREFIX [format [msgcat::mc "Removing distfiles for %s"] [option subport]]"
|
||||
clean_dist
|
||||
}
|
||||
if {[info exists ports_clean_all] && $ports_clean_all eq "yes" || \
|
||||
[info exists ports_clean_archive] && $ports_clean_archive eq "yes"} {
|
||||
ui_info "$UI_PREFIX [format [msgcat::mc "Removing temporary archives for %s"] [option subport]]"
|
||||
clean_archive
|
||||
}
|
||||
if {[info exists ports_clean_all] && $ports_clean_all eq "yes" || \
|
||||
[info exists ports_clean_work] && $ports_clean_work eq "yes" || \
|
||||
[info exists ports_clean_archive] && $ports_clean_archive eq "yes" || \
|
||||
[info exists ports_clean_dist] && $ports_clean_dist eq "yes" || \
|
||||
!([info exists ports_clean_logs] && $ports_clean_logs eq "yes")} {
|
||||
ui_info "$UI_PREFIX [format [msgcat::mc "Removing work directory for %s"] [option subport]]"
|
||||
clean_work
|
||||
}
|
||||
if {([info exists ports_clean_logs] && $ports_clean_logs eq "yes") || ($keeplogs eq "no")} {
|
||||
clean_logs
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
#
|
||||
# Remove the directory where the distfiles reside.
|
||||
# This is crude, but works.
|
||||
#
|
||||
proc portclean::clean_dist {args} {
|
||||
global name ports_force distpath dist_subdir distfiles patchfiles portdbpath
|
||||
|
||||
# remove known distfiles for sure (if they exist)
|
||||
set count 0
|
||||
foreach file $distfiles {
|
||||
set distfile [getdistname $file]
|
||||
ui_debug "Looking for $distfile"
|
||||
set distfile [file join $distpath $distfile]
|
||||
if {[file isfile $distfile]} {
|
||||
ui_debug "Removing file: $distfile"
|
||||
if {[catch {delete $distfile} result]} {
|
||||
ui_debug "$::errorInfo"
|
||||
ui_error "$result"
|
||||
}
|
||||
incr count
|
||||
}
|
||||
}
|
||||
if {$count > 0} {
|
||||
ui_debug "$count distfile(s) removed."
|
||||
} else {
|
||||
ui_debug "No distfiles found to remove at $distpath"
|
||||
}
|
||||
|
||||
set count 0
|
||||
if {![info exists patchfiles]} {
|
||||
set patchfiles [list]
|
||||
}
|
||||
foreach file $patchfiles {
|
||||
set patchfile [getdistname $file]
|
||||
ui_debug "Looking for $patchfile"
|
||||
set patchfile [file join $distpath $patchfile]
|
||||
if {[file isfile $patchfile]} {
|
||||
ui_debug "Removing file: $patchfile"
|
||||
if {[catch {delete $patchfile} result]} {
|
||||
ui_debug "$::errorInfo"
|
||||
ui_error "$result"
|
||||
}
|
||||
incr count
|
||||
}
|
||||
}
|
||||
if {$count > 0} {
|
||||
ui_debug "$count patchfile(s) removed."
|
||||
} else {
|
||||
ui_debug "No patchfiles found to remove at $distpath"
|
||||
}
|
||||
|
||||
# next remove dist_subdir if only needed for this port,
|
||||
# or if user forces us to
|
||||
set dirlist [list]
|
||||
if {$dist_subdir ne $name} {
|
||||
if {!([info exists ports_force] && $ports_force eq "yes")
|
||||
&& [file isdirectory $distpath]
|
||||
&& ![dirempty $distpath]} {
|
||||
ui_warn [format [msgcat::mc "Distfiles directory '%s' may contain distfiles needed for other ports, use the -f flag to force removal" ] $distpath]
|
||||
} else {
|
||||
lappend dirlist $dist_subdir
|
||||
lappend dirlist $name
|
||||
}
|
||||
} else {
|
||||
lappend dirlist $name
|
||||
}
|
||||
# loop through directories
|
||||
set count 0
|
||||
foreach dir $dirlist {
|
||||
set distdir [file join ${portdbpath} distfiles $dir]
|
||||
if {[file isdirectory $distdir]} {
|
||||
ui_debug "Removing directory: ${distdir}"
|
||||
if {[catch {delete $distdir} result]} {
|
||||
ui_debug "$::errorInfo"
|
||||
ui_error "$result"
|
||||
}
|
||||
incr count
|
||||
}
|
||||
}
|
||||
if {$count > 0} {
|
||||
ui_debug "$count distfile directory(s) removed."
|
||||
} else {
|
||||
ui_debug "No distfile directory found to remove."
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
proc portclean::clean_work {args} {
|
||||
global portbuildpath subbuildpath worksymlink subport
|
||||
|
||||
if {[file isdirectory $subbuildpath]} {
|
||||
ui_debug "Removing directory: ${subbuildpath}"
|
||||
macports_try -pass_signal {
|
||||
delete $subbuildpath
|
||||
} on error {eMessage} {
|
||||
ui_debug "$::errorInfo"
|
||||
ui_error "$eMessage"
|
||||
}
|
||||
} else {
|
||||
ui_debug "No work directory found to remove at ${subbuildpath}"
|
||||
}
|
||||
|
||||
set old_buildpath [portutil::get_oldbuildpath]
|
||||
set old_subbbuildpath [file join $old_buildpath $subport]
|
||||
if {[catch {set old_subbbuildpath_norm [realpath $old_subbbuildpath]}]} {
|
||||
set old_subbbuildpath_norm [file normalize $old_subbbuildpath]
|
||||
}
|
||||
if {$old_subbbuildpath_norm ne $old_subbbuildpath && [file isdirectory $old_subbbuildpath_norm]} {
|
||||
ui_debug "Removing directory: ${old_subbbuildpath_norm}"
|
||||
macports_try -pass_signal {
|
||||
delete $old_subbbuildpath_norm
|
||||
} on error {eMessage} {
|
||||
ui_debug "$::errorInfo"
|
||||
ui_error "$eMessage"
|
||||
}
|
||||
}
|
||||
|
||||
if {![catch {file type $old_subbbuildpath}]} {
|
||||
ui_debug "Removing symlink: ${old_subbbuildpath}"
|
||||
macports_try -pass_signal {
|
||||
delete $old_subbbuildpath
|
||||
} on error {eMessage} {
|
||||
ui_debug "$::errorInfo"
|
||||
ui_error "$eMessage"
|
||||
}
|
||||
}
|
||||
# silently fail if non-empty (other subports might be using old_buildpath)
|
||||
catch {file delete $old_buildpath}
|
||||
|
||||
# Clean symlink, if necessary
|
||||
if {![catch {file type $worksymlink} result] && $result eq "link"} {
|
||||
ui_debug "Removing symlink: $worksymlink"
|
||||
delete $worksymlink
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
proc portclean::clean_logs {args} {
|
||||
global portpath subport
|
||||
set logpath [getportlogpath $portpath]
|
||||
set subdir [file join $logpath $subport]
|
||||
if {[file isdirectory $subdir]} {
|
||||
ui_debug "Removing directory: ${subdir}"
|
||||
if {[catch {delete $subdir} result]} {
|
||||
ui_debug "$::errorInfo"
|
||||
ui_error "$result"
|
||||
}
|
||||
catch {file delete $logpath}
|
||||
} else {
|
||||
ui_debug "No log directory found to remove at ${logpath}"
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
proc portclean::clean_archive {args} {
|
||||
global subport ports_version_glob portdbpath
|
||||
|
||||
# Define archive destination directory, target filename, regex for archive name
|
||||
set archivepath [file join $portdbpath incoming]
|
||||
|
||||
if {[info exists ports_version_glob]} {
|
||||
# Match all possible archive variants that match the version
|
||||
# glob specified by the user.
|
||||
set fileglob "$subport-${ports_version_glob}*.*.*.*"
|
||||
} else {
|
||||
# Match all possible archives for this port.
|
||||
set fileglob "$subport-*_*.*.*.*"
|
||||
}
|
||||
|
||||
# Remove the archive files
|
||||
set count 0
|
||||
foreach dir [list $archivepath ${archivepath}/verified] {
|
||||
set archivelist [glob -nocomplain -directory $dir $fileglob]
|
||||
foreach path $archivelist {
|
||||
# Make sure file is truly an archive file for this port, and not
|
||||
# an accidental match with some other file that might exist. Also
|
||||
# delete anything ending in .TMP since those are incomplete and
|
||||
# thus can't be checked and aren't useful anyway.
|
||||
set archivetype [string range [file extension $path] 1 end]
|
||||
if {[file isfile $path] && ($archivetype eq "TMP"
|
||||
|| [dict get [extract_archive_metadata $path $archivetype portname] portname] eq $subport)} {
|
||||
ui_debug "Removing archive: $path"
|
||||
if {[catch {delete $path} result]} {
|
||||
ui_debug "$::errorInfo"
|
||||
ui_error "$result"
|
||||
}
|
||||
if {$archivetype eq "TMP"} {
|
||||
set path [file rootname $path]
|
||||
}
|
||||
foreach sigtype {rmd160 sig} {
|
||||
if {[file isfile ${path}.${sigtype}]} {
|
||||
ui_debug "Removing archive signature: ${path}.${sigtype}"
|
||||
if {[catch {delete ${path}.${sigtype}} result]} {
|
||||
ui_debug "$::errorInfo"
|
||||
ui_error "$result"
|
||||
}
|
||||
}
|
||||
}
|
||||
incr count
|
||||
}
|
||||
}
|
||||
}
|
||||
if {$count > 0} {
|
||||
ui_debug "$count archive(s) removed."
|
||||
} else {
|
||||
ui_debug "No archives found to remove at $archivepath"
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
target_runpkg ${org.macports.clean} portclean_run
|
||||
|
||||
@@ -0,0 +1,288 @@
|
||||
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
|
||||
#
|
||||
# Copyright (c) 2005-2007, 2009-2011, 2013 The MacPorts Project
|
||||
# Copyright (c) 2004 Robert Shaw <rshaw@opendarwin.org>
|
||||
# Copyright (c) 2002 - 2003 Apple Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of Apple Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package provide portclean_run 1.0
|
||||
package require portutil 1.0
|
||||
package require Pextlib 1.0
|
||||
|
||||
namespace eval portclean {
|
||||
|
||||
proc clean_start {args} {
|
||||
global UI_PREFIX
|
||||
|
||||
ui_notice "$UI_PREFIX [format [msgcat::mc "Cleaning %s"] [option subport]]"
|
||||
|
||||
if {[getuid] == 0 && [geteuid] != 0} {
|
||||
elevateToRoot "clean"
|
||||
}
|
||||
}
|
||||
|
||||
proc clean_main {args} {
|
||||
global UI_PREFIX ports_clean_dist ports_clean_work ports_clean_logs \
|
||||
ports_clean_archive ports_clean_all keeplogs
|
||||
|
||||
if {[info exists ports_clean_all] && $ports_clean_all eq "yes" || \
|
||||
[info exists ports_clean_dist] && $ports_clean_dist eq "yes"} {
|
||||
ui_info "$UI_PREFIX [format [msgcat::mc "Removing distfiles for %s"] [option subport]]"
|
||||
clean_dist
|
||||
}
|
||||
if {[info exists ports_clean_all] && $ports_clean_all eq "yes" || \
|
||||
[info exists ports_clean_archive] && $ports_clean_archive eq "yes"} {
|
||||
ui_info "$UI_PREFIX [format [msgcat::mc "Removing temporary archives for %s"] [option subport]]"
|
||||
clean_archive
|
||||
}
|
||||
if {[info exists ports_clean_all] && $ports_clean_all eq "yes" || \
|
||||
[info exists ports_clean_work] && $ports_clean_work eq "yes" || \
|
||||
[info exists ports_clean_archive] && $ports_clean_archive eq "yes" || \
|
||||
[info exists ports_clean_dist] && $ports_clean_dist eq "yes" || \
|
||||
!([info exists ports_clean_logs] && $ports_clean_logs eq "yes")} {
|
||||
ui_info "$UI_PREFIX [format [msgcat::mc "Removing work directory for %s"] [option subport]]"
|
||||
clean_work
|
||||
}
|
||||
if {([info exists ports_clean_logs] && $ports_clean_logs eq "yes") || ($keeplogs eq "no")} {
|
||||
clean_logs
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
#
|
||||
# Remove the directory where the distfiles reside.
|
||||
# This is crude, but works.
|
||||
#
|
||||
proc clean_dist {args} {
|
||||
global name ports_force distpath dist_subdir distfiles patchfiles portdbpath
|
||||
|
||||
# remove known distfiles for sure (if they exist)
|
||||
set count 0
|
||||
foreach file $distfiles {
|
||||
set distfile [getdistname $file]
|
||||
ui_debug "Looking for $distfile"
|
||||
set distfile [file join $distpath $distfile]
|
||||
if {[file isfile $distfile]} {
|
||||
ui_debug "Removing file: $distfile"
|
||||
if {[catch {delete $distfile} result]} {
|
||||
ui_debug "$::errorInfo"
|
||||
ui_error "$result"
|
||||
}
|
||||
incr count
|
||||
}
|
||||
}
|
||||
if {$count > 0} {
|
||||
ui_debug "$count distfile(s) removed."
|
||||
} else {
|
||||
ui_debug "No distfiles found to remove at $distpath"
|
||||
}
|
||||
|
||||
set count 0
|
||||
if {![info exists patchfiles]} {
|
||||
set patchfiles [list]
|
||||
}
|
||||
foreach file $patchfiles {
|
||||
set patchfile [getdistname $file]
|
||||
ui_debug "Looking for $patchfile"
|
||||
set patchfile [file join $distpath $patchfile]
|
||||
if {[file isfile $patchfile]} {
|
||||
ui_debug "Removing file: $patchfile"
|
||||
if {[catch {delete $patchfile} result]} {
|
||||
ui_debug "$::errorInfo"
|
||||
ui_error "$result"
|
||||
}
|
||||
incr count
|
||||
}
|
||||
}
|
||||
if {$count > 0} {
|
||||
ui_debug "$count patchfile(s) removed."
|
||||
} else {
|
||||
ui_debug "No patchfiles found to remove at $distpath"
|
||||
}
|
||||
|
||||
# next remove dist_subdir if only needed for this port,
|
||||
# or if user forces us to
|
||||
set dirlist [list]
|
||||
if {$dist_subdir ne $name} {
|
||||
if {!([info exists ports_force] && $ports_force eq "yes")
|
||||
&& [file isdirectory $distpath]
|
||||
&& ![dirempty $distpath]} {
|
||||
ui_warn [format [msgcat::mc "Distfiles directory '%s' may contain distfiles needed for other ports, use the -f flag to force removal" ] $distpath]
|
||||
} else {
|
||||
lappend dirlist $dist_subdir
|
||||
lappend dirlist $name
|
||||
}
|
||||
} else {
|
||||
lappend dirlist $name
|
||||
}
|
||||
# loop through directories
|
||||
set count 0
|
||||
foreach dir $dirlist {
|
||||
set distdir [file join ${portdbpath} distfiles $dir]
|
||||
if {[file isdirectory $distdir]} {
|
||||
ui_debug "Removing directory: ${distdir}"
|
||||
if {[catch {delete $distdir} result]} {
|
||||
ui_debug "$::errorInfo"
|
||||
ui_error "$result"
|
||||
}
|
||||
incr count
|
||||
}
|
||||
}
|
||||
if {$count > 0} {
|
||||
ui_debug "$count distfile directory(s) removed."
|
||||
} else {
|
||||
ui_debug "No distfile directory found to remove."
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
proc clean_work {args} {
|
||||
global portbuildpath subbuildpath worksymlink subport
|
||||
|
||||
if {[file isdirectory $subbuildpath]} {
|
||||
ui_debug "Removing directory: ${subbuildpath}"
|
||||
macports_try -pass_signal {
|
||||
delete $subbuildpath
|
||||
} on error {eMessage} {
|
||||
ui_debug "$::errorInfo"
|
||||
ui_error "$eMessage"
|
||||
}
|
||||
} else {
|
||||
ui_debug "No work directory found to remove at ${subbuildpath}"
|
||||
}
|
||||
|
||||
set old_buildpath [portutil::get_oldbuildpath]
|
||||
set old_subbbuildpath [file join $old_buildpath $subport]
|
||||
if {[catch {set old_subbbuildpath_norm [realpath $old_subbbuildpath]}]} {
|
||||
set old_subbbuildpath_norm [file normalize $old_subbbuildpath]
|
||||
}
|
||||
if {$old_subbbuildpath_norm ne $old_subbbuildpath && [file isdirectory $old_subbbuildpath_norm]} {
|
||||
ui_debug "Removing directory: ${old_subbbuildpath_norm}"
|
||||
macports_try -pass_signal {
|
||||
delete $old_subbbuildpath_norm
|
||||
} on error {eMessage} {
|
||||
ui_debug "$::errorInfo"
|
||||
ui_error "$eMessage"
|
||||
}
|
||||
}
|
||||
|
||||
if {![catch {file type $old_subbbuildpath}]} {
|
||||
ui_debug "Removing symlink: ${old_subbbuildpath}"
|
||||
macports_try -pass_signal {
|
||||
delete $old_subbbuildpath
|
||||
} on error {eMessage} {
|
||||
ui_debug "$::errorInfo"
|
||||
ui_error "$eMessage"
|
||||
}
|
||||
}
|
||||
# silently fail if non-empty (other subports might be using old_buildpath)
|
||||
catch {file delete $old_buildpath}
|
||||
|
||||
# Clean symlink, if necessary
|
||||
if {![catch {file type $worksymlink} result] && $result eq "link"} {
|
||||
ui_debug "Removing symlink: $worksymlink"
|
||||
delete $worksymlink
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
proc clean_logs {args} {
|
||||
global portpath subport
|
||||
set logpath [getportlogpath $portpath]
|
||||
set subdir [file join $logpath $subport]
|
||||
if {[file isdirectory $subdir]} {
|
||||
ui_debug "Removing directory: ${subdir}"
|
||||
if {[catch {delete $subdir} result]} {
|
||||
ui_debug "$::errorInfo"
|
||||
ui_error "$result"
|
||||
}
|
||||
catch {file delete $logpath}
|
||||
} else {
|
||||
ui_debug "No log directory found to remove at ${logpath}"
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
proc clean_archive {args} {
|
||||
global subport ports_version_glob portdbpath
|
||||
|
||||
# Define archive destination directory, target filename, regex for archive name
|
||||
set archivepath [file join $portdbpath incoming]
|
||||
|
||||
if {[info exists ports_version_glob]} {
|
||||
# Match all possible archive variants that match the version
|
||||
# glob specified by the user.
|
||||
set fileglob "$subport-${ports_version_glob}*.*.*.*"
|
||||
} else {
|
||||
# Match all possible archives for this port.
|
||||
set fileglob "$subport-*_*.*.*.*"
|
||||
}
|
||||
|
||||
# Remove the archive files
|
||||
set count 0
|
||||
foreach dir [list $archivepath ${archivepath}/verified] {
|
||||
set archivelist [glob -nocomplain -directory $dir $fileglob]
|
||||
foreach path $archivelist {
|
||||
# Make sure file is truly an archive file for this port, and not
|
||||
# an accidental match with some other file that might exist. Also
|
||||
# delete anything ending in .TMP since those are incomplete and
|
||||
# thus can't be checked and aren't useful anyway.
|
||||
set archivetype [string range [file extension $path] 1 end]
|
||||
if {[file isfile $path] && ($archivetype eq "TMP"
|
||||
|| [dict get [extract_archive_metadata $path $archivetype portname] portname] eq $subport)} {
|
||||
ui_debug "Removing archive: $path"
|
||||
if {[catch {delete $path} result]} {
|
||||
ui_debug "$::errorInfo"
|
||||
ui_error "$result"
|
||||
}
|
||||
if {$archivetype eq "TMP"} {
|
||||
set path [file rootname $path]
|
||||
}
|
||||
foreach sigtype {rmd160 sig} {
|
||||
if {[file isfile ${path}.${sigtype}]} {
|
||||
ui_debug "Removing archive signature: ${path}.${sigtype}"
|
||||
if {[catch {delete ${path}.${sigtype}} result]} {
|
||||
ui_debug "$::errorInfo"
|
||||
ui_error "$result"
|
||||
}
|
||||
}
|
||||
}
|
||||
incr count
|
||||
}
|
||||
}
|
||||
}
|
||||
if {$count > 0} {
|
||||
ui_debug "$count archive(s) removed."
|
||||
} else {
|
||||
ui_debug "No archives found to remove at $archivepath"
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
}
|
||||
@@ -31,14 +31,13 @@
|
||||
#
|
||||
|
||||
package provide portconfigure 1.0
|
||||
package require portutil 1.0
|
||||
package require portprogress 1.0
|
||||
|
||||
set org.macports.configure [target_new org.macports.configure portconfigure::configure_main]
|
||||
target_provides ${org.macports.configure} configure
|
||||
target_requires ${org.macports.configure} main fetch checksum extract patch
|
||||
target_prerun ${org.macports.configure} portconfigure::configure_start
|
||||
target_postrun ${org.macports.configure} portconfigure::configure_finish
|
||||
target_runpkg ${org.macports.configure} portconfigure_run
|
||||
|
||||
namespace eval portconfigure {
|
||||
# configure_get_default_compiler is fairly expensive, so cache the result
|
||||
@@ -359,79 +358,6 @@ default compiler.openmp_version {}
|
||||
default compiler.mpi {}
|
||||
default compiler.thread_local_storage no
|
||||
|
||||
set_ui_prefix
|
||||
|
||||
proc portconfigure::configure_start {args} {
|
||||
global UI_PREFIX subport configure.compiler compiler.fallback configure.ccache
|
||||
|
||||
ui_notice "$UI_PREFIX [format [msgcat::mc "Configuring %s"] $subport]"
|
||||
|
||||
set compiler ${configure.compiler}
|
||||
set valid_compilers {
|
||||
{^apple-gcc-(4\.[02])$} {MacPorts Apple GCC %s}
|
||||
{^cc$} {System cc}
|
||||
{^clang$} {Xcode Clang}
|
||||
{^gcc$} {System GCC}
|
||||
{^gcc-(3\.3|4\.[02])$} {Xcode GCC %s}
|
||||
{^llvm-gcc-4\.2$} {Xcode LLVM-GCC 4.2}
|
||||
{^macports-clang$} {MacPorts Clang (port select)}
|
||||
{^macports-clang-(\d+(?:\.\d+)?)$} {MacPorts Clang %s}
|
||||
{^macports-gcc$} {MacPorts GCC (port select)}
|
||||
{^macports-gcc-(\d+(?:\.\d+)?)$} {MacPorts GCC %s}
|
||||
{^macports-llvm-gcc-4\.2$} {MacPorts LLVM-GCC 4.2}
|
||||
{^macports-g95$} {MacPorts G95}
|
||||
{^macports-mpich-default$} {MacPorts MPICH Wrapper for MacPorts' Default C/C++ Compiler}
|
||||
{^macports-openmpi-default$} {MacPorts Open MPI Wrapper for MacPorts' Default C/C++ Compiler}
|
||||
{^macports-mpich-clang$} {MacPorts MPICH Wrapper for Xcode Clang}
|
||||
{^macports-openmpi-clang$} {MacPorts Open MPI Wrapper for Xcode Clang}
|
||||
{^macports-mpich-clang-(\d+(?:\.\d+)?)$} {MacPorts MPICH Wrapper for Clang %s}
|
||||
{^macports-openmpi-clang-(\d+(?:\.\d+)?)$} {MacPorts Open MPI Wrapper for Clang %s}
|
||||
{^macports-mpich-gcc-(\d+(?:\.\d+)?)$} {MacPorts MPICH Wrapper for GCC %s}
|
||||
{^macports-openmpi-gcc-(\d+(?:\.\d+)?)$} {MacPorts Open MPI Wrapper for GCC %s}
|
||||
{^macports-(clang|gcc)-devel$} {MacPorts %s Development}
|
||||
}
|
||||
foreach {re fmt} $valid_compilers {
|
||||
if {[set matches [regexp -inline $re $compiler]] ne ""} {
|
||||
set compiler_name [format $fmt {*}[lrange $matches 1 end]]
|
||||
break
|
||||
}
|
||||
}
|
||||
if {![info exists compiler_name]} {
|
||||
return -code error "Invalid value for configure.compiler: $compiler"
|
||||
}
|
||||
ui_debug "Preferred compilers: ${compiler.fallback}"
|
||||
ui_debug "Using compiler '$compiler_name'"
|
||||
variable no_default_compiler_allowed
|
||||
if {$no_default_compiler_allowed} {
|
||||
ui_warn_once no_default_compiler_allowed "All compilers are either blacklisted or unavailable; defaulting to first fallback option"
|
||||
}
|
||||
|
||||
# Additional ccache directory setup
|
||||
if {${configure.ccache}} {
|
||||
global ccache_dir ccache_size macportsuser
|
||||
# Create ccache directory with correct permissions with root privileges
|
||||
elevateToRoot "configure ccache"
|
||||
if {[catch {
|
||||
file mkdir ${ccache_dir}
|
||||
file attributes ${ccache_dir} -owner ${macportsuser} -permissions 0755
|
||||
} result]} {
|
||||
ui_warn "ccache_dir ${ccache_dir} could not be created; disabling ccache: $result"
|
||||
set configure.ccache no
|
||||
}
|
||||
dropPrivileges
|
||||
|
||||
# Initialize ccache directory with the given maximum size
|
||||
if {${configure.ccache}} {
|
||||
if {[catch {
|
||||
exec ccache -M ${ccache_size} >/dev/null
|
||||
} result]} {
|
||||
ui_warn "ccache_dir ${ccache_dir} could not be initialized; disabling ccache: $result"
|
||||
set configure.ccache no
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# internal function to choose the default configure.build_arch and
|
||||
# configure.universal_archs based on supported_archs and build_arch or
|
||||
# universal_archs, plus the SDK being used
|
||||
@@ -1780,247 +1706,16 @@ proc portconfigure::add_compiler_port_dependencies {compiler} {
|
||||
}
|
||||
}
|
||||
|
||||
proc portconfigure::configure_main {args} {
|
||||
global worksrcpath use_configure use_autoreconf use_autoconf use_automake use_xmkmf \
|
||||
configure.pipe configure.libs configure.classpath configure.universal_args \
|
||||
configure.perl configure.python configure.ruby configure.install configure.awk configure.bison \
|
||||
configure.pkg_config configure.pkg_config_path \
|
||||
configure.ccache configure.distcc configure.javac configure.sdkroot \
|
||||
configure.march configure.mtune os.platform os.major \
|
||||
compiler.limit_flags
|
||||
foreach tool {cc cxx objc objcxx f77 f90 fc ld} {
|
||||
global configure.${tool} configure.${tool}_archflags
|
||||
}
|
||||
foreach flags {cflags cppflags cxxflags objcflags objcxxflags ldflags fflags f90flags fcflags} {
|
||||
global configure.${flags} configure.universal_${flags}
|
||||
}
|
||||
|
||||
set callback [list "-callback" portprogress::target_progress_callback]
|
||||
|
||||
if {[tbool use_autoreconf]} {
|
||||
if {[catch {command_exec {*}${callback} autoreconf} result]} {
|
||||
return -code error "[format [msgcat::mc "%s failure: %s"] autoreconf $result]"
|
||||
}
|
||||
}
|
||||
|
||||
if {[tbool use_automake]} {
|
||||
if {[catch {command_exec {*}${callback} automake} result]} {
|
||||
return -code error "[format [msgcat::mc "%s failure: %s"] automake $result]"
|
||||
}
|
||||
}
|
||||
|
||||
if {[tbool use_autoconf]} {
|
||||
if {[catch {command_exec {*}${callback} autoconf} result]} {
|
||||
return -code error "[format [msgcat::mc "%s failure: %s"] autoconf $result]"
|
||||
}
|
||||
}
|
||||
|
||||
if {[tbool use_xmkmf]} {
|
||||
parse_environment xmkmf
|
||||
if {[catch {command_exec {*}${callback} xmkmf} result]} {
|
||||
return -code error "[format [msgcat::mc "%s failure: %s"] xmkmf $result]"
|
||||
}
|
||||
|
||||
parse_environment xmkmf
|
||||
if {[catch {command_exec {*}${callback} -varprefix xmkmf "cd ${worksrcpath} && make Makefiles"} result]} {
|
||||
return -code error "[format [msgcat::mc "%s failure: %s"] "make Makefiles" $result]"
|
||||
}
|
||||
} elseif {[tbool use_configure]} {
|
||||
# Merge (ld|c|cpp|cxx)flags into the environment variable.
|
||||
parse_environment configure
|
||||
|
||||
# Set pre-compiler filter to use (ccache/distcc), if any.
|
||||
if {[tbool configure.ccache] && [tbool configure.distcc]} {
|
||||
set filter ccache
|
||||
append_to_environment_value configure "CCACHE_PREFIX" "distcc"
|
||||
} elseif {[tbool configure.ccache]} {
|
||||
set filter ccache
|
||||
} elseif {[tbool configure.distcc]} {
|
||||
set filter distcc
|
||||
} else {
|
||||
set filter ""
|
||||
}
|
||||
foreach env_var {CC CXX OBJC OBJCXX} {
|
||||
append_to_environment_value configure $env_var $filter
|
||||
}
|
||||
|
||||
# Set flags controlling the kind of compiler output.
|
||||
if {[tbool configure.pipe]} {
|
||||
set output -pipe
|
||||
} else {
|
||||
set output ""
|
||||
}
|
||||
foreach env_var {CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS FFLAGS F90FLAGS FCFLAGS} {
|
||||
append_to_environment_value configure $env_var $output
|
||||
}
|
||||
|
||||
# Append configure flags.
|
||||
foreach env_var { \
|
||||
CC CXX OBJC OBJCXX FC F77 F90 JAVAC \
|
||||
CFLAGS CPPFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS \
|
||||
FFLAGS F90FLAGS FCFLAGS LDFLAGS LIBS CLASSPATH \
|
||||
PERL PYTHON RUBY INSTALL AWK BISON PKG_CONFIG \
|
||||
DEVELOPER_DIR \
|
||||
} {
|
||||
set value [option configure.[string tolower $env_var]]
|
||||
append_to_environment_value configure $env_var {*}$value
|
||||
}
|
||||
|
||||
foreach env_var { \
|
||||
PKG_CONFIG_PATH \
|
||||
} {
|
||||
set value [option configure.[string tolower $env_var]]
|
||||
append_to_environment_value configure $env_var [join $value ":"]
|
||||
}
|
||||
|
||||
# https://trac.macports.org/ticket/34221
|
||||
if {${os.platform} eq "darwin" && ${os.major} == 12} {
|
||||
append_to_environment_value configure "__CFPREFERENCES_AVOID_DAEMON" 1
|
||||
}
|
||||
|
||||
# add SDK flags if needed
|
||||
if {${configure.sdkroot} ne "" && !${compiler.limit_flags}} {
|
||||
foreach env_var {CPPFLAGS CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS} {
|
||||
append_to_environment_value configure $env_var -isysroot${configure.sdkroot}
|
||||
}
|
||||
append_to_environment_value configure "LDFLAGS" -Wl,-syslibroot,${configure.sdkroot}
|
||||
}
|
||||
|
||||
# add extra flags that are conditional on whether we're building universal
|
||||
append_to_environment_value configure CFLAGS {*}[get_canonical_archflags cc]
|
||||
if {![catch {get_canonical_archflags f77} flags]} {
|
||||
append_to_environment_value configure FFLAGS {*}$flags
|
||||
}
|
||||
foreach tool {cxx objc objcxx cpp f90 fc ld} {
|
||||
if {[catch {get_canonical_archflags $tool} flags]} {
|
||||
continue
|
||||
}
|
||||
set env_var [string toupper $tool]FLAGS
|
||||
append_to_environment_value configure $env_var {*}$flags
|
||||
}
|
||||
if {[variant_exists universal] && [variant_isset universal]} {
|
||||
configure.pre_args-append {*}${configure.universal_args}
|
||||
} else {
|
||||
foreach env_var {CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS FFLAGS F90FLAGS FCFLAGS LDFLAGS} {
|
||||
if {${configure.march} ne ""} {
|
||||
append_to_environment_value configure $env_var -march=${configure.march}
|
||||
}
|
||||
if {${configure.mtune} ne ""} {
|
||||
append_to_environment_value configure $env_var -mtune=${configure.mtune}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Execute the command (with the new environment).
|
||||
if {[catch {command_exec {*}${callback} configure} result]} {
|
||||
global configure.dir build.dir
|
||||
foreach error_log [list ${configure.dir}/config.log ${configure.dir}/CMakeFiles/CMakeError.log ${build.dir}/meson-logs/meson-log.txt] {
|
||||
if {[file exists ${error_log}]} {
|
||||
ui_error "[format [msgcat::mc "Failed to configure %s: consult %s"] [option subport] ${error_log}]"
|
||||
}
|
||||
}
|
||||
return -code error "[format [msgcat::mc "%s failure: %s"] configure $result]"
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
proc portconfigure::check_warnings {warning_flag} {
|
||||
global \
|
||||
workpath
|
||||
|
||||
set files [list]
|
||||
|
||||
fs-traverse -tails file [list ${workpath}] {
|
||||
if {[file tail $file] in [list config.log CMakeError.log meson-log.txt] && [file isfile [file join ${workpath} $file]]} {
|
||||
# We could do the searching ourselves, but using a tool optimized for this purpose is likely much faster
|
||||
# than using Tcl.
|
||||
#
|
||||
# Using /usr/bin/grep here so we don't accidentally pick up a MacPorts-installed grep which might
|
||||
# currently not be runnable due to a missing library.
|
||||
set args [list "/usr/bin/grep" "-El" "--" "-W[quotemeta $warning_flag]\\\]\$"]
|
||||
lappend args [file join ${workpath} $file]
|
||||
|
||||
if {![catch {exec -- {*}$args}]} {
|
||||
lappend files $file
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if {[llength $files] > 0} {
|
||||
ui_warn [format [msgcat::mc "Configuration logfiles contain indications of %s; check that features were not accidentally disabled:"] "-W$warning_flag"]
|
||||
foreach file $files {
|
||||
ui_msg [format " found in %s" $file]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
options configure.checks.implicit_int
|
||||
default configure.checks.implicit_int yes
|
||||
|
||||
proc portconfigure::check_implicit_int {} {
|
||||
portconfigure::check_warnings {implicit-int}
|
||||
}
|
||||
|
||||
options configure.checks.incompatible_function_pointer_types
|
||||
default configure.checks.incompatible_function_pointer_types yes
|
||||
|
||||
proc portconfigure::check_incompatible_function_pointer_types {} {
|
||||
portconfigure::check_warnings {incompatible-function-pointer-types}
|
||||
}
|
||||
|
||||
options configure.checks.implicit_function_declaration \
|
||||
options configure.checks.implicit_int \
|
||||
configure.checks.incompatible_function_pointer_types \
|
||||
configure.checks.implicit_function_declaration \
|
||||
configure.checks.implicit_function_declaration.whitelist
|
||||
|
||||
default configure.checks.implicit_int yes
|
||||
default configure.checks.incompatible_function_pointer_types yes
|
||||
default configure.checks.implicit_function_declaration yes
|
||||
default configure.checks.implicit_function_declaration.whitelist {[portconfigure::load_implicit_function_declaration_whitelist ${configure.sdk_version}]}
|
||||
|
||||
proc portconfigure::check_implicit_function_declarations {} {
|
||||
global \
|
||||
workpath \
|
||||
configure.checks.implicit_function_declaration.whitelist
|
||||
|
||||
# Map from function name to config.log that used it without declaration
|
||||
set undeclared_functions [dict create]
|
||||
|
||||
fs-traverse -tails file [list ${workpath}] {
|
||||
if {[file tail $file] in [list config.log CMakeError.log meson-log.txt] && [file isfile [file join ${workpath} $file]]} {
|
||||
# We could do the searching ourselves, but using a tool optimized for this purpose is likely much faster
|
||||
# than using Tcl.
|
||||
#
|
||||
# Using /usr/bin/grep here so we don't accidentally pick up a MacPorts-installed grep which might
|
||||
# currently not be runnable due to a missing library.
|
||||
set args [list "/usr/bin/grep" "-E" "--" "-Wimplicit-function-declaration\\\]\$"]
|
||||
lappend args [file join ${workpath} $file]
|
||||
|
||||
if {![catch {set result [exec -- {*}$args]}]} {
|
||||
foreach line [split $result "\n"] {
|
||||
if {[regexp -- "(?:implicit declaration of function|implicitly declaring library function|call to undeclared function|call to undeclared library function) '(\[^']+)'" $line -> function]} {
|
||||
set is_whitelisted no
|
||||
foreach whitelisted ${configure.checks.implicit_function_declaration.whitelist} {
|
||||
if {[string match -nocase $whitelisted $function]} {
|
||||
set is_whitelisted yes
|
||||
break
|
||||
}
|
||||
}
|
||||
if {!$is_whitelisted} {
|
||||
dict set undeclared_functions $function $file 1
|
||||
} else {
|
||||
ui_debug [format "Ignoring implicit declaration of function '%s' because it is whitelisted" $function]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if {[dict size $undeclared_functions] > 0} {
|
||||
ui_warn [format [msgcat::mc "Configuration logfiles contain indications of %s; check that features were not accidentally disabled:"] "-Wimplicit-function-declaration"]
|
||||
dict for {function files} $undeclared_functions {
|
||||
ui_msg [format " %s: found in %s" $function [join [dict keys $files] ", "]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc portconfigure::load_implicit_function_declaration_whitelist {sdk_version} {
|
||||
set whitelist [list]
|
||||
|
||||
@@ -2035,23 +1730,3 @@ proc portconfigure::load_implicit_function_declaration_whitelist {sdk_version} {
|
||||
|
||||
return $whitelist
|
||||
}
|
||||
|
||||
proc portconfigure::configure_finish {args} {
|
||||
global \
|
||||
configure.dir \
|
||||
configure.checks.implicit_function_declaration \
|
||||
configure.checks.implicit_int \
|
||||
configure.checks.incompatible_function_pointer_types
|
||||
|
||||
if {[file isdirectory ${configure.dir}]} {
|
||||
if {${configure.checks.implicit_function_declaration}} {
|
||||
portconfigure::check_implicit_function_declarations
|
||||
}
|
||||
if {${configure.checks.implicit_int}} {
|
||||
portconfigure::check_implicit_int
|
||||
}
|
||||
if {${configure.checks.incompatible_function_pointer_types}} {
|
||||
portconfigure::check_incompatible_function_pointer_types
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,330 @@
|
||||
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
|
||||
|
||||
package provide portconfigure_run 1.0
|
||||
package require portutil 1.0
|
||||
package require portprogress 1.0
|
||||
|
||||
namespace eval portconfigure {
|
||||
|
||||
proc configure_start {args} {
|
||||
global UI_PREFIX subport configure.compiler compiler.fallback configure.ccache
|
||||
|
||||
ui_notice "$UI_PREFIX [format [msgcat::mc "Configuring %s"] $subport]"
|
||||
|
||||
set compiler ${configure.compiler}
|
||||
set valid_compilers {
|
||||
{^apple-gcc-(4\.[02])$} {MacPorts Apple GCC %s}
|
||||
{^cc$} {System cc}
|
||||
{^clang$} {Xcode Clang}
|
||||
{^gcc$} {System GCC}
|
||||
{^gcc-(3\.3|4\.[02])$} {Xcode GCC %s}
|
||||
{^llvm-gcc-4\.2$} {Xcode LLVM-GCC 4.2}
|
||||
{^macports-clang$} {MacPorts Clang (port select)}
|
||||
{^macports-clang-(\d+(?:\.\d+)?)$} {MacPorts Clang %s}
|
||||
{^macports-gcc$} {MacPorts GCC (port select)}
|
||||
{^macports-gcc-(\d+(?:\.\d+)?)$} {MacPorts GCC %s}
|
||||
{^macports-llvm-gcc-4\.2$} {MacPorts LLVM-GCC 4.2}
|
||||
{^macports-g95$} {MacPorts G95}
|
||||
{^macports-mpich-default$} {MacPorts MPICH Wrapper for MacPorts' Default C/C++ Compiler}
|
||||
{^macports-openmpi-default$} {MacPorts Open MPI Wrapper for MacPorts' Default C/C++ Compiler}
|
||||
{^macports-mpich-clang$} {MacPorts MPICH Wrapper for Xcode Clang}
|
||||
{^macports-openmpi-clang$} {MacPorts Open MPI Wrapper for Xcode Clang}
|
||||
{^macports-mpich-clang-(\d+(?:\.\d+)?)$} {MacPorts MPICH Wrapper for Clang %s}
|
||||
{^macports-openmpi-clang-(\d+(?:\.\d+)?)$} {MacPorts Open MPI Wrapper for Clang %s}
|
||||
{^macports-mpich-gcc-(\d+(?:\.\d+)?)$} {MacPorts MPICH Wrapper for GCC %s}
|
||||
{^macports-openmpi-gcc-(\d+(?:\.\d+)?)$} {MacPorts Open MPI Wrapper for GCC %s}
|
||||
{^macports-(clang|gcc)-devel$} {MacPorts %s Development}
|
||||
}
|
||||
foreach {re fmt} $valid_compilers {
|
||||
if {[set matches [regexp -inline $re $compiler]] ne ""} {
|
||||
set compiler_name [format $fmt {*}[lrange $matches 1 end]]
|
||||
break
|
||||
}
|
||||
}
|
||||
if {![info exists compiler_name]} {
|
||||
return -code error "Invalid value for configure.compiler: $compiler"
|
||||
}
|
||||
ui_debug "Preferred compilers: ${compiler.fallback}"
|
||||
ui_debug "Using compiler '$compiler_name'"
|
||||
variable no_default_compiler_allowed
|
||||
if {$no_default_compiler_allowed} {
|
||||
ui_warn_once no_default_compiler_allowed "All compilers are either blacklisted or unavailable; defaulting to first fallback option"
|
||||
}
|
||||
|
||||
# Additional ccache directory setup
|
||||
if {${configure.ccache}} {
|
||||
global ccache_dir ccache_size macportsuser
|
||||
# Create ccache directory with correct permissions with root privileges
|
||||
elevateToRoot "configure ccache"
|
||||
if {[catch {
|
||||
file mkdir ${ccache_dir}
|
||||
file attributes ${ccache_dir} -owner ${macportsuser} -permissions 0755
|
||||
} result]} {
|
||||
ui_warn "ccache_dir ${ccache_dir} could not be created; disabling ccache: $result"
|
||||
set configure.ccache no
|
||||
}
|
||||
dropPrivileges
|
||||
|
||||
# Initialize ccache directory with the given maximum size
|
||||
if {${configure.ccache}} {
|
||||
if {[catch {
|
||||
exec ccache -M ${ccache_size} >/dev/null
|
||||
} result]} {
|
||||
ui_warn "ccache_dir ${ccache_dir} could not be initialized; disabling ccache: $result"
|
||||
set configure.ccache no
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc configure_main {args} {
|
||||
global worksrcpath use_configure use_autoreconf use_autoconf use_automake use_xmkmf \
|
||||
configure.pipe configure.libs configure.classpath configure.universal_args \
|
||||
configure.perl configure.python configure.ruby configure.install configure.awk configure.bison \
|
||||
configure.pkg_config configure.pkg_config_path \
|
||||
configure.ccache configure.distcc configure.javac configure.sdkroot \
|
||||
configure.march configure.mtune os.platform os.major \
|
||||
compiler.limit_flags
|
||||
foreach tool {cc cxx objc objcxx f77 f90 fc ld} {
|
||||
global configure.${tool} configure.${tool}_archflags
|
||||
}
|
||||
foreach flags {cflags cppflags cxxflags objcflags objcxxflags ldflags fflags f90flags fcflags} {
|
||||
global configure.${flags} configure.universal_${flags}
|
||||
}
|
||||
|
||||
set callback [list "-callback" portprogress::target_progress_callback]
|
||||
|
||||
if {[tbool use_autoreconf]} {
|
||||
if {[catch {command_exec {*}${callback} autoreconf} result]} {
|
||||
return -code error "[format [msgcat::mc "%s failure: %s"] autoreconf $result]"
|
||||
}
|
||||
}
|
||||
|
||||
if {[tbool use_automake]} {
|
||||
if {[catch {command_exec {*}${callback} automake} result]} {
|
||||
return -code error "[format [msgcat::mc "%s failure: %s"] automake $result]"
|
||||
}
|
||||
}
|
||||
|
||||
if {[tbool use_autoconf]} {
|
||||
if {[catch {command_exec {*}${callback} autoconf} result]} {
|
||||
return -code error "[format [msgcat::mc "%s failure: %s"] autoconf $result]"
|
||||
}
|
||||
}
|
||||
|
||||
if {[tbool use_xmkmf]} {
|
||||
parse_environment xmkmf
|
||||
if {[catch {command_exec {*}${callback} xmkmf} result]} {
|
||||
return -code error "[format [msgcat::mc "%s failure: %s"] xmkmf $result]"
|
||||
}
|
||||
|
||||
parse_environment xmkmf
|
||||
if {[catch {command_exec {*}${callback} -varprefix xmkmf "cd ${worksrcpath} && make Makefiles"} result]} {
|
||||
return -code error "[format [msgcat::mc "%s failure: %s"] "make Makefiles" $result]"
|
||||
}
|
||||
} elseif {[tbool use_configure]} {
|
||||
# Merge (ld|c|cpp|cxx)flags into the environment variable.
|
||||
parse_environment configure
|
||||
|
||||
# Set pre-compiler filter to use (ccache/distcc), if any.
|
||||
if {[tbool configure.ccache] && [tbool configure.distcc]} {
|
||||
set filter ccache
|
||||
append_to_environment_value configure "CCACHE_PREFIX" "distcc"
|
||||
} elseif {[tbool configure.ccache]} {
|
||||
set filter ccache
|
||||
} elseif {[tbool configure.distcc]} {
|
||||
set filter distcc
|
||||
} else {
|
||||
set filter ""
|
||||
}
|
||||
foreach env_var {CC CXX OBJC OBJCXX} {
|
||||
append_to_environment_value configure $env_var $filter
|
||||
}
|
||||
|
||||
# Set flags controlling the kind of compiler output.
|
||||
if {[tbool configure.pipe]} {
|
||||
set output -pipe
|
||||
} else {
|
||||
set output ""
|
||||
}
|
||||
foreach env_var {CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS FFLAGS F90FLAGS FCFLAGS} {
|
||||
append_to_environment_value configure $env_var $output
|
||||
}
|
||||
|
||||
# Append configure flags.
|
||||
foreach env_var { \
|
||||
CC CXX OBJC OBJCXX FC F77 F90 JAVAC \
|
||||
CFLAGS CPPFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS \
|
||||
FFLAGS F90FLAGS FCFLAGS LDFLAGS LIBS CLASSPATH \
|
||||
PERL PYTHON RUBY INSTALL AWK BISON PKG_CONFIG \
|
||||
DEVELOPER_DIR \
|
||||
} {
|
||||
set value [option configure.[string tolower $env_var]]
|
||||
append_to_environment_value configure $env_var {*}$value
|
||||
}
|
||||
|
||||
foreach env_var { \
|
||||
PKG_CONFIG_PATH \
|
||||
} {
|
||||
set value [option configure.[string tolower $env_var]]
|
||||
append_to_environment_value configure $env_var [join $value ":"]
|
||||
}
|
||||
|
||||
# https://trac.macports.org/ticket/34221
|
||||
if {${os.platform} eq "darwin" && ${os.major} == 12} {
|
||||
append_to_environment_value configure "__CFPREFERENCES_AVOID_DAEMON" 1
|
||||
}
|
||||
|
||||
# add SDK flags if needed
|
||||
if {${configure.sdkroot} ne "" && !${compiler.limit_flags}} {
|
||||
foreach env_var {CPPFLAGS CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS} {
|
||||
append_to_environment_value configure $env_var -isysroot${configure.sdkroot}
|
||||
}
|
||||
append_to_environment_value configure "LDFLAGS" -Wl,-syslibroot,${configure.sdkroot}
|
||||
}
|
||||
|
||||
# add extra flags that are conditional on whether we're building universal
|
||||
append_to_environment_value configure CFLAGS {*}[get_canonical_archflags cc]
|
||||
if {![catch {get_canonical_archflags f77} flags]} {
|
||||
append_to_environment_value configure FFLAGS {*}$flags
|
||||
}
|
||||
foreach tool {cxx objc objcxx cpp f90 fc ld} {
|
||||
if {[catch {get_canonical_archflags $tool} flags]} {
|
||||
continue
|
||||
}
|
||||
set env_var [string toupper $tool]FLAGS
|
||||
append_to_environment_value configure $env_var {*}$flags
|
||||
}
|
||||
if {[variant_exists universal] && [variant_isset universal]} {
|
||||
configure.pre_args-append {*}${configure.universal_args}
|
||||
} else {
|
||||
foreach env_var {CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS FFLAGS F90FLAGS FCFLAGS LDFLAGS} {
|
||||
if {${configure.march} ne ""} {
|
||||
append_to_environment_value configure $env_var -march=${configure.march}
|
||||
}
|
||||
if {${configure.mtune} ne ""} {
|
||||
append_to_environment_value configure $env_var -mtune=${configure.mtune}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Execute the command (with the new environment).
|
||||
if {[catch {command_exec {*}${callback} configure} result]} {
|
||||
global configure.dir build.dir
|
||||
foreach error_log [list ${configure.dir}/config.log ${configure.dir}/CMakeFiles/CMakeError.log ${build.dir}/meson-logs/meson-log.txt] {
|
||||
if {[file exists ${error_log}]} {
|
||||
ui_error "[format [msgcat::mc "Failed to configure %s: consult %s"] [option subport] ${error_log}]"
|
||||
}
|
||||
}
|
||||
return -code error "[format [msgcat::mc "%s failure: %s"] configure $result]"
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
proc check_warnings {warning_flag} {
|
||||
global \
|
||||
workpath
|
||||
|
||||
set files [list]
|
||||
|
||||
fs-traverse -tails file [list ${workpath}] {
|
||||
if {[file tail $file] in [list config.log CMakeError.log meson-log.txt] && [file isfile [file join ${workpath} $file]]} {
|
||||
# We could do the searching ourselves, but using a tool optimized for this purpose is likely much faster
|
||||
# than using Tcl.
|
||||
#
|
||||
# Using /usr/bin/grep here so we don't accidentally pick up a MacPorts-installed grep which might
|
||||
# currently not be runnable due to a missing library.
|
||||
set args [list "/usr/bin/grep" "-El" "--" "-W[quotemeta $warning_flag]\\\]\$"]
|
||||
lappend args [file join ${workpath} $file]
|
||||
|
||||
if {![catch {exec -- {*}$args}]} {
|
||||
lappend files $file
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if {[llength $files] > 0} {
|
||||
ui_warn [format [msgcat::mc "Configuration logfiles contain indications of %s; check that features were not accidentally disabled:"] "-W$warning_flag"]
|
||||
foreach file $files {
|
||||
ui_msg [format " found in %s" $file]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc check_implicit_int {} {
|
||||
check_warnings {implicit-int}
|
||||
}
|
||||
|
||||
proc check_incompatible_function_pointer_types {} {
|
||||
check_warnings {incompatible-function-pointer-types}
|
||||
}
|
||||
|
||||
proc check_implicit_function_declarations {} {
|
||||
global \
|
||||
workpath \
|
||||
configure.checks.implicit_function_declaration.whitelist
|
||||
|
||||
# Map from function name to config.log that used it without declaration
|
||||
set undeclared_functions [dict create]
|
||||
|
||||
fs-traverse -tails file [list ${workpath}] {
|
||||
if {[file tail $file] in [list config.log CMakeError.log meson-log.txt] && [file isfile [file join ${workpath} $file]]} {
|
||||
# We could do the searching ourselves, but using a tool optimized for this purpose is likely much faster
|
||||
# than using Tcl.
|
||||
#
|
||||
# Using /usr/bin/grep here so we don't accidentally pick up a MacPorts-installed grep which might
|
||||
# currently not be runnable due to a missing library.
|
||||
set args [list "/usr/bin/grep" "-E" "--" "-Wimplicit-function-declaration\\\]\$"]
|
||||
lappend args [file join ${workpath} $file]
|
||||
|
||||
if {![catch {set result [exec -- {*}$args]}]} {
|
||||
foreach line [split $result "\n"] {
|
||||
if {[regexp -- "(?:implicit declaration of function|implicitly declaring library function|call to undeclared function|call to undeclared library function) '(\[^']+)'" $line -> function]} {
|
||||
set is_whitelisted no
|
||||
foreach whitelisted ${configure.checks.implicit_function_declaration.whitelist} {
|
||||
if {[string match -nocase $whitelisted $function]} {
|
||||
set is_whitelisted yes
|
||||
break
|
||||
}
|
||||
}
|
||||
if {!$is_whitelisted} {
|
||||
dict set undeclared_functions $function $file 1
|
||||
} else {
|
||||
ui_debug [format "Ignoring implicit declaration of function '%s' because it is whitelisted" $function]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if {[dict size $undeclared_functions] > 0} {
|
||||
ui_warn [format [msgcat::mc "Configuration logfiles contain indications of %s; check that features were not accidentally disabled:"] "-Wimplicit-function-declaration"]
|
||||
dict for {function files} $undeclared_functions {
|
||||
ui_msg [format " %s: found in %s" $function [join [dict keys $files] ", "]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc configure_finish {args} {
|
||||
global \
|
||||
configure.dir \
|
||||
configure.checks.implicit_function_declaration \
|
||||
configure.checks.implicit_int \
|
||||
configure.checks.incompatible_function_pointer_types
|
||||
|
||||
if {[file isdirectory ${configure.dir}]} {
|
||||
if {${configure.checks.implicit_function_declaration}} {
|
||||
check_implicit_function_declarations
|
||||
}
|
||||
if {${configure.checks.implicit_int}} {
|
||||
check_implicit_int
|
||||
}
|
||||
if {${configure.checks.incompatible_function_pointer_types}} {
|
||||
check_incompatible_function_pointer_types
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,38 +1,8 @@
|
||||
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
|
||||
# portdeactivate.tcl
|
||||
#
|
||||
# Copyright (c) 2010-2011 The MacPorts Project
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of The MacPorts Project nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
# the 'deactivate' target is provided by this package
|
||||
|
||||
package provide portdeactivate 1.0
|
||||
package require portutil 1.0
|
||||
|
||||
set org.macports.deactivate [target_new org.macports.deactivate portdeactivate::deactivate_main]
|
||||
target_runtype ${org.macports.deactivate} always
|
||||
@@ -40,35 +10,7 @@ target_state ${org.macports.deactivate} no
|
||||
target_provides ${org.macports.deactivate} deactivate
|
||||
target_requires ${org.macports.deactivate} main
|
||||
target_prerun ${org.macports.deactivate} portdeactivate::deactivate_start
|
||||
|
||||
namespace eval portdeactivate {
|
||||
}
|
||||
target_runpkg ${org.macports.deactivate} portdeactivate_run
|
||||
|
||||
options deactivate.asroot
|
||||
set deactivate.asroot no
|
||||
|
||||
proc portdeactivate::deactivate_start {args} {
|
||||
global prefix
|
||||
if {![file writable $prefix] || ([getuid] == 0 && [geteuid] != 0)} {
|
||||
# if install location is not writable, need root privileges
|
||||
elevateToRoot "deactivate"
|
||||
}
|
||||
}
|
||||
|
||||
proc portdeactivate::deactivate_main {args} {
|
||||
global subport _inregistry_version _inregistry_revision _inregistry_variants user_options
|
||||
foreach {var backup} {_inregistry_version version _inregistry_revision revision _inregistry_variants portvariants} {
|
||||
if {![info exists $var]} {
|
||||
set $var [option $backup]
|
||||
}
|
||||
}
|
||||
|
||||
if {[portstartupitem::loaded] ne ""} {
|
||||
if {[eval_targets "unload"]} {
|
||||
ui_warn [format [msgcat::mc "Failed to unload startupitem(s) for %s (continuing anyway)"] $subport]
|
||||
}
|
||||
}
|
||||
|
||||
registry_deactivate $subport $_inregistry_version $_inregistry_revision $_inregistry_variants [array get user_options]
|
||||
return 0
|
||||
}
|
||||
default deactivate.asroot no
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
|
||||
#
|
||||
# Copyright (c) 2010-2011 The MacPorts Project
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of The MacPorts Project nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package provide portdeactivate_run 1.0
|
||||
package require portutil 1.0
|
||||
|
||||
namespace eval portdeactivate {
|
||||
|
||||
proc deactivate_start {args} {
|
||||
global prefix
|
||||
if {![file writable $prefix] || ([getuid] == 0 && [geteuid] != 0)} {
|
||||
# if install location is not writable, need root privileges
|
||||
elevateToRoot "deactivate"
|
||||
}
|
||||
}
|
||||
|
||||
proc deactivate_main {args} {
|
||||
global subport _inregistry_version _inregistry_revision _inregistry_variants user_options
|
||||
foreach {var backup} {_inregistry_version version _inregistry_revision revision _inregistry_variants portvariants} {
|
||||
if {![info exists $var]} {
|
||||
set $var [option $backup]
|
||||
}
|
||||
}
|
||||
|
||||
if {[portstartupitem::loaded] ne ""} {
|
||||
if {[eval_targets "unload"]} {
|
||||
ui_warn [format [msgcat::mc "Failed to unload startupitem(s) for %s (continuing anyway)"] $subport]
|
||||
}
|
||||
}
|
||||
|
||||
registry_deactivate $subport $_inregistry_version $_inregistry_revision $_inregistry_variants [array get user_options]
|
||||
return 0
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
# et:ts=4
|
||||
# portdepends.tcl
|
||||
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
|
||||
#
|
||||
# Copyright (c) 2005, 2007-2009 The MacPorts Project
|
||||
# Copyright (c) 2002 - 2003 Apple Inc.
|
||||
@@ -28,13 +27,8 @@
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
package provide portdepends 1.0
|
||||
package require portutil 1.0
|
||||
|
||||
namespace eval portdepends {
|
||||
}
|
||||
|
||||
# define options
|
||||
options depends_fetch depends_extract depends_patch depends_build depends_run depends_lib depends_test depends
|
||||
@@ -52,9 +46,9 @@ option_proc depends_test portdepends::validate_depends_options
|
||||
# New option for the new dependency. We generate a warning because we don't handle this yet.
|
||||
option_proc depends portdepends::validate_depends_options_new
|
||||
|
||||
set_ui_prefix
|
||||
namespace eval portdepends {
|
||||
|
||||
proc portdepends::validate_depends_options {option action {value ""}} {
|
||||
proc validate_depends_options {option action {value ""}} {
|
||||
switch $action {
|
||||
set {
|
||||
foreach depspec $value {
|
||||
@@ -69,6 +63,8 @@ proc portdepends::validate_depends_options {option action {value ""}} {
|
||||
}
|
||||
}
|
||||
|
||||
proc portdepends::validate_depends_options_new {option action {value ""}} {
|
||||
proc validate_depends_options_new {option action {value ""}} {
|
||||
ui_warn [msgcat::mc "depends option is not handled yet"]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,49 +1,13 @@
|
||||
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:filetype=tcl:et:sw=4:ts=4:sts=4
|
||||
# portdestroot.tcl
|
||||
#
|
||||
# Copyright (c) 2002 - 2003 Apple Inc.
|
||||
# Copyright (c) 2004 - 2005 Robert Shaw <rshaw@opendarwin.org>
|
||||
# Copyright (c) 2004-2005, 2007-2013 The MacPorts Project
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of Apple Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
package provide portdestroot 1.0
|
||||
package require portutil 1.0
|
||||
|
||||
set org.macports.destroot [target_new org.macports.destroot portdestroot::destroot_main]
|
||||
target_provides ${org.macports.destroot} destroot
|
||||
target_requires ${org.macports.destroot} main fetch checksum extract patch configure build
|
||||
target_prerun ${org.macports.destroot} portdestroot::destroot_start
|
||||
target_postrun ${org.macports.destroot} portdestroot::destroot_finish
|
||||
|
||||
namespace eval portdestroot {
|
||||
# Save old umask
|
||||
variable oldmask
|
||||
}
|
||||
target_runpkg ${org.macports.destroot} portdestroot_run
|
||||
|
||||
# define options
|
||||
options destroot.target destroot.destdir destroot.clean destroot.keepdirs destroot.umask \
|
||||
@@ -65,9 +29,8 @@ default destroot.keepdirs {}
|
||||
default destroot.violate_mtree no
|
||||
default destroot.delete_la_files {${delete_la_files}}
|
||||
|
||||
set_ui_prefix
|
||||
|
||||
proc portdestroot::destroot_getargs {args} {
|
||||
namespace eval portdestroot {
|
||||
proc destroot_getargs {args} {
|
||||
global build.type os.platform destroot.cmd destroot.target
|
||||
if {((${build.type} eq "default" && ${os.platform} ne "freebsd") ||
|
||||
(${build.type} eq "gnu"))
|
||||
@@ -78,376 +41,4 @@ proc portdestroot::destroot_getargs {args} {
|
||||
|
||||
return ${destroot.target}
|
||||
}
|
||||
|
||||
proc portdestroot::destroot_start {args} {
|
||||
global UI_PREFIX prefix subport destroot os.platform destroot.clean portsharepath \
|
||||
destroot.umask destroot.asroot euid egid \
|
||||
applications_dir frameworks_dir
|
||||
variable oldmask
|
||||
|
||||
ui_notice "$UI_PREFIX [format [msgcat::mc "Staging %s into destroot"] ${subport}]"
|
||||
|
||||
# start gsoc08-privileges
|
||||
if { [getuid] == 0 && [geteuid] != 0 } {
|
||||
# if started with sudo but have dropped the privileges
|
||||
ui_debug "Can't run destroot under sudo without elevated privileges (due to mtree)."
|
||||
ui_debug "Run destroot without sudo to avoid root privileges."
|
||||
ui_debug "Going to escalate privileges back to root."
|
||||
seteuid $euid
|
||||
setegid $egid
|
||||
ui_debug "euid changed to: [geteuid]. egid changed to: [getegid]."
|
||||
}
|
||||
|
||||
if { [tbool destroot.asroot] && [getuid] != 0 } {
|
||||
return -code error "You cannot run this port without root privileges. You need to re-run with 'sudo port'.";
|
||||
}
|
||||
|
||||
# end gsoc08-privileges
|
||||
|
||||
set oldmask [umask ${destroot.umask}]
|
||||
set mtree [findBinary mtree ${::portutil::autoconf::mtree_path}]
|
||||
|
||||
if { ${destroot.clean} eq "yes" } {
|
||||
delete "${destroot}"
|
||||
}
|
||||
|
||||
file mkdir "${destroot}"
|
||||
if { ${os.platform} eq "darwin" } {
|
||||
system -W ${destroot} "${mtree} -e -U -f [shellescape [file join ${portsharepath} install macosx.mtree]]"
|
||||
file mkdir "${destroot}${applications_dir}"
|
||||
file mkdir "${destroot}${frameworks_dir}"
|
||||
}
|
||||
file mkdir "${destroot}${prefix}"
|
||||
system -W ${destroot}${prefix} "${mtree} -e -U -f [shellescape [file join ${portsharepath} install prefix.mtree]]"
|
||||
|
||||
# Create startup-scripts/items
|
||||
portstartupitem::startupitem_create
|
||||
}
|
||||
|
||||
proc portdestroot::destroot_main {args} {
|
||||
global system_options
|
||||
if {$system_options(clonebin_path) ne ""} {
|
||||
global env
|
||||
set saved_path $env(PATH)
|
||||
set env(PATH) $system_options(clonebin_path):$env(PATH)
|
||||
}
|
||||
try {
|
||||
command_exec -callback portprogress::target_progress_callback destroot
|
||||
} finally {
|
||||
if {[info exists saved_path]} {
|
||||
set env(PATH) $saved_path
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
proc portdestroot::destroot_finish {args} {
|
||||
global UI_PREFIX destroot prefix subport destroot.violate_mtree \
|
||||
applications_dir frameworks_dir destroot.keepdirs \
|
||||
destroot.delete_la_files install.user install.group \
|
||||
macportsuser
|
||||
variable oldmask
|
||||
|
||||
foreach fileToDelete {share/info/dir lib/charset.alias} {
|
||||
if {[file exists "${destroot}${prefix}/${fileToDelete}"]} {
|
||||
ui_debug "Deleting stray ${fileToDelete} file."
|
||||
file delete "${destroot}${prefix}/${fileToDelete}"
|
||||
}
|
||||
}
|
||||
|
||||
# Prevent overlinking due to glibtool .la files: https://trac.macports.org/ticket/38010
|
||||
ui_debug "Fixing glibtool .la files in destroot for ${subport}"
|
||||
if {[getuid] == 0} {
|
||||
set macports_uid [name_to_uid $macportsuser]
|
||||
set macports_gid [uname_to_gid $macportsuser]
|
||||
set fix_ownership 1
|
||||
} else {
|
||||
set fix_ownership 0
|
||||
}
|
||||
fs-traverse -depth fullpath [list $destroot] {
|
||||
file lstat $fullpath statinfo
|
||||
# Ensure installed files are not owned by the unprivileged account
|
||||
if {$fix_ownership && ($statinfo(uid) == $macports_uid || $statinfo(gid) == $macports_gid)} {
|
||||
if {$statinfo(uid) == $macports_uid} {
|
||||
ui_debug "Changing owner to ${install.user} for $fullpath"
|
||||
set new_owner ${install.user}
|
||||
} else {
|
||||
# only group needs to be changed
|
||||
set new_owner -1
|
||||
}
|
||||
if {$statinfo(gid) == $macports_gid} {
|
||||
ui_debug "Changing group to ${install.group} for $fullpath"
|
||||
set new_group ${install.group}
|
||||
} else {
|
||||
# only owner needs to be changed
|
||||
set new_group -1
|
||||
}
|
||||
# Changing owner may also change permissions, so we restore
|
||||
# them afterwards. 'file attributes' doesn't work on links
|
||||
# (it operates on the link target instead) but links should
|
||||
# not have setuid/setgid bits set anyway.
|
||||
if {$statinfo(type) ne "link"} {
|
||||
set saved_perms [file attributes $fullpath -permissions]
|
||||
}
|
||||
lchown $fullpath $new_owner $new_group
|
||||
if {$statinfo(type) ne "link"} {
|
||||
file attributes $fullpath -permissions $saved_perms
|
||||
}
|
||||
}
|
||||
if {[file extension $fullpath] eq ".la" && $statinfo(type) in {file link}} {
|
||||
if {$statinfo(type) eq "link" && [file pathtype [file link $fullpath]] ne "relative"} {
|
||||
# prepend $destroot to target of absolute symlinks
|
||||
set checkpath ${destroot}[file link $fullpath]
|
||||
} else {
|
||||
set checkpath $fullpath
|
||||
}
|
||||
# Make sure it is from glibtool ... "a libtool library file" will appear in the first line
|
||||
set is_la_file 0
|
||||
if {![catch {open $checkpath} fp]} {
|
||||
if {[gets $fp line] > 0 && [string first "a libtool library file" $line] != -1} {
|
||||
set is_la_file 1
|
||||
}
|
||||
catch {close $fp}
|
||||
} else {
|
||||
ui_debug "Failed to open $checkpath"
|
||||
}
|
||||
if {$is_la_file} {
|
||||
if {${destroot.delete_la_files}} {
|
||||
ui_debug "Removing [file tail $fullpath]"
|
||||
file delete ${fullpath}
|
||||
} elseif {$statinfo(type) eq "file"} {
|
||||
ui_debug "Clearing dependency_libs in [file tail $fullpath]"
|
||||
reinplace -q "/dependency_libs/ s/'.*'/''/" ${fullpath}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Prune empty directories in ${destroot}
|
||||
package require fileutil
|
||||
foreach path ${destroot.keepdirs} {
|
||||
# Prepend $destroot if $path isn't already inside it
|
||||
set path [::fileutil::jail $destroot $path]
|
||||
if {![file isdirectory ${path}]} {
|
||||
xinstall -m 0755 -d ${path}
|
||||
}
|
||||
if {![file exists ${path}/.turd_${subport}]} {
|
||||
xinstall -c -m 0644 /dev/null ${path}/.turd_${subport}
|
||||
}
|
||||
}
|
||||
fs-traverse -depth dir [list ${destroot}] {
|
||||
if {[file type $dir] eq "directory"} {
|
||||
catch {file delete $dir}
|
||||
}
|
||||
}
|
||||
|
||||
if {![file isdirectory ${destroot}]} {
|
||||
ui_error "No files have been installed in the destroot directory!"
|
||||
ui_error "Please make sure that this software supports\
|
||||
'make install DESTDIR=\${destroot}' or implement an\
|
||||
alternative destroot mechanism in the Portfile."
|
||||
ui_error "Files might have been installed directly into your system,\
|
||||
check before proceeding."
|
||||
return -code error "Staging $subport into destroot failed"
|
||||
}
|
||||
|
||||
# Compress all manpages with gzip (instead)
|
||||
set manpath ${destroot}${prefix}/share/man
|
||||
if {[file isdirectory ${manpath}] && [file type ${manpath}] eq "directory"} {
|
||||
ui_info "$UI_PREFIX [format [msgcat::mc "Compressing man pages for %s"] ${subport}]"
|
||||
|
||||
set gzip [findBinary gzip ${::portutil::autoconf::gzip_path}]
|
||||
set gunzip "$gzip -d"
|
||||
set bunzip2 "[findBinary bzip2 ${::portutil::autoconf::bzip2_path}] -d"
|
||||
|
||||
set found 0
|
||||
set manlinks [list]
|
||||
set mandir_re {^(cat|man)(.)$}
|
||||
|
||||
foreach mandir [readdir "${manpath}"] {
|
||||
if {![regexp ${mandir_re} ${mandir} match ignore manindex]} { continue }
|
||||
set gzfile_re "^(.*\[.\]${manindex}\[a-z\]*)\[.\]gz\$"
|
||||
set bz2file_re "^(.*\[.\]${manindex}\[a-z\]*)\[.\]bz2\$"
|
||||
set normalfile_re "\[.\]${manindex}\[a-z\]*\$"
|
||||
set mandirpath [file join ${manpath} ${mandir}]
|
||||
if {[file isdirectory ${mandirpath}] && [file type ${mandirpath}] eq "directory"} {
|
||||
ui_debug "Scanning ${mandir}"
|
||||
foreach manfile [readdir ${mandirpath}] {
|
||||
set manfilepath [file join ${mandirpath} ${manfile}]
|
||||
if {[file isfile ${manfilepath}] && [file type ${manfilepath}] eq "file"} {
|
||||
if {[regexp ${gzfile_re} ${manfile} gzfile manfile]} {
|
||||
set found 1
|
||||
system -W ${manpath} \
|
||||
"$gunzip -f [shellescape [file join ${mandir} ${gzfile}]] && \
|
||||
$gzip -9vnf [shellescape [file join ${mandir} ${manfile}]]"
|
||||
} elseif {[regexp ${bz2file_re} ${manfile} bz2file manfile]} {
|
||||
set found 1
|
||||
system -W ${manpath} \
|
||||
"$bunzip2 -f [shellescape [file join ${mandir} ${bz2file}]] && \
|
||||
$gzip -9vnf [shellescape [file join ${mandir} ${manfile}]]"
|
||||
} elseif {[regexp ${normalfile_re} ${manfile}]} {
|
||||
set found 1
|
||||
system -W ${manpath} \
|
||||
"$gzip -9vnf [shellescape [file join ${mandir} ${manfile}]]"
|
||||
}
|
||||
set gzmanfile ${manfile}.gz
|
||||
set gzmanfilepath [file join ${mandirpath} ${gzmanfile}]
|
||||
if {[file exists ${gzmanfilepath}]} {
|
||||
set desired 00444
|
||||
set current [file attributes ${gzmanfilepath} -permissions]
|
||||
if {$current != $desired} {
|
||||
ui_info "[file join ${mandir} ${gzmanfile}]: changing permissions from $current to $desired"
|
||||
file attributes ${gzmanfilepath} -permissions $desired
|
||||
}
|
||||
}
|
||||
} elseif {[file type ${manfilepath}] eq "link"} {
|
||||
lappend manlinks [file join ${mandir} ${manfile}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if {$found == 1} {
|
||||
# check man page links and rename/repoint them if necessary
|
||||
set gzext_re "\[.\]gz\$"
|
||||
foreach manlink $manlinks {
|
||||
set manlinkpath [file join $manpath $manlink]
|
||||
# if link destination is not gzipped, check it
|
||||
set manlinksrc [file readlink $manlinkpath]
|
||||
if {![regexp ${gzext_re} ${manlinksrc}]} {
|
||||
set mandir [file dirname $manlink]
|
||||
set mandirpath [file join $manpath $mandir]
|
||||
if {[catch {pwd} oldpwd]} {
|
||||
set oldpwd {}
|
||||
}
|
||||
if {[catch {_cd $mandirpath} err]} {
|
||||
puts $err
|
||||
return
|
||||
}
|
||||
# if link source is an absolute path, check for it under destroot
|
||||
set mls_check "$manlinksrc"
|
||||
if {[file pathtype $mls_check] eq "absolute"} {
|
||||
set mls_check "${destroot}${mls_check}"
|
||||
}
|
||||
# if gzipped destination exists, fix link
|
||||
if {[file isfile ${mls_check}.gz]} {
|
||||
# if actual link name does not end with gz, rename it
|
||||
if {![regexp ${gzext_re} ${manlink}]} {
|
||||
ui_debug "renaming link: $manlink to ${manlink}.gz"
|
||||
file rename $manlinkpath ${manlinkpath}.gz
|
||||
set manlink ${manlink}.gz
|
||||
set manlinkpath [file join $manpath $manlink]
|
||||
}
|
||||
# repoint the link
|
||||
ui_debug "repointing link: $manlink from $manlinksrc to ${manlinksrc}.gz"
|
||||
file delete $manlinkpath
|
||||
ln -s "${manlinksrc}.gz" "${manlinkpath}"
|
||||
}
|
||||
if {$oldpwd ne {}} {
|
||||
_cd $oldpwd
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ui_debug "No man pages found to compress."
|
||||
}
|
||||
}
|
||||
|
||||
# test for violations of mtree
|
||||
if { ${destroot.violate_mtree} ne "yes" } {
|
||||
ui_debug "checking for mtree violations"
|
||||
set mtree_violation "no"
|
||||
|
||||
set prefixPaths [list bin etc include lib libexec sbin share src var www Applications Developer Library]
|
||||
|
||||
set pathsToCheck [list /]
|
||||
while {[llength $pathsToCheck] > 0} {
|
||||
set pathToCheck [lpop pathsToCheck 0]
|
||||
foreach file [glob -nocomplain -directory $destroot$pathToCheck .* *] {
|
||||
if {[file tail $file] eq "." || [file tail $file] eq ".."} {
|
||||
continue
|
||||
}
|
||||
if {[string equal -length [string length $destroot] $destroot $file]} {
|
||||
# just double-checking that $destroot is a prefix, as is appropriate
|
||||
set dfile [file join / [string range $file [string length $destroot] end]]
|
||||
} else {
|
||||
throw MACPORTS "Unexpected filepath `${file}' while checking for mtree violations"
|
||||
}
|
||||
if {$dfile eq $prefix} {
|
||||
# we've found our prefix
|
||||
foreach pfile [glob -nocomplain -tails -directory $file .* *] {
|
||||
if {$pfile eq "." || $pfile eq ".."} {
|
||||
continue
|
||||
}
|
||||
if {$pfile ni $prefixPaths} {
|
||||
ui_warn "violation by [file join $dfile $pfile]"
|
||||
set mtree_violation "yes"
|
||||
}
|
||||
}
|
||||
} elseif {[string equal -length [expr {[string length $dfile] + 1}] $dfile/ $prefix]} {
|
||||
# we've found a subpath of our prefix
|
||||
lappend pathsToCheck $dfile
|
||||
} else {
|
||||
set dir_allowed no
|
||||
# these files are (at least potentially) outside of the prefix
|
||||
foreach dir [list $applications_dir $frameworks_dir /Library/LaunchAgents /Library/LaunchDaemons /Library/StartupItems] {
|
||||
if {[string equal -length [expr {[string length $dfile] + 1}] $dfile/ $dir]} {
|
||||
# it's a prefix of one of the allowed paths
|
||||
set dir_allowed yes
|
||||
break
|
||||
}
|
||||
}
|
||||
if {$dir_allowed} {
|
||||
lappend pathsToCheck $dfile
|
||||
} else {
|
||||
# not a prefix of an allowed path, so it's either the path itself or a violation
|
||||
switch -- $dfile \
|
||||
$applications_dir - \
|
||||
$frameworks_dir - \
|
||||
/Library/LaunchAgents - \
|
||||
/Library/LaunchDaemons - \
|
||||
/Library/StartupItems { ui_debug "port installs files in $dfile" } \
|
||||
default {
|
||||
ui_warn "violation by $dfile"
|
||||
set mtree_violation "yes"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# abort here only so all violations can be observed
|
||||
if { ${mtree_violation} ne "no" } {
|
||||
ui_warn "[format [msgcat::mc "%s violates the layout of the ports-filesystems!"] $subport]"
|
||||
ui_warn "Please fix or indicate this misbehavior (if it is intended), it will be an error in future releases!"
|
||||
# error "mtree violation!"
|
||||
}
|
||||
} else {
|
||||
ui_warn "[format [msgcat::mc "%s installs files outside the common directory structure."] $subport]"
|
||||
}
|
||||
|
||||
# Work around apparent filesystem bug.
|
||||
# https://trac.macports.org/ticket/67336
|
||||
if {![catch {fs_clone_capable $destroot} result] && $result} {
|
||||
global workpath
|
||||
ui_debug "Applying sparse file lseek bug workaround"
|
||||
try {
|
||||
fs-traverse -depth fullpath [list $destroot] {
|
||||
if {[file type $fullpath] eq "file" && [fileIsSparse $fullpath]} {
|
||||
ui_debug "Cloning $fullpath for workaround"
|
||||
clonefile $fullpath ${workpath}/.macports-sparse-workaround
|
||||
file delete ${workpath}/.macports-sparse-workaround
|
||||
if {![fileIsSparse $fullpath]} {
|
||||
ui_debug "$fullpath is no longer sparse"
|
||||
}
|
||||
}
|
||||
}
|
||||
} on error {eMessage} {
|
||||
ui_debug "Error while applying sparse file workaround: $eMessage"
|
||||
}
|
||||
}
|
||||
|
||||
# Restore umask
|
||||
umask $oldmask
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -0,0 +1,413 @@
|
||||
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
|
||||
#
|
||||
# Copyright (c) 2002 - 2003 Apple Inc.
|
||||
# Copyright (c) 2004 - 2005 Robert Shaw <rshaw@opendarwin.org>
|
||||
# Copyright (c) 2004-2005, 2007-2013 The MacPorts Project
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of Apple Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package provide portdestroot_run 1.0
|
||||
package require portutil 1.0
|
||||
|
||||
namespace eval portdestroot {
|
||||
|
||||
# Save old umask
|
||||
variable oldmask
|
||||
|
||||
proc destroot_start {args} {
|
||||
global UI_PREFIX prefix subport destroot os.platform destroot.clean portsharepath \
|
||||
destroot.umask destroot.asroot euid egid \
|
||||
applications_dir frameworks_dir
|
||||
variable oldmask
|
||||
|
||||
ui_notice "$UI_PREFIX [format [msgcat::mc "Staging %s into destroot"] ${subport}]"
|
||||
|
||||
# start gsoc08-privileges
|
||||
if { [getuid] == 0 && [geteuid] != 0 } {
|
||||
# if started with sudo but have dropped the privileges
|
||||
ui_debug "Can't run destroot under sudo without elevated privileges (due to mtree)."
|
||||
ui_debug "Run destroot without sudo to avoid root privileges."
|
||||
ui_debug "Going to escalate privileges back to root."
|
||||
seteuid $euid
|
||||
setegid $egid
|
||||
ui_debug "euid changed to: [geteuid]. egid changed to: [getegid]."
|
||||
}
|
||||
|
||||
if { [tbool destroot.asroot] && [getuid] != 0 } {
|
||||
return -code error "You cannot run this port without root privileges. You need to re-run with 'sudo port'.";
|
||||
}
|
||||
|
||||
# end gsoc08-privileges
|
||||
|
||||
set oldmask [umask ${destroot.umask}]
|
||||
set mtree [findBinary mtree ${::portutil::autoconf::mtree_path}]
|
||||
|
||||
if { ${destroot.clean} eq "yes" } {
|
||||
delete "${destroot}"
|
||||
}
|
||||
|
||||
file mkdir "${destroot}"
|
||||
if { ${os.platform} eq "darwin" } {
|
||||
system -W ${destroot} "${mtree} -e -U -f [shellescape [file join ${portsharepath} install macosx.mtree]]"
|
||||
file mkdir "${destroot}${applications_dir}"
|
||||
file mkdir "${destroot}${frameworks_dir}"
|
||||
}
|
||||
file mkdir "${destroot}${prefix}"
|
||||
system -W ${destroot}${prefix} "${mtree} -e -U -f [shellescape [file join ${portsharepath} install prefix.mtree]]"
|
||||
|
||||
# Create startup-scripts/items
|
||||
portstartupitem::startupitem_create
|
||||
}
|
||||
|
||||
proc destroot_main {args} {
|
||||
global system_options
|
||||
if {$system_options(clonebin_path) ne ""} {
|
||||
global env
|
||||
set saved_path $env(PATH)
|
||||
set env(PATH) $system_options(clonebin_path):$env(PATH)
|
||||
}
|
||||
try {
|
||||
command_exec -callback portprogress::target_progress_callback destroot
|
||||
} finally {
|
||||
if {[info exists saved_path]} {
|
||||
set env(PATH) $saved_path
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
proc destroot_finish {args} {
|
||||
global UI_PREFIX destroot prefix subport destroot.violate_mtree \
|
||||
applications_dir frameworks_dir destroot.keepdirs \
|
||||
destroot.delete_la_files install.user install.group \
|
||||
macportsuser
|
||||
variable oldmask
|
||||
|
||||
foreach fileToDelete {share/info/dir lib/charset.alias} {
|
||||
if {[file exists "${destroot}${prefix}/${fileToDelete}"]} {
|
||||
ui_debug "Deleting stray ${fileToDelete} file."
|
||||
file delete "${destroot}${prefix}/${fileToDelete}"
|
||||
}
|
||||
}
|
||||
|
||||
# Prevent overlinking due to glibtool .la files: https://trac.macports.org/ticket/38010
|
||||
ui_debug "Fixing glibtool .la files in destroot for ${subport}"
|
||||
if {[getuid] == 0} {
|
||||
set macports_uid [name_to_uid $macportsuser]
|
||||
set macports_gid [uname_to_gid $macportsuser]
|
||||
set fix_ownership 1
|
||||
} else {
|
||||
set fix_ownership 0
|
||||
}
|
||||
fs-traverse -depth fullpath [list $destroot] {
|
||||
file lstat $fullpath statinfo
|
||||
# Ensure installed files are not owned by the unprivileged account
|
||||
if {$fix_ownership && ($statinfo(uid) == $macports_uid || $statinfo(gid) == $macports_gid)} {
|
||||
if {$statinfo(uid) == $macports_uid} {
|
||||
ui_debug "Changing owner to ${install.user} for $fullpath"
|
||||
set new_owner ${install.user}
|
||||
} else {
|
||||
# only group needs to be changed
|
||||
set new_owner -1
|
||||
}
|
||||
if {$statinfo(gid) == $macports_gid} {
|
||||
ui_debug "Changing group to ${install.group} for $fullpath"
|
||||
set new_group ${install.group}
|
||||
} else {
|
||||
# only owner needs to be changed
|
||||
set new_group -1
|
||||
}
|
||||
# Changing owner may also change permissions, so we restore
|
||||
# them afterwards. 'file attributes' doesn't work on links
|
||||
# (it operates on the link target instead) but links should
|
||||
# not have setuid/setgid bits set anyway.
|
||||
if {$statinfo(type) ne "link"} {
|
||||
set saved_perms [file attributes $fullpath -permissions]
|
||||
}
|
||||
lchown $fullpath $new_owner $new_group
|
||||
if {$statinfo(type) ne "link"} {
|
||||
file attributes $fullpath -permissions $saved_perms
|
||||
}
|
||||
}
|
||||
if {[file extension $fullpath] eq ".la" && $statinfo(type) in {file link}} {
|
||||
if {$statinfo(type) eq "link" && [file pathtype [file link $fullpath]] ne "relative"} {
|
||||
# prepend $destroot to target of absolute symlinks
|
||||
set checkpath ${destroot}[file link $fullpath]
|
||||
} else {
|
||||
set checkpath $fullpath
|
||||
}
|
||||
# Make sure it is from glibtool ... "a libtool library file" will appear in the first line
|
||||
set is_la_file 0
|
||||
if {![catch {open $checkpath} fp]} {
|
||||
if {[gets $fp line] > 0 && [string first "a libtool library file" $line] != -1} {
|
||||
set is_la_file 1
|
||||
}
|
||||
catch {close $fp}
|
||||
} else {
|
||||
ui_debug "Failed to open $checkpath"
|
||||
}
|
||||
if {$is_la_file} {
|
||||
if {${destroot.delete_la_files}} {
|
||||
ui_debug "Removing [file tail $fullpath]"
|
||||
file delete ${fullpath}
|
||||
} elseif {$statinfo(type) eq "file"} {
|
||||
ui_debug "Clearing dependency_libs in [file tail $fullpath]"
|
||||
reinplace -q "/dependency_libs/ s/'.*'/''/" ${fullpath}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Prune empty directories in ${destroot}
|
||||
package require fileutil
|
||||
foreach path ${destroot.keepdirs} {
|
||||
# Prepend $destroot if $path isn't already inside it
|
||||
set path [::fileutil::jail $destroot $path]
|
||||
if {![file isdirectory ${path}]} {
|
||||
xinstall -m 0755 -d ${path}
|
||||
}
|
||||
if {![file exists ${path}/.turd_${subport}]} {
|
||||
xinstall -c -m 0644 /dev/null ${path}/.turd_${subport}
|
||||
}
|
||||
}
|
||||
fs-traverse -depth dir [list ${destroot}] {
|
||||
if {[file type $dir] eq "directory"} {
|
||||
catch {file delete $dir}
|
||||
}
|
||||
}
|
||||
|
||||
if {![file isdirectory ${destroot}]} {
|
||||
ui_error "No files have been installed in the destroot directory!"
|
||||
ui_error "Please make sure that this software supports\
|
||||
'make install DESTDIR=\${destroot}' or implement an\
|
||||
alternative destroot mechanism in the Portfile."
|
||||
ui_error "Files might have been installed directly into your system,\
|
||||
check before proceeding."
|
||||
return -code error "Staging $subport into destroot failed"
|
||||
}
|
||||
|
||||
# Compress all manpages with gzip (instead)
|
||||
set manpath ${destroot}${prefix}/share/man
|
||||
if {[file isdirectory ${manpath}] && [file type ${manpath}] eq "directory"} {
|
||||
ui_info "$UI_PREFIX [format [msgcat::mc "Compressing man pages for %s"] ${subport}]"
|
||||
|
||||
set gzip [findBinary gzip ${::portutil::autoconf::gzip_path}]
|
||||
set gunzip "$gzip -d"
|
||||
set bunzip2 "[findBinary bzip2 ${::portutil::autoconf::bzip2_path}] -d"
|
||||
|
||||
set found 0
|
||||
set manlinks [list]
|
||||
set mandir_re {^(cat|man)(.)$}
|
||||
|
||||
foreach mandir [readdir "${manpath}"] {
|
||||
if {![regexp ${mandir_re} ${mandir} match ignore manindex]} { continue }
|
||||
set gzfile_re "^(.*\[.\]${manindex}\[a-z\]*)\[.\]gz\$"
|
||||
set bz2file_re "^(.*\[.\]${manindex}\[a-z\]*)\[.\]bz2\$"
|
||||
set normalfile_re "\[.\]${manindex}\[a-z\]*\$"
|
||||
set mandirpath [file join ${manpath} ${mandir}]
|
||||
if {[file isdirectory ${mandirpath}] && [file type ${mandirpath}] eq "directory"} {
|
||||
ui_debug "Scanning ${mandir}"
|
||||
foreach manfile [readdir ${mandirpath}] {
|
||||
set manfilepath [file join ${mandirpath} ${manfile}]
|
||||
if {[file isfile ${manfilepath}] && [file type ${manfilepath}] eq "file"} {
|
||||
if {[regexp ${gzfile_re} ${manfile} gzfile manfile]} {
|
||||
set found 1
|
||||
system -W ${manpath} \
|
||||
"$gunzip -f [shellescape [file join ${mandir} ${gzfile}]] && \
|
||||
$gzip -9vnf [shellescape [file join ${mandir} ${manfile}]]"
|
||||
} elseif {[regexp ${bz2file_re} ${manfile} bz2file manfile]} {
|
||||
set found 1
|
||||
system -W ${manpath} \
|
||||
"$bunzip2 -f [shellescape [file join ${mandir} ${bz2file}]] && \
|
||||
$gzip -9vnf [shellescape [file join ${mandir} ${manfile}]]"
|
||||
} elseif {[regexp ${normalfile_re} ${manfile}]} {
|
||||
set found 1
|
||||
system -W ${manpath} \
|
||||
"$gzip -9vnf [shellescape [file join ${mandir} ${manfile}]]"
|
||||
}
|
||||
set gzmanfile ${manfile}.gz
|
||||
set gzmanfilepath [file join ${mandirpath} ${gzmanfile}]
|
||||
if {[file exists ${gzmanfilepath}]} {
|
||||
set desired 00444
|
||||
set current [file attributes ${gzmanfilepath} -permissions]
|
||||
if {$current != $desired} {
|
||||
ui_info "[file join ${mandir} ${gzmanfile}]: changing permissions from $current to $desired"
|
||||
file attributes ${gzmanfilepath} -permissions $desired
|
||||
}
|
||||
}
|
||||
} elseif {[file type ${manfilepath}] eq "link"} {
|
||||
lappend manlinks [file join ${mandir} ${manfile}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if {$found == 1} {
|
||||
# check man page links and rename/repoint them if necessary
|
||||
set gzext_re "\[.\]gz\$"
|
||||
foreach manlink $manlinks {
|
||||
set manlinkpath [file join $manpath $manlink]
|
||||
# if link destination is not gzipped, check it
|
||||
set manlinksrc [file readlink $manlinkpath]
|
||||
if {![regexp ${gzext_re} ${manlinksrc}]} {
|
||||
set mandir [file dirname $manlink]
|
||||
set mandirpath [file join $manpath $mandir]
|
||||
if {[catch {pwd} oldpwd]} {
|
||||
set oldpwd {}
|
||||
}
|
||||
if {[catch {_cd $mandirpath} err]} {
|
||||
puts $err
|
||||
return
|
||||
}
|
||||
# if link source is an absolute path, check for it under destroot
|
||||
set mls_check "$manlinksrc"
|
||||
if {[file pathtype $mls_check] eq "absolute"} {
|
||||
set mls_check "${destroot}${mls_check}"
|
||||
}
|
||||
# if gzipped destination exists, fix link
|
||||
if {[file isfile ${mls_check}.gz]} {
|
||||
# if actual link name does not end with gz, rename it
|
||||
if {![regexp ${gzext_re} ${manlink}]} {
|
||||
ui_debug "renaming link: $manlink to ${manlink}.gz"
|
||||
file rename $manlinkpath ${manlinkpath}.gz
|
||||
set manlink ${manlink}.gz
|
||||
set manlinkpath [file join $manpath $manlink]
|
||||
}
|
||||
# repoint the link
|
||||
ui_debug "repointing link: $manlink from $manlinksrc to ${manlinksrc}.gz"
|
||||
file delete $manlinkpath
|
||||
ln -s "${manlinksrc}.gz" "${manlinkpath}"
|
||||
}
|
||||
if {$oldpwd ne {}} {
|
||||
_cd $oldpwd
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ui_debug "No man pages found to compress."
|
||||
}
|
||||
}
|
||||
|
||||
# test for violations of mtree
|
||||
if { ${destroot.violate_mtree} ne "yes" } {
|
||||
ui_debug "checking for mtree violations"
|
||||
set mtree_violation "no"
|
||||
|
||||
set prefixPaths [list bin etc include lib libexec sbin share src var www Applications Developer Library]
|
||||
|
||||
set pathsToCheck [list /]
|
||||
while {[llength $pathsToCheck] > 0} {
|
||||
set pathToCheck [lpop pathsToCheck 0]
|
||||
foreach file [glob -nocomplain -directory $destroot$pathToCheck .* *] {
|
||||
if {[file tail $file] eq "." || [file tail $file] eq ".."} {
|
||||
continue
|
||||
}
|
||||
if {[string equal -length [string length $destroot] $destroot $file]} {
|
||||
# just double-checking that $destroot is a prefix, as is appropriate
|
||||
set dfile [file join / [string range $file [string length $destroot] end]]
|
||||
} else {
|
||||
throw MACPORTS "Unexpected filepath `${file}' while checking for mtree violations"
|
||||
}
|
||||
if {$dfile eq $prefix} {
|
||||
# we've found our prefix
|
||||
foreach pfile [glob -nocomplain -tails -directory $file .* *] {
|
||||
if {$pfile eq "." || $pfile eq ".."} {
|
||||
continue
|
||||
}
|
||||
if {$pfile ni $prefixPaths} {
|
||||
ui_warn "violation by [file join $dfile $pfile]"
|
||||
set mtree_violation "yes"
|
||||
}
|
||||
}
|
||||
} elseif {[string equal -length [expr {[string length $dfile] + 1}] $dfile/ $prefix]} {
|
||||
# we've found a subpath of our prefix
|
||||
lappend pathsToCheck $dfile
|
||||
} else {
|
||||
set dir_allowed no
|
||||
# these files are (at least potentially) outside of the prefix
|
||||
foreach dir [list $applications_dir $frameworks_dir /Library/LaunchAgents /Library/LaunchDaemons /Library/StartupItems] {
|
||||
if {[string equal -length [expr {[string length $dfile] + 1}] $dfile/ $dir]} {
|
||||
# it's a prefix of one of the allowed paths
|
||||
set dir_allowed yes
|
||||
break
|
||||
}
|
||||
}
|
||||
if {$dir_allowed} {
|
||||
lappend pathsToCheck $dfile
|
||||
} else {
|
||||
# not a prefix of an allowed path, so it's either the path itself or a violation
|
||||
switch -- $dfile \
|
||||
$applications_dir - \
|
||||
$frameworks_dir - \
|
||||
/Library/LaunchAgents - \
|
||||
/Library/LaunchDaemons - \
|
||||
/Library/StartupItems { ui_debug "port installs files in $dfile" } \
|
||||
default {
|
||||
ui_warn "violation by $dfile"
|
||||
set mtree_violation "yes"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# abort here only so all violations can be observed
|
||||
if { ${mtree_violation} ne "no" } {
|
||||
ui_warn "[format [msgcat::mc "%s violates the layout of the ports-filesystems!"] $subport]"
|
||||
ui_warn "Please fix or indicate this misbehavior (if it is intended), it will be an error in future releases!"
|
||||
# error "mtree violation!"
|
||||
}
|
||||
} else {
|
||||
ui_warn "[format [msgcat::mc "%s installs files outside the common directory structure."] $subport]"
|
||||
}
|
||||
|
||||
# Work around apparent filesystem bug.
|
||||
# https://trac.macports.org/ticket/67336
|
||||
if {![catch {fs_clone_capable $destroot} result] && $result} {
|
||||
global workpath
|
||||
ui_debug "Applying sparse file lseek bug workaround"
|
||||
try {
|
||||
fs-traverse -depth fullpath [list $destroot] {
|
||||
if {[file type $fullpath] eq "file" && [fileIsSparse $fullpath]} {
|
||||
ui_debug "Cloning $fullpath for workaround"
|
||||
clonefile $fullpath ${workpath}/.macports-sparse-workaround
|
||||
file delete ${workpath}/.macports-sparse-workaround
|
||||
if {![fileIsSparse $fullpath]} {
|
||||
ui_debug "$fullpath is no longer sparse"
|
||||
}
|
||||
}
|
||||
}
|
||||
} on error {eMessage} {
|
||||
ui_debug "Error while applying sparse file workaround: $eMessage"
|
||||
}
|
||||
}
|
||||
|
||||
# Restore umask
|
||||
umask $oldmask
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,142 +1,16 @@
|
||||
# et:ts=4
|
||||
# portdistcheck.tcl
|
||||
#
|
||||
# Copyright (c) 2007-2011, 2014, 2016 The MacPorts Project
|
||||
# Copyright (c) 2005-2006 Paul Guyot <pguyot@kallisys.net>,
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of The MacPorts Project nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
|
||||
|
||||
package provide portdistcheck 1.0
|
||||
package require portutil 1.0
|
||||
package require portfetch 1.0
|
||||
|
||||
set org.macports.distcheck [target_new org.macports.distcheck portdistcheck::distcheck_main]
|
||||
target_runtype ${org.macports.distcheck} always
|
||||
target_state ${org.macports.distcheck} no
|
||||
target_provides ${org.macports.distcheck} distcheck
|
||||
target_requires ${org.macports.distcheck} main
|
||||
|
||||
namespace eval portdistcheck {
|
||||
}
|
||||
target_runpkg ${org.macports.distcheck} portdistcheck_run
|
||||
|
||||
# define options
|
||||
options distcheck.type
|
||||
|
||||
# defaults
|
||||
default distcheck.type moddate
|
||||
|
||||
proc portdistcheck::distcheck_main {args} {
|
||||
global distcheck.type fetch.type fetch.ignore_sslcert \
|
||||
subport portpath
|
||||
|
||||
set port_moddate [file mtime ${portpath}/Portfile]
|
||||
|
||||
ui_debug "Portfile modification date is [clock format $port_moddate]"
|
||||
|
||||
set curl_options [list]
|
||||
if {[tbool fetch.ignore_sslcert]} {
|
||||
lappend curl_options "--ignore-ssl-cert"
|
||||
}
|
||||
|
||||
# Check the distfiles if it's a regular fetch phase.
|
||||
if {${distcheck.type} ne "none"
|
||||
&& ${fetch.type} eq "standard"} {
|
||||
# portfetch 1.0::checkfiles sets fetch_urls list.
|
||||
set fetch_urls [list]
|
||||
portfetch::checkfiles fetch_urls
|
||||
set totalsize 0
|
||||
|
||||
global portfetch::urlmap
|
||||
# Check all the files.
|
||||
foreach {url_var distfile} $fetch_urls {
|
||||
if {![info exists urlmap($url_var)]} {
|
||||
ui_error [format [msgcat::mc "No defined site for tag: %s, using master_sites"] $url_var]
|
||||
set urlmap($url_var) $master_sites
|
||||
}
|
||||
if {${distcheck.type} eq "moddate"} {
|
||||
set count 0
|
||||
foreach site $urlmap($url_var) {
|
||||
ui_debug [format [msgcat::mc "Checking %s from %s"] $distfile $site]
|
||||
set file_url [portfetch::assemble_url $site $distfile]
|
||||
macports_try -pass_signal {
|
||||
set urlnewer [curl isnewer {*}$curl_options $file_url $port_moddate]
|
||||
if {$urlnewer} {
|
||||
ui_warn "port $subport: $file_url is newer than Portfile"
|
||||
}
|
||||
incr count
|
||||
} on error {eMessage} {
|
||||
ui_debug [msgcat::mc "couldn't fetch %s for %s (%s)" $file_url $subport $eMessage]
|
||||
}
|
||||
}
|
||||
if {$count == 0} {
|
||||
ui_error "no mirror had $distfile for $subport"
|
||||
}
|
||||
} elseif {${distcheck.type} eq "filesize"} {
|
||||
set count 0
|
||||
foreach site $urlmap($url_var) {
|
||||
ui_debug [format [msgcat::mc "Checking %s from %s"] $distfile $site]
|
||||
set file_url [portfetch::assemble_url $site $distfile]
|
||||
macports_try -pass_signal {
|
||||
set urlsize [curl getsize {*}$curl_options $file_url]
|
||||
incr count
|
||||
if {$urlsize > 0} {
|
||||
ui_info "port $subport: $distfile $urlsize bytes"
|
||||
incr totalsize $urlsize
|
||||
break
|
||||
}
|
||||
} on error {eMessage} {
|
||||
ui_debug [msgcat::mc "couldn't fetch %s for %s (%s)" $file_url $subport $eMessage]
|
||||
}
|
||||
}
|
||||
if {$count == 0} {
|
||||
ui_error "no mirror had $distfile for $subport"
|
||||
}
|
||||
} else {
|
||||
ui_error "unknown distcheck.type ${distcheck.type}"
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if {${distcheck.type} eq "filesize" && $totalsize > 0} {
|
||||
if {$totalsize < 1024} {
|
||||
set size $totalsize
|
||||
set humansize "${size}"
|
||||
} elseif {$totalsize < 1024*1024} {
|
||||
set size [expr {$totalsize / 1024.0}]
|
||||
set humansize [format "%.1fK" $size]
|
||||
} elseif {$totalsize < 1024*1024*1024} {
|
||||
set size [expr {$totalsize / (1024.0*1024.0)}]
|
||||
set humansize [format "%.1fM" $size]
|
||||
} else {
|
||||
set size [expr {$totalsize / (1024.0*1024.0*1024.0)}]
|
||||
set humansize [format "%.1fG" $size]
|
||||
}
|
||||
ui_msg "$subport: $humansize"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
|
||||
#
|
||||
# Copyright (c) 2007-2011, 2014, 2016 The MacPorts Project
|
||||
# Copyright (c) 2005-2006 Paul Guyot <pguyot@kallisys.net>,
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of The MacPorts Project nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package provide portdistcheck_run 1.0
|
||||
package require portutil 1.0
|
||||
package require portfetch 1.0
|
||||
package require portfetch_run 1.0
|
||||
|
||||
namespace eval portdistcheck {
|
||||
|
||||
proc distcheck_main {args} {
|
||||
global distcheck.type fetch.type fetch.ignore_sslcert \
|
||||
subport portpath
|
||||
|
||||
set port_moddate [file mtime ${portpath}/Portfile]
|
||||
|
||||
ui_debug "Portfile modification date is [clock format $port_moddate]"
|
||||
|
||||
set curl_options [list]
|
||||
if {[tbool fetch.ignore_sslcert]} {
|
||||
lappend curl_options "--ignore-ssl-cert"
|
||||
}
|
||||
|
||||
# Check the distfiles if it's a regular fetch phase.
|
||||
if {${distcheck.type} ne "none"
|
||||
&& ${fetch.type} eq "standard"} {
|
||||
# portfetch 1.0::checkfiles sets fetch_urls list.
|
||||
set fetch_urls [list]
|
||||
portfetch::checkfiles fetch_urls
|
||||
set totalsize 0
|
||||
|
||||
global portfetch::urlmap
|
||||
# Check all the files.
|
||||
foreach {url_var distfile} $fetch_urls {
|
||||
if {![info exists urlmap($url_var)]} {
|
||||
ui_error [format [msgcat::mc "No defined site for tag: %s, using master_sites"] $url_var]
|
||||
set urlmap($url_var) $master_sites
|
||||
}
|
||||
if {${distcheck.type} eq "moddate"} {
|
||||
set count 0
|
||||
foreach site $urlmap($url_var) {
|
||||
ui_debug [format [msgcat::mc "Checking %s from %s"] $distfile $site]
|
||||
set file_url [portfetch::assemble_url $site $distfile]
|
||||
macports_try -pass_signal {
|
||||
set urlnewer [curl isnewer {*}$curl_options $file_url $port_moddate]
|
||||
if {$urlnewer} {
|
||||
ui_warn "port $subport: $file_url is newer than Portfile"
|
||||
}
|
||||
incr count
|
||||
} on error {eMessage} {
|
||||
ui_debug [msgcat::mc "couldn't fetch %s for %s (%s)" $file_url $subport $eMessage]
|
||||
}
|
||||
}
|
||||
if {$count == 0} {
|
||||
ui_error "no mirror had $distfile for $subport"
|
||||
}
|
||||
} elseif {${distcheck.type} eq "filesize"} {
|
||||
set count 0
|
||||
foreach site $urlmap($url_var) {
|
||||
ui_debug [format [msgcat::mc "Checking %s from %s"] $distfile $site]
|
||||
set file_url [portfetch::assemble_url $site $distfile]
|
||||
macports_try -pass_signal {
|
||||
set urlsize [curl getsize {*}$curl_options $file_url]
|
||||
incr count
|
||||
if {$urlsize > 0} {
|
||||
ui_info "port $subport: $distfile $urlsize bytes"
|
||||
incr totalsize $urlsize
|
||||
break
|
||||
}
|
||||
} on error {eMessage} {
|
||||
ui_debug [msgcat::mc "couldn't fetch %s for %s (%s)" $file_url $subport $eMessage]
|
||||
}
|
||||
}
|
||||
if {$count == 0} {
|
||||
ui_error "no mirror had $distfile for $subport"
|
||||
}
|
||||
} else {
|
||||
ui_error "unknown distcheck.type ${distcheck.type}"
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if {${distcheck.type} eq "filesize" && $totalsize > 0} {
|
||||
if {$totalsize < 1024} {
|
||||
set size $totalsize
|
||||
set humansize "${size}"
|
||||
} elseif {$totalsize < 1024*1024} {
|
||||
set size [expr {$totalsize / 1024.0}]
|
||||
set humansize [format "%.1fK" $size]
|
||||
} elseif {$totalsize < 1024*1024*1024} {
|
||||
set size [expr {$totalsize / (1024.0*1024.0)}]
|
||||
set humansize [format "%.1fM" $size]
|
||||
} else {
|
||||
set size [expr {$totalsize / (1024.0*1024.0*1024.0)}]
|
||||
set humansize [format "%.1fG" $size]
|
||||
}
|
||||
ui_msg "$subport: $humansize"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user