summaryrefslogtreecommitdiff
path: root/xibuild
blob: cfa64f9c317a7bddfb18e158bbd60beb240b238b (plain)
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
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
#!/bin/bash

XI_ROOT=$(pwd)
PKGS_OUTPUT=$XI_ROOT/xipkgs
PRIV_KEY=$XI_ROOT/keychain/xi.pem

ERROR="\033[0;31m"
INFO="\033[0;34m"
PASS="\033[0;32m"
NEUTRAL="\033[0;33m"
RESET="\033[0m"

MAKEFLAGS="-j11"
alias make="make $MAKEFLAGS"

extract () {
    FILE=$1
    echo extracting $FILE
    case "${FILE#*.}" in 
        "tar.gz" )
            tar -zxf $FILE
            ;;
        "tar.lz" )
            tar --lzip -xf "$FILE"
            ;;
        "zip" )
            unzip $FILE
            ;;
        * )
            tar -xf $FILE
            ;;
    esac
}

pkgname () {
    echo $(basename $1 .xibuild)
}

xibuild () {
    BUILD_FILE=${@: -1}
    BUILD_HASH=$(md5sum $BUILD_FILE | cut -f1 -d" ")

    cd $XI_ROOT

    [[ $# = 0 ]] && usage && return 1
    [ ! -f "$BUILD_FILE" ] && echo "$BUILD_FILE not found" && return 1

    BUILD_FILE_PATH=$(realpath $BUILD_FILE)

    clean () {
        # clean up
        rm -rf $PKG_BUILD_DIR
        rmdir $XI_ROOT/tmp > /dev/null 2>&1
    }

    patch () {
        echo "Passing missing patch stage"
    }
    build () {
        printf "\tpassing missing build stage..."
    }
    check () {
        echo "Passing missing check stage"
    }
    package () {
        echo "Passing missing package stage"
    }

    BRANCH=HEAD

    source $BUILD_FILE

    PKG_NAME=$(pkgname $BUILD_FILE)

    LOGFILE=$XI_ROOT/logs/$PKG_NAME.log
    PKG_FILE=$PKGS_OUTPUT/$PKG_NAME.xipkg

    PKG_BUILD_DIR=$XI_ROOT/tmp/$PKG_NAME
    PKG_DEST=$XI_ROOT/tmp/$PKG_NAME.package

    # make sure build dir is clean before starting
    rm -rf $PKG_BUILD_DIR

    # make the directories
    mkdir -p $PKG_BUILD_DIR
    mkdir -p $PKG_DEST
    mkdir -p $PKGS_OUTPUT
    mkdir -p $XI_ROOT/logs

    date > $LOGFILE
    echo "Build log for $PKG_NAME from $BUILD_FILE\n" >> $LOGFILE
    printf "\033[0;36m====> $PKG_NAME.xipkg$RESET\n" | tee -a $LOGFILE

    cd $PKG_BUILD_DIR

    # fetch, build then package the package
    ############

    if [ ! -z ${SOURCE+x} ]; then
        # try get the commit hash for the package
        if git ls-remote -q $SOURCE &> /dev/null; then
            VER_HASH=$(git ls-remote $SOURCE $BRANCH )
        elif hg identify $SOURCE &> /dev/null; then
            VER_HASH=$(hg identify $SOURCE)
        else
            VER_HASH=$(curl -Ls $SOURCE | md5sum)
        fi
        
        VER_HASH=$(echo $VER_HASH | awk '{ print $1 }')

        # If we already have this package, don't waste our time
        if [ -f "$PKG_FILE.info" ] && [ -f "$PKG_FILE" ]; then
            EXISTING_HASH=$(grep -a "VER_HASH" $PKG_FILE.info | sed "s/VER_HASH=//")

            echo "Comparing $EXISTING_HASH to $VER_HASH" >> $LOGFILE

            printf "$INFO\tvalidating commit hash...";

            EXISTING_BUILD_HASH=$(md5sum $PKGS_OUTPUT/$PKG_NAME.xibuild | cut -f1 -d" ")
            if [ "$EXISTING_HASH" = "$VER_HASH" ] && [ "$EXISTING_BUILD_HASH" = "$BUILD_HASH" ]; then
                printf "$NEUTRAL package exists$RESET\n"
                echo "exists $PKG_NAME $DESC" >> $REPORT_LOG
                rm $LOGFILE
                return;
            else 
                printf "$NEUTRAL package outdated\n"
            fi
        fi

        printf "$INFO\tfetching package...";
        if git ls-remote -q $SOURCE $BRANCH &> /dev/null; then
            git clone $SOURCE . >> $LOGFILE 2>&1 && printf "$PASS fetched $(du -sh $PKG_BUILD_DIR | awk '{ print $1 }') source\n" || return 1;
            git checkout $BRANCH >> $LOGFILE 2>&1 

        elif hg identify $SOURCE &> /dev/null; then
            hg clone $SOURCE . >> $LOGFILE 2>&1 && printf "$PASS fetched $(du -sh $PKG_BUILD_DIR | awk '{ print $1 }') source\n" || return 1;
        else
            DOWNLOADED=$(basename $SOURCE)
            curl -Ls $SOURCE > $DOWNLOADED
            extract $DOWNLOADED >> $LOGFILE 2>&1 && printf "$PASS fetched $(du -sh $PKG_BUILD_DIR | awk '{ print $1 }') source\n" || return 1;
            cd $(ls -d */)
        fi
    else
        SOURCE="none"
    fi

    printf "\033[0;34m\tpatching package...\033[0m";
    patch >> $LOGFILE 2>&1 && printf "$PASS patched\n" ||  return 1;

    printf "$INFO\tbuilding package...";
    build >> $LOGFILE 2>&1 && printf "$PASS built\n" || return 1;

    printf "\033[0;34m\ttesting package...\033[0m";
    check >> $LOGFILE 2>&1 && printf "$PASS checked\n" ||  return 1;

    printf "\033[0;34m\tpackaging package...\033[0m";
    package >> $LOGFILE 2>&1 && printf "$PASS packaged\n" ||  return 1;
    
    # add postinstall script
    if command -v postinstall > /dev/null; then
        POSTINSTALL=$(type postinstall | sed '1,3d;$d')
        if [ ${#POSTINSTALL} != 0 ]; then
            POST_DIR=$PKG_DEST/tmp/xi/postinstall
            mkdir -p $POST_DIR
            echo "#!/bin/sh" > $POST_DIR/$PKG_NAME.sh
            echo $POSTINSTALL >> $POST_DIR/$PKG_NAME.sh
        fi
    fi

    # go back to root, make things easier
    cd $XI_ROOT

    if [ -z "$(ls -A $PKG_DEST)" ] && [ ! $SOURCE = "none" ]; then
        printf "$FAIL!!!Package is empty!!!$RESET\n"
        return 1;
    fi

    printf "$INFO\tarchiving package...";
    tar -C $PKG_DEST -cvzf $PKG_FILE ./ >> $LOGFILE 2>&1 && printf "$PASS archived to $(du -sh $PKG_FILE | awk '{ print $1 }')\n" || return 1;


    # create info file
    printf "$INFO\tcreating xipkg.info...";
    PKG_INFO=$PKGS_OUTPUT/$PKG_NAME.xipkg.info

    cp $BUILD_FILE $PKGS_OUTPUT/$PKG_NAME.xibuild

    echo "" > $PKG_INFO
    echo "NAME=$PKG_NAME" >> $PKG_INFO
    echo "DESCRIPTION=$DESC" >> $PKG_INFO
    echo "PKG_FILE=$PKG_NAME.xipkg" >> $PKG_INFO
    echo "CHECKSUM=$(md5sum $PKG_FILE | awk '{ print $1 }')" >> $PKG_INFO
    echo "VER_HASH=$VER_HASH" >> $PKG_INFO
    echo "SOURCE=$SOURCE" >> $PKG_INFO
    echo "DATE=$(date)" >> $PKG_INFO
    echo "DEPS=(${DEPS[*]})" >> $PKG_INFO

    printf "$INFOsigning...";
    # sign the package

    if [ -f "$PRIV_KEY" ]; then
        echo "SIGNATURE=" >> $PKG_INFO
        openssl dgst -sign $PRIV_KEY $PKG_FILE >> $PKG_INFO
    else
        echo "SIGNATURE=">> $PKG_INFO
        echo "unsigned">> $PKG_INFO
        >&2 printf "$ERROR WARNING! No private key: unsigned packages!\n"
    fi
    printf "$PASS signed\n";

    printf "$PASS successfully built $PKG_NAME to $(basename $PKG_FILE)$RESET\n"

    clean

    echo "new $PKG_NAME $DESC" >> $REPORT_LOG

    unset SOURCE DESC DEPS install package check
    return 0
}

usage () {
 cat << EOF
usage: $0 [-h] [-o output-dir] [-r working_root]  [-k private_key.pem] build_file.xibuild
    -h          display this help message
    -o          set the output dir for the xipkg files (default: $PWD/xipkgs)
    -r          set the working root for all log and tmp files (default: $PWD)
    -k          set the private key used to sign packages (default: $PWD/keychain/xi.pem)
EOF
}

build-all () {
    FILES=$@

    while test $# -gt 0; do
        case "$1" in
            "-o" )
                shift
                PKGS_OUTPUT=$PWD/$1
                ;;
            "-r" )
                shift
                XI_ROOT=$PWD/$1
                ;;
            "-k" )
                shift
                PRIV_KEY=$PWD/$1
                ;;
            "-h" )
                usage
                ;;
            * )
                REPORT_LOG=$XI_ROOT/xibuild.report.log
                BUILD_FILE=$1
                if xibuild $BUILD_FILE; then 
                    printf "$RESET"
                else
                    printf "$ERROR error! See log$RESET\n"
                    echo "fail $PKG_NAME $DESC" >> $REPORT_LOG
                fi
                cd $XI_ROOT
                ;;
        esac

        shift
    done
}
if [ $# -gt 0 ]; then
    build-all $@ | tee -a xibuild.log
else
    usage; return 1
fi