summaryrefslogtreecommitdiff
path: root/share/sfpm/env.sh
blob: e9127a61d358f997be30c88672147416f57e6ac3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
function sfpm_env_exists() {
    # Returns empty string on failure (implicit)
    local name="${1}"
    if [[ ! ${name} ]]; then
        msg_error "sfpm_env_exists(): missing environment name"
        exit 1
    fi

    local path="${sfpm_envdir}/${name}"
    if [[ ! -d ${path} ]]; then
        return 1
    fi
    echo ${path}
}


function sfpm_env_create() {
    local name="${1}"
    local path="${sfpm_envdir}/${name}"
    if [[ ! $(sfpm_env_exists ${name}) ]]; then
        msg "Creating environment root: ${name}"
        sfpm_gen_sysroot "${path}"
    fi

    if [[ ! -f ${path}/bin/activate ]]; then
        sed -e "s|__SFPM_ENV__|${path}|g" \
            ${sfpm_sysconfdir}/sfpm.activate.sh > ${path}/bin/activate
    fi

}


function sfpm_env_remove() {
    local name="${1}"
    local path="${sfpm_envdir}/${name}"
    if [[ $(sfpm_env_exists ${name}) ]]; then
        msg "Removing environment root: ${name}"
        rm -rf "${path}"
    fi
}

function sfpm_rpath_nearest() {
    local cwd="$(pwd)"
    local start=$(dirname $(sfpm_abspath ${1}))
    local result=

    # Jump to location of file
    cd "$(dirname ${start})"

    # Scan upward until we find a "lib" directory
    # OR when:
    # - Top of filesystem is reached (pretty much total failure [missing local dep])
    # - Top of active environment is reached (post installation)
    # - Top of default installation prefix is reached (during packaging)
    while [[ $(pwd) != / ]]
    do
        result+="../"
        if [[ -d lib ]] || [[ $(pwd) == ${SFPM_ENV} ]] || [[ $(pwd) == *${sfpm_build_prefix} ]]; then
            result+="lib"
            break
        fi
        cd ..
    done

    # Sanitize: removing double-slashes (if any)
    result=${result/\/\//\/}

    # Return to where we were instantiated
    cd "${cwd}"

    echo "${result}"
}


function sfpm_install() {
    local env_name="${1}"
    local env_path=$(sfpm_env_exists "${env_name}")
    local pkg_name="${2}"
    local pkg_version="${3}"
    local pkg_release="${4}"
    local pkg="${pkg_name}-${pkg_version}-${pkg_release}"
    local pkg_path
    local metadata
    local staging
    local have_prefix_text
    local have_prefix_bin

    msg "Installing ${pkg_name} [env: ${env_name}]"
    if [[ ! ${env_path} ]]; then
        msg_error "sfpm_install(): Environment does not exist: ${env_name}"
        exit 1
    fi

    if [[ ${pkg_name} == */*.tar.bz2 ]]; then
        pkg_path="${pkg_name}"
    else
        pkg_path=$(sfpm_package_exists "${pkg}.tar.bz2")
    fi

    if [[ ! -f ${pkg_path} ]]; then
        msg_error "sfpm_install(): Package does not exist: ${pkg}"
        exit 1
    fi


    msg2 "Extracting metadata"
    metadata=$(mktemp -d ${TMPDIR}/sfpm.metadata.XXXXXX)
    tar -xf "${pkg_path}" \
        -C "${metadata}" \
        --wildcards "\.SFPM-*"

    msg2 "Extracting package"
    staging=$(mktemp -d ${TMPDIR}/sfpm.staging.XXXXXX)
    tar -xf "${pkg_path}" \
        -C "${staging}" \
        --strip-components=1 \
        --wildcards "${sfpm_build_prefix/\//}*"

    have_prefix_text=$(wc -l ${metadata}/.SFPM-PREFIX-TEXT | cut -d ' ' -f 1)
    if [[ ${have_prefix_text} != 0 ]]; then
        msg2 "Relocating text paths"
        while read filename
        do
            msg3 "${filename}"
            sfpm_file_relocate --text --env "${env_name}" --path "${filename}"
        done < <(sed -e "s|.${sfpm_build_prefix}|${staging}|g" "${metadata}/.SFPM-PREFIX-TEXT")
    fi

    # TODO: Not implemented
    #have_prefix_bin=$(wc -l ${metadata}/.SFPM-PREFIX-BIN | cut -d ' ' -f 1)
    #if [[ ${have_prefix_bin} != 0 ]]; then
    #    msg2 "Relocating binary paths"
    #    while read filename
    #    do
    #        msg3 "${filename}"
    #        sfpm_file_relocate --bin --env "${env_name}" --path "${filename}"
    #    done < <(sed -e "s|.${sfpm_build_prefix}|${staging}|g" "${metadata}/.SFPM-PREFIX-BIN")
    #fi
    rsync -a "${staging}/" "${env_path}"

    rm -rf "${staging}"
    rm -rf "${metadata}"
}


function sfpm_file_relocate() {
    # TODO: binary relocation
    # easy peasy... already wrote sfpm_rpath_nearest()
    #local env_name="${1}"
    #local env_path=$(sfpm_env_exists "${env_name}")
    #local path="${2}"

    local path
    local env_name
    local mode_text=0
    local mode_bin=0

    while (( "${#}" )); do
        case "${1}" in
            -t|--text)
                mode_text=1
                shift
                ;;
            -b|--bin)
                # TODO: Not implemented
                mode_bin=1
                shift
                ;;
            -e|--env)
                env_name="${2}"
                shift 2
                ;;
            -p|--path)
                path="${2}"
                shift 2
                ;;
            --)
                shift
                break
                ;;
            -*|--*)
                msg_error "Invalid argument: ${1}" >&2
                exit 1
                ;;
            *)
                # do nothing with positional args
                shift
                ;;
        esac
    done

    if (( ${mode_text} )) && (( ${mode_bin} )); then
        msg_error "-t/--text and -b/--bin are mutually exclusive arguments"
        exit 1
    fi

    local env_path=$(sfpm_env_exists "${env_name}")
    if [[ ! ${env_path} ]]; then
        msg_error "sfpm_file_relocate(): Environment does not exist: ${env_name}"
        exit 1
    fi

    if [[ ! -f ${path} ]] && [[ ! -L ${path} ]]; then
        msg_warn "sfpm_file_relocate(): ${path}: not a file or symbolic link"
        return 1
    fi

    tmpfile=$(mktemp ${TMPDIR}/sfpm.relocate.XXXXXX)
    if [[ ! -f ${tmpfile} ]]; then
        msg_error "sfpm_file_relocate(): Failed to create temporary relocation file."
        exit 1
    fi

    filemode=$(stat -c '%a' "${path}")
    if (( ${mode_text} )); then
        sed -e "s|${sfpm_build_prefix}|${env_path}|g" < "${path}" > "${tmpfile}"
    elif (( ${mode_bin} )); then
        # TODO
        :
    else
        msg_error "sfpm_file_relocate(): Invalid modification mode. --text nor --bin specified"
        exit 1
    fi

    chmod ${filemode} "${tmpfile}"
    mv "${tmpfile}" "${path}"

    if (( $? )); then
        msg_error "sfpm_file_relocate(): Failed to move temporary relocation file. Purging."
        rm -f "${tmpfile}"
    fi
}