@@ -1650,54 +1650,6 @@ proc execShAndGetEnv {elt_ignored_list shell script args} {
16501650 }
16511651}
16521652
1653- # split the range of a variable value to prepend or append into a
1654- # directory list for sh-to-mod: a directory found several times in this
1655- # list is not de-duplicated, as it is genuinely meant to be added at each
1656- # of these positions in the resulting value. Whether de-duplication would
1657- # have dropped an entry is also reported, to guide the --duplicates
1658- # option decision made in mkPathAddModCmd
1659- proc splitPathAddList {rangeval delim} {
1660- set dirlist [ split $rangeval $delim ]
1661- set diruniq [ list ]
1662- lappendNoDup diruniq {*}$dirlist
1663- set dupbylen [ expr {[llength $dirlist ] != [ llength $diruniq ] }]
1664- # an empty element is added
1665- if {![ llength $dirlist ] } {
1666- lappend dirlist {}
1667- }
1668- return [ list $dirlist $dupbylen ]
1669- }
1670-
1671- # build the prepend-path or append-path modulefile command adding dirlist
1672- # to variable name for sh-to-mod. --duplicates is set on this command
1673- # when one of its entries is genuinely meant to end up at this specific
1674- # position in the resulting value, so it is not silently absorbed by
1675- # prepend-path/append-path's default dedup behavior, nor relocated by the
1676- # path_entry_reorder configuration option: this is the case when this
1677- # entry is already found in befval, was found several times in dirlist
1678- # prior de-duplication (dupbylen), or is also found in the list of
1679- # entries added on the other side of the value (dupacross)
1680- proc mkPathAddModCmd {cmdname dirlist dupbylen dupacross delim pathsep\
1681- befval name} {
1682- set dupopt [ list ]
1683- if {$dupacross || $dupbylen } {
1684- set dupopt [ list --duplicates]
1685- } else {
1686- foreach dir $dirlist {
1687- if {$dir in [ split $befval $delim ] } {
1688- set dupopt [ list --duplicates]
1689- break
1690- }
1691- }
1692- }
1693- set modcmd [ list $cmdname {*}$dupopt ]
1694- if {$delim ne $pathsep } {
1695- lappend modcmd -d $delim
1696- }
1697- lappend modcmd $name
1698- return [ list {*}$modcmd {*}$dirlist ]
1699- }
1700-
17011653# execute script with args through shell and convert environment changes into
17021654# corresponding modulefile commands
17031655proc sh-to-mod {elt_ignored_list args} {
@@ -1724,71 +1676,76 @@ proc sh-to-mod {elt_ignored_list args} {
17241676 foreach name $diff {
17251677 if {$name ni $ignvarlist && ![ string equal -length 10 $name \
17261678 __MODULES_] } {
1679+ set idx [ string first $varbef($name) $varaft($name) ]
1680+ set doprepend [ expr {$idx > 0}]
1681+ if {$doprepend } {
1682+ # check from the end to get the largest chunk to prepend
1683+ set idx [ string last $varbef($name) $varaft($name) ]
1684+ # get delimiter from char found between new and existing value
1685+ set predelim [ string index $varaft($name) $idx -1]
1686+ set delim $predelim
1687+ }
1688+ set appdelim_idx [ expr {$idx + [string length $varbef($name) ] }]
1689+ set doappend [ expr {$appdelim_idx < [string length $varaft($name) ] }]
1690+ if {$doappend } {
1691+ set appdelim [ string index $varaft($name) $appdelim_idx ]
1692+ set delim $appdelim
1693+ }
17271694 # new value is totally different (also consider a bare ':' as a
17281695 # totally different value to avoid erroneous matches)
1729- if {$varbef($name) eq $pathsep || [ set idx [string first\
1730- $varbef($name) $varaft($name) ] ] == -1} {
1696+ # if content must both be prepended and appended but each side uses a
1697+ # different delimiter character, consider new value totally different
1698+ if {$varbef($name) eq $pathsep || $idx == -1 || ($doprepend &&\
1699+ $doappend && $predelim ne $appdelim )} {
17311700 lappend modcontent [ list setenv $name $varaft($name) ]
17321701 } else {
1733- set doprepend [ expr {$idx > 0}]
1702+ set alllist [ list ]
1703+ # de-dup pre-existing list to correctly determine if new dup added
1704+ lappendNoDup alllist {*}[ split $varbef($name) $delim ]
1705+ set addmodcmd [ list ]
1706+ # content should be prepended
17341707 if {$doprepend } {
1735- # check from the end to get the largest chunk to prepend
1736- set idx [ string last $varbef($name) $varaft($name) ]
1737- # get delimiter from char found between new and existing value
1738- set predelim [ string index $varaft($name) $idx -1]
1708+ set prelist [ split [string range $varaft($name) 0 $idx -2] \
1709+ $delim ]
1710+ # an empty element is added
1711+ if {![ llength $prelist ] } {
1712+ lappend prelist {}
1713+ }
1714+ lappend alllist {*}$prelist
1715+ lappend addmodcmd prepend-path $prelist
17391716 }
1740- set doappend [ expr {($idx + [string length $varbef($name) ] ) <\
1741- [ string length $varaft($name) ] }]
1717+ # content should be appended
17421718 if {$doappend } {
1743- set appdelim [ string index $varaft($name) $idx +[string \
1744- length $varbef($name) ] ]
1745- }
1746-
1747- # if content must both be prepended and appended but each side
1748- # uses a different delimiter character, the change cannot be
1749- # expressed as a coherent pair of path-manipulation commands,
1750- # since each delimiter implies a different, incompatible split
1751- # of the value: fall back to a plain setenv to correctly
1752- # capture the new value
1753- if {$doprepend && $doappend && $predelim ne $appdelim } {
1754- lappend modcontent [ list setenv $name $varaft($name) ]
1755- } else {
1756- # content should be prepended
1757- if {$doprepend } {
1758- lassign [ splitPathAddList [string range $varaft($name) \
1759- 0 $idx -2] $predelim ] prelist predupbylen
1760- }
1761- # content should be appended
1762- if {$doappend } {
1763- lassign [ splitPathAddList [string range $varaft($name) \
1764- [expr {$idx + [string length $varbef($name) ] + 1}]\
1765- end] $appdelim ] applist appdupbylen
1719+ set applist [ split [string range $varaft($name) [expr \
1720+ {$appdelim_idx + 1}] end] $delim ]
1721+ # an empty element is added
1722+ if {![ llength $applist ] } {
1723+ lappend applist {}
17661724 }
1725+ lappend alllist {*}$applist
1726+ lappend addmodcmd append-path $applist
1727+ }
17671728
1768- # a directory found in both the prepended and appended
1769- # entries is also genuinely meant to end up at each of
1770- # these positions in the resulting value: this is passed
1771- # on to mkPathAddModCmd along with each side's own
1772- # dupbylen, to decide whether --duplicates should be set
1773- set dupacross 0
1774- if {$doprepend && $doappend } {
1775- foreach dir $prelist {
1776- if {$dir in $applist } {
1777- set dupacross 1
1778- break
1779- }
1780- }
1781- }
1782- if {$doprepend } {
1783- lappend modcontent [ mkPathAddModCmd prepend-path\
1784- $prelist $predupbylen $dupacross $predelim $pathsep \
1785- $varbef($name) $name ]
1729+ # if a directory is found several times in prepended or appended
1730+ # list, or across both list, or already in pre-existing value:
1731+ # should not be de-duplicated by prepend-path/append-path's
1732+ # default behavior, nor relocated by the path_entry_reorder
1733+ # configuration option. a plain membership test (rather than
1734+ # merging pre-existing value into alllist) is required here, as
1735+ # merging would let lappendNoDup silently skip an entry already
1736+ # in alllist, hiding the very overlap this check looks for
1737+ set isdup [ isDupInList $alllist ]
1738+
1739+ foreach {cmd addlist} $addmodcmd {
1740+ set addcmd [ list $cmd ]
1741+ if {$isdup } {
1742+ lappend addcmd --duplicates
17861743 }
1787- if {$doappend } {
1788- lappend modcontent [ mkPathAddModCmd append-path\
1789- $applist $appdupbylen $dupacross $appdelim $pathsep \
1790- $varbef($name) $name ]
1744+ if {$delim ne $pathsep } {
1745+ lappend addcmd -d $delim
17911746 }
1747+ lappend addcmd $name {*}$addlist
1748+ lappend modcontent $addcmd
17921749 }
17931750 }
17941751 }
0 commit comments