source: branches/gsoc13-tests/src/package1.0/portunarchive.tcl @ 139170

Last change on this file since 139170 was 111323, checked in by marius@…, 7 years ago

Merge from trunk.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 11.3 KB
Line 
1# -*- 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
2# portunarchive.tcl
3# $Id: portunarchive.tcl 111323 2013-09-18 23:11:02Z marius@macports.org $
4#
5# Copyright (c) 2005, 2007-2012 The MacPorts Project
6# Copyright (c) 2004 Robert Shaw <rshaw@opendarwin.org>
7# Copyright (c) 2002 - 2003 Apple Inc.
8# All rights reserved.
9#
10# Redistribution and use in source and binary forms, with or without
11# modification, are permitted provided that the following conditions
12# are met:
13# 1. Redistributions of source code must retain the above copyright
14#    notice, this list of conditions and the following disclaimer.
15# 2. Redistributions in binary form must reproduce the above copyright
16#    notice, this list of conditions and the following disclaimer in the
17#    documentation and/or other materials provided with the distribution.
18# 3. Neither the name of Apple Inc. nor the names of its contributors
19#    may be used to endorse or promote products derived from this software
20#    without specific prior written permission.
21#
22# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32# POSSIBILITY OF SUCH DAMAGE.
33#
34
35package provide portunarchive 1.0
36package require portutil 1.0
37
38set org.macports.unarchive [target_new org.macports.unarchive portunarchive::unarchive_main]
39target_runtype ${org.macports.unarchive} always
40target_init ${org.macports.unarchive} portunarchive::unarchive_init
41target_provides ${org.macports.unarchive} unarchive
42target_requires ${org.macports.unarchive} main archivefetch
43target_prerun ${org.macports.unarchive} portunarchive::unarchive_start
44target_postrun ${org.macports.unarchive} portunarchive::unarchive_finish
45
46namespace eval portunarchive {
47}
48
49# defaults
50default unarchive.dir {${destpath}}
51default unarchive.env {}
52default unarchive.cmd {}
53default unarchive.pre_args {}
54default unarchive.args {}
55default unarchive.post_args {}
56
57default unarchive.type {}
58default unarchive.file {}
59default unarchive.path {}
60default unarchive.skip 0
61
62set_ui_prefix
63
64proc portunarchive::unarchive_init {args} {
65    global target_state_fd unarchive.skip destroot \
66           ports_force ports_source_only ports_binary_only \
67           subport version revision portvariants \
68           unarchive.type unarchive.file unarchive.path
69
70    # Determine if unarchive should be skipped
71    set skipped 0
72    if {[check_statefile target org.macports.unarchive $target_state_fd]} {
73        return 0
74    } elseif {[info exists ports_source_only] && $ports_source_only == "yes"} {
75        ui_debug "Skipping unarchive ($subport) since source-only is set"
76        set skipped 1
77    } elseif {[check_statefile target org.macports.destroot $target_state_fd]
78              && [file isdirectory $destroot]} {
79        ui_debug "Skipping unarchive ($subport) since destroot completed"
80        set skipped 1
81    } elseif {[info exists ports_force] && $ports_force == "yes"} {
82        ui_debug "Skipping unarchive ($subport) since force is set"
83        set skipped 1
84    } else {
85        set unarchive.path [find_portarchive_path]
86        set unarchive.file [file tail ${unarchive.path}]
87        set unarchive.type [string range [file extension ${unarchive.file}] 1 end]
88        if {${unarchive.path} != ""} {
89            ui_debug "Found [string toupper ${unarchive.type}] archive: ${unarchive.path}"
90        } else {
91            if {[info exists ports_binary_only] && $ports_binary_only == "yes"} {
92                return -code error "Archive for ${subport} ${version}_${revision}${portvariants} not found, required when binary-only is set!"
93            } else {
94                ui_debug "Skipping unarchive ($subport) since no suitable archive found"
95                set skipped 1
96            }
97        }
98    }
99    # Skip running the main body of this target
100    set unarchive.skip $skipped
101
102    return 0
103}
104
105proc portunarchive::unarchive_start {args} {
106    global UI_PREFIX subport version revision portvariants \
107           unarchive.type unarchive.skip
108
109    if {${unarchive.skip}} {
110        return 0
111    }
112
113    if {[getuid] == 0 && [geteuid] != 0} {
114        # run as root if possible so file ownership can be preserved
115        elevateToRoot "unarchive"
116    }
117
118    # create any users and groups needed by the port
119    handle_add_users
120
121    ui_msg "$UI_PREFIX [format [msgcat::mc "Unpacking ${unarchive.type} archive for %s %s_%s%s"] $subport $version $revision $portvariants]"
122
123    return 0
124}
125
126proc portunarchive::unarchive_command_setup {args} {
127    global unarchive.env unarchive.cmd unarchive.pre_args unarchive.args \
128           unarchive.post_args unarchive.type unarchive.path \
129           unarchive.pipe_cmd os.platform os.version env
130
131    # Define appropriate unarchive command and options
132    set unarchive.env {}
133    set unarchive.cmd {}
134    set unarchive.pre_args {}
135    set unarchive.args {}
136    set unarchive.post_args {}
137    set unarchive.pipe_cmd ""
138    switch -regex ${unarchive.type} {
139        cp(io|gz) {
140            set pax "pax"
141            if {[catch {set pax [findBinary $pax ${portutil::autoconf::pax_path}]} errmsg] == 0} {
142                ui_debug "Using $pax"
143                set unarchive.cmd "$pax"
144                if {[geteuid] == 0} {
145                    set unarchive.pre_args {-r -v -p e}
146                } else {
147                    set unarchive.pre_args {-r -v -p p}
148                }
149                if {[regexp {z$} ${unarchive.type}]} {
150                    set unarchive.args {.}
151                    set gzip "gzip"
152                    if {[catch {set gzip [findBinary $gzip ${portutil::autoconf::gzip_path}]} errmsg] == 0} {
153                        ui_debug "Using $gzip"
154                        set unarchive.pipe_cmd "$gzip -d -c ${unarchive.path} |"
155                    } else {
156                        ui_debug $errmsg
157                        return -code error "No '$gzip' was found on this system!"
158                    }
159                } else {
160                    set unarchive.args "-f ${unarchive.path} ."
161                }
162            } else {
163                ui_debug $errmsg
164                return -code error "No '$pax' was found on this system!"
165            }
166        }
167        t(ar|bz|lz|xz|gz) {
168            set tar "tar"
169            if {[catch {set tar [findBinary $tar ${portutil::autoconf::tar_path}]} errmsg] == 0} {
170                ui_debug "Using $tar"
171                set unarchive.cmd "$tar"
172                set unarchive.pre_args {-xvpf}
173                if {[regexp {z2?$} ${unarchive.type}]} {
174                    set unarchive.args {-}
175                    if {[regexp {bz2?$} ${unarchive.type}]} {
176                        set gzip "bzip2"
177                    } elseif {[regexp {lz$} ${unarchive.type}]} {
178                        set gzip "lzma"
179                    } elseif {[regexp {xz$} ${unarchive.type}]} {
180                        set gzip "xz"
181                    } else {
182                        set gzip "gzip"
183                    }
184                    if {[info exists portutil::autoconf::${gzip}_path]} {
185                        set hint [set portutil::autoconf::${gzip}_path]
186                    } else {
187                        set hint ""
188                    }
189                    if {[catch {set gzip [findBinary $gzip $hint]} errmsg] == 0} {
190                        ui_debug "Using $gzip"
191                        set unarchive.pipe_cmd "$gzip -d -c ${unarchive.path} |"
192                    } else {
193                        ui_debug $errmsg
194                        return -code error "No '$gzip' was found on this system!"
195                    }
196                } else {
197                    set unarchive.args "${unarchive.path}"
198                }
199            } else {
200                ui_debug $errmsg
201                return -code error "No '$tar' was found on this system!"
202            }
203        }
204        xar {
205            set xar "xar"
206            if {[catch {set xar [findBinary $xar ${portutil::autoconf::xar_path}]} errmsg] == 0} {
207                ui_debug "Using $xar"
208                set unarchive.cmd "$xar"
209                set unarchive.pre_args {-xvpf}
210                set unarchive.args "${unarchive.path}"
211            } else {
212                ui_debug $errmsg
213                return -code error "No '$xar' was found on this system!"
214            }
215        }
216        zip {
217            set unzip "unzip"
218            if {[catch {set unzip [findBinary $unzip ${portutil::autoconf::unzip_path}]} errmsg] == 0} {
219                ui_debug "Using $unzip"
220                set unarchive.cmd "$unzip"
221                if {[geteuid] == 0} {
222                    set unarchive.pre_args {-oX}
223                } else {
224                    set unarchive.pre_args {-o}
225                }
226                set unarchive.args "${unarchive.path} -d ."
227            } else {
228                ui_debug $errmsg
229                return -code error "No '$unzip' was found on this system!"
230            }
231        }
232        default {
233            return -code error "Invalid port archive type '${unarchive.type}' specified!"
234        }
235    }
236
237    return 0
238}
239
240proc portunarchive::unarchive_main {args} {
241    global UI_PREFIX unarchive.dir unarchive.file unarchive.pipe_cmd unarchive.skip
242
243    if {${unarchive.skip}} {
244        return 0
245    }
246
247    # Setup unarchive command
248    unarchive_command_setup
249
250    # Create destination directory for unpacking
251    if {![file isdirectory ${unarchive.dir}]} {
252        file mkdir ${unarchive.dir}
253    }
254
255    # Unpack the archive
256    ui_info "$UI_PREFIX [format [msgcat::mc "Extracting %s"] ${unarchive.file}]"
257    if {${unarchive.pipe_cmd} == ""} {
258        command_exec unarchive
259    } else {
260        command_exec unarchive "${unarchive.pipe_cmd} (" ")"
261    }
262
263    return 0
264}
265
266proc portunarchive::unarchive_finish {args} {
267    global UI_PREFIX target_state_fd unarchive.file subport workpath destpath unarchive.skip
268
269    if {${unarchive.skip}} {
270        return 0
271    }
272
273    # Reset state file with archive version
274    set statefile [file join $workpath .macports.${subport}.state]
275    set plus_state [file join $destpath "+STATE"]
276    if {[file isfile $plus_state]} {
277        close $target_state_fd
278        file copy -force $plus_state $statefile
279        file mtime $statefile [clock seconds]
280        chownAsRoot $statefile
281        update_statefile checksum [sha256 file [option portpath]/Portfile] $statefile
282        set newstate 1
283    } else {
284        # fake it
285        write_statefile target org.macports.destroot $target_state_fd
286    }
287
288    # Cleanup all control files when finished
289    set control_files [glob -nocomplain -types f [file join $destpath +*]]
290    foreach file $control_files {
291        ui_debug "Removing $file"
292        file delete -force $file
293    }
294
295    if {[info exists newstate]} {
296        # Update the state from unpacked archive version
297        set target_state_fd [open_statefile]
298    }
299
300    ui_info "$UI_PREFIX [format [msgcat::mc "Archive %s unpacked"] ${unarchive.file}]"
301    return 0
302}
Note: See TracBrowser for help on using the repository browser.