Browse Source

Split-fork from qecc

All other files have been moved to *eecc* and whole qecc
history (~300 commits) has been squashed into this commit.
Alois Mahdal 10 years ago
parent
commit
b4826f26a4

+ 1
- 0
.gitignore View File

@@ -0,0 +1 @@
1
+.autoclean

+ 165
- 0
LICENSE View File

@@ -0,0 +1,165 @@
1
+                   GNU LESSER GENERAL PUBLIC LICENSE
2
+                       Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+
9
+  This version of the GNU Lesser General Public License incorporates
10
+the terms and conditions of version 3 of the GNU General Public
11
+License, supplemented by the additional permissions listed below.
12
+
13
+  0. Additional Definitions.
14
+
15
+  As used herein, "this License" refers to version 3 of the GNU Lesser
16
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
17
+General Public License.
18
+
19
+  "The Library" refers to a covered work governed by this License,
20
+other than an Application or a Combined Work as defined below.
21
+
22
+  An "Application" is any work that makes use of an interface provided
23
+by the Library, but which is not otherwise based on the Library.
24
+Defining a subclass of a class defined by the Library is deemed a mode
25
+of using an interface provided by the Library.
26
+
27
+  A "Combined Work" is a work produced by combining or linking an
28
+Application with the Library.  The particular version of the Library
29
+with which the Combined Work was made is also called the "Linked
30
+Version".
31
+
32
+  The "Minimal Corresponding Source" for a Combined Work means the
33
+Corresponding Source for the Combined Work, excluding any source code
34
+for portions of the Combined Work that, considered in isolation, are
35
+based on the Application, and not on the Linked Version.
36
+
37
+  The "Corresponding Application Code" for a Combined Work means the
38
+object code and/or source code for the Application, including any data
39
+and utility programs needed for reproducing the Combined Work from the
40
+Application, but excluding the System Libraries of the Combined Work.
41
+
42
+  1. Exception to Section 3 of the GNU GPL.
43
+
44
+  You may convey a covered work under sections 3 and 4 of this License
45
+without being bound by section 3 of the GNU GPL.
46
+
47
+  2. Conveying Modified Versions.
48
+
49
+  If you modify a copy of the Library, and, in your modifications, a
50
+facility refers to a function or data to be supplied by an Application
51
+that uses the facility (other than as an argument passed when the
52
+facility is invoked), then you may convey a copy of the modified
53
+version:
54
+
55
+   a) under this License, provided that you make a good faith effort to
56
+   ensure that, in the event an Application does not supply the
57
+   function or data, the facility still operates, and performs
58
+   whatever part of its purpose remains meaningful, or
59
+
60
+   b) under the GNU GPL, with none of the additional permissions of
61
+   this License applicable to that copy.
62
+
63
+  3. Object Code Incorporating Material from Library Header Files.
64
+
65
+  The object code form of an Application may incorporate material from
66
+a header file that is part of the Library.  You may convey such object
67
+code under terms of your choice, provided that, if the incorporated
68
+material is not limited to numerical parameters, data structure
69
+layouts and accessors, or small macros, inline functions and templates
70
+(ten or fewer lines in length), you do both of the following:
71
+
72
+   a) Give prominent notice with each copy of the object code that the
73
+   Library is used in it and that the Library and its use are
74
+   covered by this License.
75
+
76
+   b) Accompany the object code with a copy of the GNU GPL and this license
77
+   document.
78
+
79
+  4. Combined Works.
80
+
81
+  You may convey a Combined Work under terms of your choice that,
82
+taken together, effectively do not restrict modification of the
83
+portions of the Library contained in the Combined Work and reverse
84
+engineering for debugging such modifications, if you also do each of
85
+the following:
86
+
87
+   a) Give prominent notice with each copy of the Combined Work that
88
+   the Library is used in it and that the Library and its use are
89
+   covered by this License.
90
+
91
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
92
+   document.
93
+
94
+   c) For a Combined Work that displays copyright notices during
95
+   execution, include the copyright notice for the Library among
96
+   these notices, as well as a reference directing the user to the
97
+   copies of the GNU GPL and this license document.
98
+
99
+   d) Do one of the following:
100
+
101
+       0) Convey the Minimal Corresponding Source under the terms of this
102
+       License, and the Corresponding Application Code in a form
103
+       suitable for, and under terms that permit, the user to
104
+       recombine or relink the Application with a modified version of
105
+       the Linked Version to produce a modified Combined Work, in the
106
+       manner specified by section 6 of the GNU GPL for conveying
107
+       Corresponding Source.
108
+
109
+       1) Use a suitable shared library mechanism for linking with the
110
+       Library.  A suitable mechanism is one that (a) uses at run time
111
+       a copy of the Library already present on the user's computer
112
+       system, and (b) will operate properly with a modified version
113
+       of the Library that is interface-compatible with the Linked
114
+       Version.
115
+
116
+   e) Provide Installation Information, but only if you would otherwise
117
+   be required to provide such information under section 6 of the
118
+   GNU GPL, and only to the extent that such information is
119
+   necessary to install and execute a modified version of the
120
+   Combined Work produced by recombining or relinking the
121
+   Application with a modified version of the Linked Version. (If
122
+   you use option 4d0, the Installation Information must accompany
123
+   the Minimal Corresponding Source and Corresponding Application
124
+   Code. If you use option 4d1, you must provide the Installation
125
+   Information in the manner specified by section 6 of the GNU GPL
126
+   for conveying Corresponding Source.)
127
+
128
+  5. Combined Libraries.
129
+
130
+  You may place library facilities that are a work based on the
131
+Library side by side in a single library together with other library
132
+facilities that are not Applications and are not covered by this
133
+License, and convey such a combined library under terms of your
134
+choice, if you do both of the following:
135
+
136
+   a) Accompany the combined library with a copy of the same work based
137
+   on the Library, uncombined with any other library facilities,
138
+   conveyed under the terms of this License.
139
+
140
+   b) Give prominent notice with the combined library that part of it
141
+   is a work based on the Library, and explaining where to find the
142
+   accompanying uncombined form of the same work.
143
+
144
+  6. Revised Versions of the GNU Lesser General Public License.
145
+
146
+  The Free Software Foundation may publish revised and/or new versions
147
+of the GNU Lesser General Public License from time to time. Such new
148
+versions will be similar in spirit to the present version, but may
149
+differ in detail to address new problems or concerns.
150
+
151
+  Each version is given a distinguishing version number. If the
152
+Library as you received it specifies that a certain numbered version
153
+of the GNU Lesser General Public License "or any later version"
154
+applies to it, you have the option of following the terms and
155
+conditions either of that published version or of any later version
156
+published by the Free Software Foundation. If the Library as you
157
+received it does not specify a version number of the GNU Lesser
158
+General Public License, you may choose any version of the GNU Lesser
159
+General Public License ever published by the Free Software Foundation.
160
+
161
+  If the Library as you received it specifies that a proxy can decide
162
+whether future versions of the GNU Lesser General Public License shall
163
+apply, that proxy's public statement of acceptance of any version is
164
+permanent authorization for you to choose that version for the
165
+Library.

+ 40
- 0
Makefile View File

@@ -0,0 +1,40 @@
1
+# ffood - Fast Food - a Bash Library
2
+# See LICENSE file for copyright and license details.
3
+
4
+include config.mk
5
+
6
+all: options doc ffood
7
+
8
+options:
9
+	@echo ffood build options:
10
+	@echo "VERSION  = ${VERSION}"
11
+	@echo "PREFIX   = ${PREFIX}"
12
+
13
+doc:
14
+	@setup/mk.sh doc
15
+
16
+install_manpages: manpages
17
+	@setup/mk.sh install_manpages
18
+
19
+manpages:
20
+	@setup/mk.sh manpages
21
+
22
+ffood:
23
+	@setup/mk.sh ffood
24
+
25
+test: install
26
+	@setup/mk.sh test
27
+
28
+clean:
29
+	@setup/mk.sh clean
30
+
31
+dist: clean
32
+	@setup/mk.sh dist
33
+
34
+install: all
35
+	@setup/mk.sh install
36
+
37
+uninstall:
38
+	@setup/mk.sh uninstall
39
+
40
+.PHONY: all options clean dist install test uninstall

+ 19
- 3
README View File

@@ -1,4 +1,20 @@
1
-QECC
2
-====
1
+Fast Food Bash library
2
+======================
3 3
 
4
-Quality Engineering Control Centre
4
+ffood - Fast Food - a Bash Library
5
+
6
+
7
+BUGS
8
+----
9
+
10
+  * *core.debug():* if `debug -v "x*:` is used, `x*` apparently tries to match
11
+    match *filenames* first, and only if there is no match, it goes on to
12
+    match variable names.  This does not seem to affect `@`, though.
13
+
14
+    Probably some eval pitfall.  For now I'll just remove `*`.  If somebody
15
+    can fix it, we can re-add it.
16
+
17
+    On the other hand, I don't even understand how `*` should exactly behave
18
+    compared to `@`, so having it disabled does not seem like such a loss.
19
+    And by the way, did you know that the eval is evil?  So in the end, maybe
20
+    we should not have this feature in the first place... :)

+ 43
- 0
bin/fffun.in View File

@@ -0,0 +1,43 @@
1
+#!/bin/bash
2
+
3
+. __FFOOD_DIR__/ffood.sh
4
+
5
+ffood import core
6
+ffood import recon
7
+
8
+
9
+usage() {
10
+    usage_is "[-I|--include module] [--] function [args...]"
11
+}
12
+
13
+includes=""
14
+FFOOD_DEBUG=false
15
+
16
+while true; do
17
+    case $1 in
18
+        -d|--debug)
19
+            FFOOD_DEBUG=true
20
+            shift 1
21
+            ;;
22
+        -I|--include)
23
+            includes=$includes:$2
24
+            shift 2
25
+            ;;
26
+        "")
27
+            usage
28
+            ;;
29
+        --)
30
+            shift 1
31
+            break
32
+            ;;
33
+        *)
34
+            break;
35
+            ;;
36
+    esac;
37
+done
38
+
39
+for i in $(tr ":" " " <<<"$includes"); do
40
+    ffood import $i
41
+done
42
+
43
+"$@"

+ 3
- 0
config.mk View File

@@ -0,0 +1,3 @@
1
+VERSION = 0.0.0
2
+PREFIX = /usr/local
3
+MANPREFIX = ${PREFIX}/share/man

+ 8
- 0
doc/BUGS.md View File

@@ -0,0 +1,8 @@
1
+Bugs
2
+====
3
+
4
+*   debug_pipe and all `while read`-based commands will throw away
5
+    last line if there is no newline at the end.
6
+
7
+    This is "fixed" by adding at least one (possibly all-matching)
8
+    `grep` command before the while loop

+ 8
- 0
doc/examples/template.sh.in View File

@@ -0,0 +1,8 @@
1
+#!/bin/bash
2
+
3
+. __FFOOD_DIR__/ffood.sh
4
+
5
+ffood import core
6
+
7
+FFOOD_VERBOSE=true
8
+FFOOD_DEBUG=true

+ 13
- 0
doc/fffun.1.md View File

@@ -0,0 +1,13 @@
1
+FFFUN
2
+=====
3
+
4
+
5
+SYNOPSIS
6
+--------
7
+
8
+    fffun [-d] [-I module] function [args...]
9
+
10
+AUTHOR
11
+------
12
+
13
+Alois Mahdal

+ 74
- 0
doc/ffood.3.md View File

@@ -0,0 +1,74 @@
1
+FFOOD
2
+=====
3
+
4
+SYNOPSIS
5
+--------
6
+
7
+    #!/bin/bash
8
+    # ~/bin/example
9
+    source /usr/share/lib/ffood/ffood.sh
10
+    ffood import core
11
+
12
+    # basic echo helpers
13
+    think "about saying something..."   # like echo if FFOOD_VERBOSE
14
+    warn "this is just an example"      # obvious :)
15
+    false || die "false was true!"      # Perlism :)
16
+    x=1; y=2; z=3
17
+    debug "x=$x" "y=$y" "z=$z"          # debug:example: x=1
18
+                                        # debug:example: y=2
19
+                                        # debug:example: z=3
20
+    debug -v x:y:z                      # short for above!
21
+    echo "hello" | debug_pipe mypipe    # debug:PIPE mypipe: hello
22
+
23
+    # more advanced functions
24
+    FFOOD_DATADIR=$HOME/.example
25
+    cat >$FFOOD_DATADIR/main.ini <<EOF
26
+    # a sample ini file
27
+    [mysection]
28
+        key = something
29
+        multiline = also possible
30
+        multiline = like this :)
31
+    [scripts]
32
+        s1 =#!/usr/bin/python
33
+        s1 =def main():
34
+        s1 =    print "will work!"
35
+    EOF
36
+    iniread -s mysection -k mykey main.ini  # prints "something"
37
+    iniread -S -k s1 > sample.py            # why section? with unique key...
38
+    python sample.py                        # "will work!" due to the -S
39
+
40
+    # even more
41
+    ffood import recon
42
+    wait_until -e ! test -e badfile         # -e means use eval (make "!" work)
43
+    think "the badfile is away..."
44
+    bad_file_away() {                       # but you can avoid eval
45
+        ! test -f badfile
46
+    }
47
+    wait_until bad_file_away
48
+
49
+    # ... and more
50
+    ffood import recon
51
+    register_artifact this_file_will_exist.log
52
+    some_important_program > this_file_will_exist.log
53
+    collect_artifacts                       # will preserve tree from /
54
+
55
+    # ...AND MORE!
56
+    ffood import sw
57
+    cat > dependencies.ini <<EOF
58
+    [needs/now]
59
+        yum = ronn
60
+        yum = vim
61
+        pypi = docopt
62
+    [needs/for_test]
63
+        cpan = Test::More
64
+    # yeah I made that up
65
+    EOF
66
+    iniread ./dependencies.ini | any_install
67
+
68
+
69
+
70
+
71
+AUTHOR
72
+------
73
+
74
+Alois Mahdal

+ 38
- 0
ffood.sh.in View File

@@ -0,0 +1,38 @@
1
+#!/bin/bash
2
+
3
+FFOOD_DATA_DIR=${FFOOD_DATA_DIR:-$HOME/.ffood}
4
+FFOOD_ARTIFACTS_DIR=${FFOOD_ARTIFACTS_DIR:-artifacts}
5
+FFOOD_DEBUG=${FFOOD_DEBUG:-false}
6
+FFOOD_VERBOSE=${FFOOD_VERBOSE:-false}
7
+FFOOD_VERSION=__VERSION__
8
+
9
+die() {
10
+    echo "$@" >&2
11
+    exit 1
12
+}
13
+
14
+ffood() {
15
+    local ffood_dir="${FFOOD_DIR:-__FFOOD_DIR__}"
16
+    case $1 in
17
+        import)
18
+            if test -f "$ffood_dir/include/$2.sh";
19
+            then
20
+                . "$ffood_dir/include/$2.sh";
21
+                return $?
22
+            elif test -n "$FFOOD_INCLUDE" -a -f "$FFOOD_INCLUDE/$2.sh";
23
+            then
24
+                . "$FFOOD_INCLUDE/$2.sh"
25
+                return $?
26
+            elif test -f "./$2.sh";
27
+            then
28
+                . "./$2.sh"
29
+                return $?
30
+            else
31
+                die "cannot find library: $2"
32
+            fi
33
+            ;;
34
+        *)
35
+            die "unknown ffood command: $1"
36
+            ;;
37
+    esac
38
+}

+ 323
- 0
include/core.sh View File

@@ -0,0 +1,323 @@
1
+#!/bin/bash
2
+
3
+debug() {
4
+    #
5
+    # You already know what it does.
6
+    #
7
+    # BTW, following are equivalent:
8
+    #
9
+    #     debug "var1=$var1" "var2=$var2" "result=$result"
10
+    #     debug -v var1:var2:result
11
+    #     debug -v "var@:result"
12
+    #
13
+    $FFOOD_DEBUG || return 0
14
+    if test "$1" == "-v";
15
+    then
16
+        local varnames="$2"
17
+        local vn
18
+        for vn in $(tr ":" " " <<<"$varnames");
19
+        do
20
+            local heel="${vn:0-1}"          # last char
21
+            local toes="${vn%%$heel}"       # all but last char
22
+            if test "$heel" == "@";
23
+            then
24
+                # FIXME: review+fix the eval (even at cost of dropping the feature)
25
+                local vars=$(eval "echo \"\${!$toes$heel}\"")
26
+                debug -v $(tr " " ":" <<<"$vars")
27
+            else
28
+                debug "$vn='$(echo -n ${!vn})'"
29
+            fi
30
+        done
31
+    elif test "$1" == "-t";
32
+    then
33
+        local -a tr=(${FUNCNAME[@]})
34
+        unset tr[0]; unset tr[1];
35
+        local tmp=$(echo "${tr[*]}" | tr '  ' '\n' | tac )
36
+        echo "== trace ==" >&2
37
+        echo "$tmp" | sed -e 's/^/-> /g' >&2
38
+    else
39
+        local me=${FUNCNAME[1]}
40
+        case $me in
41
+            main)       me=$(basename $0)       ;;
42
+            debug)      me="${FUNCNAME[2]}()"   ;;
43
+            debug_pipe) me="${FUNCNAME[2]}()"   ;;
44
+            *)          me="$me()"              ;;
45
+        esac
46
+        local l
47
+        for l in "$@";
48
+        do echo "debug:$me: $l" >&2
49
+        done
50
+    fi
51
+}
52
+
53
+debug_pipe() {
54
+    #
55
+    # Debug the whole pipe.
56
+    #
57
+    grep ".*" \
58
+        | while IFS= read line;
59
+          do
60
+              debug "PIPE $1: '$line'"
61
+              echo "$line"
62
+          done
63
+}
64
+
65
+die() {
66
+    #
67
+    # A Perl-style death (a truly honorable one that is)
68
+    #
69
+    debug -t
70
+    warn $*
71
+    exit 9
72
+}
73
+
74
+echo_hr() {
75
+    #
76
+    # Echo a horizontal ruler out of char "$1" all across terminal.
77
+    #
78
+    test 0$COLUMNS -gt 0 || return
79
+    local char="$1"
80
+    local i
81
+    for (( i=1; $i<$COLUMNS; i=$i+1 )); do echo -n "$char"; done
82
+    echo
83
+}
84
+
85
+mute_known() {
86
+    #
87
+    # Mute known messages
88
+    #
89
+    # For those yums and rpms that don't know theit manners.  Use with care!
90
+    #
91
+    grep -vxf <(iniread -s mute -k $1 mute.ini)
92
+}
93
+
94
+usage_is() {
95
+    #
96
+    # Echo out usage patterns and exit 1
97
+    #
98
+    # Define usage() in your script and use this in body
99
+    #
100
+    local me=$(basename $0)
101
+    local u
102
+    for u in "$@";
103
+    do echo "usage: $me $u"
104
+    done
105
+    exit 1
106
+}
107
+
108
+usagef() {
109
+    #
110
+    # Same as usage_is, but for functions.
111
+    #
112
+    # That means it does not exit and uses FUNCNAME, not $0
113
+    #
114
+    local u
115
+    for u in "$@";
116
+    do echo "usage: ${FUNCNAME[1]} $u"
117
+    done
118
+}
119
+
120
+think() {
121
+    #
122
+    # If verose is on, think loud.
123
+    #
124
+    $FFOOD_VERBOSE && echo "$@"
125
+}
126
+
127
+warn() {
128
+    #
129
+    # Warn them
130
+    #
131
+    # Resist  temptation to prefix "warning" or similar BS here.
132
+    # STDERR is *made* for warnings.
133
+    #
134
+    echo "$*" >&2
135
+}
136
+
137
+append_if_missing() {
138
+    #
139
+    # Append line to the file but only if it's not already there.
140
+    #
141
+    # Handy for your fstabs, or whatever line-based confs Handy for your fstabs, or whatever line-based confs
142
+    #
143
+    local line=$1
144
+    local file=$2
145
+    grep -qsx "$line" $file || echo "$line" >> $file
146
+}
147
+
148
+collapse_tilde() {
149
+    #
150
+    # Exchange home back to "~".
151
+    #
152
+    # Nice to save them users from some eye pain.
153
+    #
154
+    perl -pe "s|^$HOME|~|"
155
+}
156
+
157
+expand_tilde() {
158
+    #
159
+    # Exchange "~" for home.
160
+    #
161
+    perl -pe "s|^[[:space:]]*~|$HOME|"
162
+}
163
+
164
+__iniread__cat() {
165
+    # cat without starting a process
166
+    while IFS= read line;
167
+    do echo "$line"; done
168
+}
169
+
170
+__iniread__flt_comments() {
171
+    grep -v -e "^[[:space:]]*[#;]" -e "^[[:space:]]*$"
172
+}
173
+
174
+__iniread__flt_key() {
175
+    # filter values from key=value pair
176
+    local line
177
+    local key
178
+    local value
179
+    while IFS= read line;
180
+    do
181
+        line=$(sed -re 's/^\s*//' <<<"$line")
182
+        key=$(sed -re 's/\s*=.*//; s/^\s*//' <<<"$line")
183
+        if $strict;
184
+        then
185
+            value=$(sed -re 's/[^=]*=//' <<<"$line")
186
+        else
187
+            value=$(sed -re 's/[^=]*=\s*//' <<<"$line")
188
+        fi
189
+        if test "$key" = "$wantkey";
190
+        then
191
+            echo "$value"
192
+        fi
193
+    done
194
+}
195
+
196
+__iniread__flt_section() {
197
+    # filter per section
198
+    local section_ok=false
199
+    local line
200
+    while IFS= read line;
201
+    do
202
+        if grep -qse "^\[$wantsection\]" <<<"$line";
203
+        then
204
+            section_ok=true
205
+        elif grep -qse "^\[" <<<"$line";
206
+        then
207
+            section_ok=false
208
+        elif $section_ok;
209
+        then
210
+            $strict || line="$(sed -re 's/^\s*//' <<<"$line")"
211
+            echo "$line"
212
+        fi
213
+    done
214
+}
215
+
216
+__iniread__merge() {
217
+    local spec="$1"
218
+    local file=""
219
+    local dirs="/etc/ffood $HOME/.ffood"
220
+    local p
221
+    case $spec in
222
+        -|*/*)          # stdin, or path (with slash)
223
+            cat "$spec"
224
+            ;;
225
+        "")             # name not given
226
+            for p in $dirs;
227
+            do
228
+                debug -v p
229
+                cat $p/ffood.ini 2>/dev/null
230
+            done
231
+            cat .ffood.ini 2>/dev/null
232
+            ;;
233
+        *)              # name given
234
+            for p in $dirs;
235
+            do
236
+                debug -v p
237
+                cat $p/$spec 2>/dev/null
238
+            done
239
+            ;;
240
+    esac
241
+    true
242
+}
243
+
244
+iniread() {
245
+    #
246
+    # A flexible (not just) .ini file reader
247
+    #
248
+    # Can read anything from commented plaintext to keyless section INI,
249
+    # sectionless keyed INI or sectioned keyed INI, including multi-line
250
+    # and whitespace-safe chunks.
251
+    #
252
+    # Is constantly becoming smarter and smarter.
253
+    #
254
+    local file="-"
255
+    local wantsection=""
256
+    local wantkey=""
257
+    local strict=false
258
+    local section_ok=true
259
+    local one_line=false
260
+    while true;
261
+    do
262
+        case $1 in
263
+            -1|--one-line)
264
+                one_line=true
265
+                shift 1
266
+                ;;
267
+            -k|--key)
268
+                wantkey="$2"
269
+                shift 2
270
+                ;;
271
+            -p|--path)
272
+                wantkey="$(echo $2 | rev | cut -d. -f1 | rev)"
273
+                wantsection="${2%.$wantkey}"
274
+                shift 2
275
+                ;;
276
+            -s|--section)
277
+                wantsection="$2"
278
+                section_ok=false
279
+                shift 2
280
+                ;;
281
+            -S|--strict)
282
+                strict=true
283
+                shift 1
284
+                ;;
285
+            -l|--list-sections)
286
+                #TODO: list sections
287
+                warn "--list-sections is not implemented"
288
+                shift
289
+                ;;
290
+            -L|--list-keys)
291
+                #TODO: list keys as section/key (with -s, list keys only)
292
+                warn "--list-keys is not implemented"
293
+                shift
294
+                ;;
295
+            --)
296
+                file=$2
297
+                break
298
+                ;;
299
+            "")
300
+                break
301
+                ;;
302
+            *)
303
+                file=$1
304
+                break
305
+                ;;
306
+        esac
307
+    done
308
+
309
+    flt_section=__iniread__cat
310
+    flt_key=__iniread__cat
311
+    limit_line=__iniread__cat
312
+    test -n "$wantsection" && flt_section=__iniread__flt_section
313
+    test -n "$wantkey" && flt_key=__iniread__flt_key
314
+    $one_line && limit_line="head -1"
315
+
316
+    debug -v file:wantkey:wantsection
317
+
318
+    __iniread__merge $file \
319
+        | __iniread__flt_comments \
320
+        | $flt_section \
321
+        | $flt_key \
322
+        | $limit_line
323
+}

+ 86
- 0
include/proj_ol.sh View File

@@ -0,0 +1,86 @@
1
+#!/bin/bash
2
+
3
+ffood import core
4
+ffood import recon
5
+ffood import testing
6
+ffood import yummy
7
+
8
+
9
+OLCS_RUNHOW=$(iniread -s run.how proj-ol.ini)
10
+OLCS_VGLOG="cimserver-valgrind.log"
11
+OLCS_VG="valgrind --trace-children=yes --log-file=$OLCS_VGLOG"
12
+OLCS_GDBFIFO="/tmp/gdbfifo.$$"
13
+
14
+disable_pam_for() {
15
+    echo "disabling PAM for $1"
16
+    sed -i -e 's/^[^#].* pam_/# \0/' /etc/pam.d/$1
17
+}
18
+
19
+start_cimserver() {
20
+    local cmd="cimserver"
21
+    local args="daemon=false"
22
+    local out="cimserver.out"
23
+    local err="cimserver.err"
24
+    register_artifact "$out" "$err"
25
+    case $OLCS_RUNHOW in
26
+        simple)
27
+            $cmd $args > $out 2>$err &
28
+            ;;
29
+        service)
30
+            systemctl start tog-pegasus
31
+            ;;
32
+        gdb)
33
+            yum_install_if_needed gdb
34
+            rm -f $OLCS_GDBFIFO
35
+            mkfifo $OLCS_GDBFIFO
36
+            gdb cimserver 2>$err < $OLCS_GDBFIFO | tee $out &
37
+            echo  "run $args" > $OLCS_GDBFIFO
38
+            ;;
39
+        valgrind)
40
+            yum_install_if_needed valgrind
41
+            disable_pam_for wbem
42
+            chmod -s /usr/sbin/unix_chkpwd
43
+            register_artifact "$OLCS_VGLOG"
44
+            $OLCS_VG $cmd $args > $out 2>$err &
45
+            ;;
46
+    esac
47
+    wait_until -t 20 port_listening 5989
48
+}
49
+
50
+stop_cimserver() {
51
+    echo "stopping cimserver"
52
+    case $OLCS_RUNHOW in
53
+        simple)
54
+            killall cimserver
55
+            ;;
56
+        service)
57
+            systemctl stop tog-pegasus
58
+            ;;
59
+        gdb)
60
+            killall cimserver
61
+            echo bt > $OLCS_GDBFIFO
62
+            echo quit > $OLCS_GDBFIFO
63
+            echo y > $OLCS_GDBFIFO
64
+            rm -f $OLCS_GDBFIFO
65
+            ;;
66
+        valgrind)
67
+            killall -r ^memcheck-
68
+            ;;
69
+    esac
70
+    wait_until -t 20 -e ! pids_matching cimserver,^memcheck-
71
+}
72
+
73
+comment_cimserver() {
74
+    case $OLCS_RUNHOW in
75
+        simple)
76
+            echo "as a separate process"
77
+            ;;
78
+        service)
79
+            echo "as a service"
80
+            ;;
81
+        gdb|valgrind)
82
+            echo "under $OLCS_RUNHOW"
83
+            ;;
84
+    esac
85
+}
86
+

+ 193
- 0
include/recon.sh View File

@@ -0,0 +1,193 @@
1
+#!/bin/bash
2
+
3
+ffood import core
4
+
5
+
6
+age_of_leaf() {
7
+    local now=$1
8
+    sed 's/.*/"&"/' \
9
+        | xargs stat -c %Z \
10
+        | while read ctime;
11
+          do echo $(($now - $ctime));
12
+          done
13
+}
14
+
15
+age_of_tree() {
16
+    local now=$(date +%s)
17
+    find -L "$1" \
18
+        | age_of_leaf $now \
19
+        | sort -n \
20
+        | head -1
21
+}
22
+
23
+cat_uri() {
24
+    wget -q $1 -O - || echo "ERROR: $?" >&2
25
+}
26
+
27
+filter() {
28
+    local silent
29
+    while true; do case $1 in
30
+        -s|--silent) silent=true; shift ;;
31
+        *) break ;;
32
+    esac done
33
+    debug "\$*=$*"
34
+    while read item;
35
+    do
36
+        if $* $item;
37
+        then
38
+            echo "$item"
39
+        fi
40
+    done
41
+}
42
+
43
+pids_matching() {
44
+    local all_pids=""
45
+    local pids=""
46
+    local pfx=""
47
+    local pattern
48
+    for pattern in "$@";
49
+    do
50
+        local pids=$(ps -e -o pid= -o comm= \
51
+                     | grep $pattern \
52
+                     | sed -e 's/^ *//' \
53
+                     | cut -d\  -f 1 \
54
+                     | tr "\n" " ")
55
+        debug -v pattern:pids
56
+        all_pids="$all_pids$pfx$pids"
57
+        pfx=" "
58
+    done
59
+    debug -v all_pids
60
+    echo $all_pids
61
+    test -n "$all_pids"
62
+}
63
+
64
+port_listening() {
65
+    local host="localhost"
66
+    local port="$1"
67
+    debug -v host:port
68
+    test -n "$port" || usagef "PORT"
69
+    netstat -ntlp \
70
+        | sed -e 's/  */ /g' \
71
+        | cut -d\  -f 4 \
72
+        | grep -qs :$port\$
73
+}
74
+
75
+reachable_by_ping() {
76
+    local host=$1
77
+    debug -v host
78
+    test -n "$host" || usagef "HOST"
79
+    ping -w 1 $host >& /dev/null
80
+}
81
+
82
+reachable_by_ssh() {
83
+    local host=$1
84
+    debug -v host
85
+    test -n "$host" || usagef "HOST"
86
+    ssh -n -o ConnectTimeout=3 $host -- true >/dev/null 2>&1;
87
+}
88
+
89
+reachable_by_tcp() {
90
+    local port=$1
91
+    local host=$2
92
+    debug -v port:host
93
+    test -n "$host" -a -n "$port" || usagef "PORT HOST"
94
+    nc -w 1 $host $port >/dev/null 2>&1;
95
+}
96
+
97
+filter_hosts() {
98
+    local do_ping=true
99
+    local do_ssh=false
100
+    local do_tcp=false
101
+    local tcp_port=0
102
+
103
+    while true;
104
+    do
105
+        case $1 in
106
+            -t|--tcp)
107
+                do_tcp=true
108
+                tcp_port=$2
109
+                shift 2
110
+                ;;
111
+            -p|--ping)
112
+                do_ping=true
113
+                shift 1
114
+                ;;
115
+            -P|--no-ping)
116
+                do_ping=false
117
+                shift 1
118
+                ;;
119
+            -s|--ssh)
120
+                do_ssh=true
121
+                shift 1
122
+                ;;
123
+            -S|--no-ssh)
124
+                do_ssh=false
125
+                shift 1
126
+                ;;
127
+            "")
128
+                break
129
+                ;;
130
+            *)
131
+                usagef "[-p|P] [-s|-S] [-t port]"
132
+                return 2
133
+                ;;
134
+        esac
135
+    done
136
+
137
+    local ping_fun=true
138
+    local ssh_fun=true
139
+    local tcp_fun=true
140
+    $do_ping    && ping_fun="reachable_by_ping"
141
+    $do_tcp     && tcp_fun="reachable_by_tcp $tcp_port"
142
+    $do_ssh     && ssh_fun="reachable_by_ssh"
143
+    filter $ping_fun | filter $tcp_fun | filter $ssh_fun
144
+}
145
+
146
+sort_paths_by_age() {
147
+    while read path;
148
+    do echo "$(age_of_tree $path) $path"
149
+    done \
150
+      | sort -n \
151
+      | cut -d\  -f 2-
152
+}
153
+
154
+wait_until() {
155
+    local timeout=10
156
+    local delay=1
157
+    local use_eval=false
158
+    while true; do case "$1" in
159
+        -e) use_eval=true; shift; break ;;
160
+        -d) delay="$2"; shift 2;        ;;
161
+        -t) timeout="$2"; shift 2;      ;;
162
+        --) shift 1; break;             ;;
163
+        *)  break;                      ;;
164
+    esac done
165
+    think "waiting for: $@"
166
+    local elapsed=0
167
+    local start=$(date +%s)
168
+    while true;
169
+    do
170
+        sleep $delay
171
+        local now=$(date +%s)
172
+        local elapsed=$(($now - $start))
173
+        local rv=0
174
+        if $use_eval;
175
+        then
176
+            eval $@;
177
+            rv=$?
178
+        else
179
+            $@;
180
+            rv=$?
181
+        fi
182
+        if [ $rv -eq 0 ];
183
+        then
184
+            return 0;
185
+        fi
186
+        if test $elapsed -gt $timeout;
187
+        then
188
+            warn "timeout reached when waiting: $elapsed > $timeout"
189
+            return 1
190
+        fi
191
+        think "waiting for another $delay s"
192
+    done
193
+}

+ 32
- 0
include/sw.sh View File

@@ -0,0 +1,32 @@
1
+#!/bin/bash
2
+
3
+ffood import core
4
+ffood import yummy
5
+
6
+any_install() {
7
+    local tool pkg
8
+    sed -e 's/^\s*//; s/\s*=\s*/=/;' \
9
+      | while read line;
10
+        do
11
+            tool=$(cut -d= -f1 <<<"$line")
12
+            pkg=$(cut -d= -f2 <<<"$line")
13
+            debug -v line:tool:pkg
14
+            think "installing $pkg"
15
+            case $tool in
16
+                cpan)
17
+                    yum_install_if_needed perl-CPAN
18
+                    cpan $pkg
19
+                    ;;
20
+                pypi)
21
+                    yum_install_if_needed python-setuptools
22
+                    easy_install -q $pkg
23
+                    ;;
24
+                yum)
25
+                    yum_install_if_needed $pkg
26
+                    ;;
27
+                *)
28
+                    warn "unsupported tool: $tool"
29
+                    ;;
30
+            esac
31
+        done
32
+}

+ 30
- 0
include/testing.sh View File

@@ -0,0 +1,30 @@
1
+#!/bin/bash
2
+
3
+ffood import core
4
+
5
+FFOOD_ARTIFACTS_DIR=artifacts
6
+
7
+collect_artifacts() {
8
+    test -f $TMP_DIR/artifact_list || return 0
9
+    local tgt
10
+    echo "collecting artifacts to $FFOOD_ARTIFACTS_DIR"
11
+    cat $TMP_DIR/artifact_list \
12
+        | while read path;
13
+          do
14
+              tgt=$FFOOD_ARTIFACTS_DIR/$(dirname $path)
15
+              mkdir -p $tgt
16
+              cp -r "$path" "$tgt"
17
+          done
18
+}
19
+
20
+register_artifact() {
21
+    local list=$TMP_DIR/artifact_list
22
+    local a
23
+    for a in "$@";
24
+    do
25
+        local dn=$(cd $(dirname $a); pwd)
26
+        test "$dn" = "/" && dn=""   # hack: avoid "//" if path was abs
27
+        local abspath="$dn/$(basename $a)"
28
+        append_if_missing  "$abspath" $list
29
+    done
30
+}

+ 95
- 0
include/www.sh View File

@@ -0,0 +1,95 @@
1
+#!/bin/bash
2
+
3
+ffood import core
4
+
5
+filter_ids() {
6
+    #
7
+    # Hack doer-like id's (ID#123) out of the text.
8
+    #
9
+    tr ' ' '\n' \
10
+      | perl -ne '
11
+            next unless m/\b([a-zA-Z]{2,}#\d+)\b/;
12
+            print "$1\n";
13
+        ' \
14
+      | debug_pipe id_lookalikes
15
+}
16
+
17
+filter_kws() {
18
+    #
19
+    # Hack out lines that look like kw expressions.
20
+    #
21
+    local kwbase="[a-z][a-z0-9]*"
22
+    grep -e "^$kwbase " -e "^$kwbase\$" \
23
+        | debug_pipe kw_lookalikes
24
+}
25
+
26
+filter_uris() {
27
+    #
28
+    # Hack URIs out of the text.
29
+    #
30
+    tr ' ' '\n' \
31
+      | perl -ne '
32
+            next unless m|(\bhttps?://[[:alnum:]_:/.?&%=-]+)\b|;
33
+            print "$1\n";
34
+        ' \
35
+      | debug_pipe uri_lookalikes
36
+}
37
+
38
+find_uri() {
39
+    #
40
+    # Scan stdin for what looks like URI, ID or keyword
41
+    #
42
+    # Output URIS: first what were apparent uris, then IDs converted to
43
+    # URIs, then things that looked like kw expressions, converted to
44
+    # URIs.
45
+    #
46
+    # Apply this filter to args or clipboard, and either use head -1 or
47
+    # if you are brave, open all URIs.
48
+    #
49
+    local d=$(mktemp -d)
50
+    pushd $d >&/dev/null
51
+        ##
52
+        # heat up and fill pipes
53
+        #
54
+        mkfifo maybe_uris maybe_ids maybe_kws \
55
+               uris uris_from_ids uris_from_kws
56
+        tee maybe_uris | tee maybe_ids | tee maybe_kws | cat >/dev/null &
57
+        ##
58
+        # process each pipe *async* by different filter
59
+        #
60
+        cat maybe_uris | filter_uris                       > uris &
61
+        cat maybe_ids  | filter_ids  | tr '#' ' ' | kw2uri > uris_from_ids &
62
+        cat maybe_kws  | filter_kws  | kw2uri              > uris_from_kws &
63
+        ##
64
+        # print result *sync* in correct order
65
+        #
66
+        cat uris
67
+        cat uris_from_ids
68
+        cat uris_from_kws
69
+    popd >&/dev/null
70
+    rm -rf $d
71
+}
72
+
73
+kw2uri() {
74
+    #
75
+    # Turn keyword or query (like "g hello" for google) to URI
76
+    #
77
+    local line
78
+    declare -l line
79
+    while read line;
80
+    do
81
+        line="$line "
82
+        local kw=${line%% *}
83
+        local query=${line#$kw }
84
+        debug -v kw:query
85
+        if test -n "$query";
86
+        then
87
+            local fmt=$(iniread -1 -p www.query.$kw www.ini)
88
+            debug -v fmt
89
+            printf "$fmt\n" "$query"
90
+        else
91
+            iniread -1 -p www.bookmark.$kw www.ini
92
+        fi
93
+    done
94
+}
95
+

+ 9
- 0
include/xorg.sh View File

@@ -0,0 +1,9 @@
1
+#!/bin/bash
2
+
3
+ffood import core
4
+
5
+clipln() {
6
+    xclip -o -selection primary 2>/dev/null
7
+    echo ""
8
+}
9
+

+ 107
- 0
include/yummy.sh View File

@@ -0,0 +1,107 @@
1
+#!/bin/bash
2
+
3
+guess_pkgnames() {
4
+    # guess interesting names from folder of RPMs
5
+    ls "$1" \
6
+      | grep rpm\$ \
7
+      | sed -e 's/-[0-9].*$//' \
8
+      | sort \
9
+      | uniq
10
+}
11
+
12
+guess_rtag() {
13
+    uname -r | sed -e 's/^[.0-9-]*//; s/\..*$//'
14
+}
15
+
16
+guess_rtagn() {
17
+    echo $(guess_rtag) | sed -e 's/[0-9]*$//'
18
+}
19
+
20
+installed_versions() {
21
+    # for every prefix print installed versions
22
+    cat - \
23
+        | while read name;
24
+          do rpm -qa "$name*";
25
+          done \
26
+            | sort \
27
+            | uniq
28
+}
29
+
30
+nvc_parse() {
31
+    local what="$1"
32
+    local nvc="$2"
33
+    test -n "$2" || warn "usage: nvc_parse WHAT NVC"
34
+    local arch="${nvc##*.}"
35
+    local rest="${nvc%%.$arch}"
36
+    local release="${rest##*-}"
37
+    local rest="${rest%%-$release}"
38
+    local version="${rest##*-}"
39
+    local name="${rest%-*}"
40
+    case $what in
41
+        arch)
42
+            echo $arch
43
+            ;;
44
+        release)
45
+            echo $release
46
+            ;;
47
+        version)
48
+            echo $version
49
+            ;;
50
+        name)
51
+            echo $name
52
+            ;;
53
+        *)
54
+            warn "WHAT = [arch|release|version|name]"
55
+            return 1
56
+    esac
57
+}
58
+
59
+save_repo_for() {
60
+    local target=$1
61
+    local rtagn=$(guess_rtagn)
62
+    local uri=$(iniread -s $rtagn -k $target repo_uris.ini)
63
+    think "adding repo for $target"
64
+    debug -v target:rtagn:uri
65
+    case "$uri" in
66
+        INCLUDED)
67
+            ;;
68
+        NONE)
69
+            warn "no repo available for $target"
70
+            return 1
71
+            ;;
72
+        *)
73
+            pushd /etc/yum.repos.d/ >/dev/null
74
+            wget -q "$uri"
75
+            popd >/dev/null
76
+            ;;
77
+    esac
78
+}
79
+
80
+yum_preerase() {
81
+    # read package names from stdin and pre-erase them
82
+    cat - \
83
+        | while read pkgname;
84
+          do
85
+              if rpm -q "$pkgname" 2>/dev/null 1>&2;
86
+              then
87
+                  echo "pre-erasing $pkgname"
88
+                  yum -q -y erase "$pkgname"
89
+              fi
90
+          done
91
+}
92
+
93
+yum_install() {
94
+    yum -q -y install "$@" 2>&1 | mute_known yum
95
+}
96
+
97
+yum_install_if_needed() {
98
+    local pkg
99
+    for pkg in "$@";
100
+    do
101
+        rpm -q $pkg >& /dev/null || yum_install $pkg;
102
+    done
103
+}
104
+
105
+yum_update() {
106
+    yum -q -y update "$@" 2>&1 | mute_known yum
107
+}

+ 10
- 0
notes/BUGS.md View File

@@ -0,0 +1,10 @@
1
+BUGS
2
+====
3
+
4
+  * iniread: when same key is found in e.g. /etc/ffood.ffood.ini
5
+    and ~/.ffood.ffood.ini, output is concatenated.  If you want
6
+    the value be rather overriden, you can simply add `-1` to
7
+    limit output to the last one but that obviously won't work
8
+    for multi-line values.
9
+
10
+    It's not yet decided what should be the behavior.

+ 52
- 0
notes/guidelines.md View File

@@ -0,0 +1,52 @@
1
+
2
+UI
3
+--
4
+
5
+*   Heavily prefer unix filter UI.
6
+
7
+    If you can't do it with filtering, it could mean you should split your
8
+    function anyway.
9
+
10
+*   Even function can use dash options and even `usagef()`.
11
+
12
+*   Reserved options are
13
+
14
+     *  `-q|--quiet`, to turn off verbosity,
15
+     *  `-v|--verbose`, to turn on verbosity,
16
+     *  and `-d|--debug` to turn on debug output (stderr).
17
+
18
+*   Do not `think()` in functions.
19
+
20
+*   Preferred capitalization in messages is:
21
+
22
+    *   all small for libs (debug/warn/die)
23
+
24
+    *   First cap for scripts
25
+
26
+*   Message width:
27
+
28
+    *   think/warn/die: try hard to never exceed 72
29
+
30
+    *   debug: do what you must
31
+
32
+    *   always try to split message to fixed part, colon and  *before* colon and
33
+        the "data" part after the colon, e.g.:
34
+
35
+            file missing: /var/run/media/somebody/some-medium/some-long/path
36
+
37
+        instead of:
38
+
39
+            file /var/run/media/somebody/some-medium/some-long/path is missing
40
+
41
+        (even if you think that it will be short)
42
+
43
+
44
+
45
+
46
+PRINCIPLES
47
+----------
48
+
49
+Be smart but honest: if you can default, default, otherwise be honest = fail
50
+
51
+Don't talk.  `think()` instead.
52
+

+ 121
- 0
setup/mk.sh View File

@@ -0,0 +1,121 @@
1
+#!/bin/bash
2
+# ffood - Fast Food - a Bash Library
3
+# See LICENSE file for copyright and license details.
4
+
5
+tmp=$(mktemp)
6
+sed -e 's/ = /=/' < config.mk > $tmp
7
+. $tmp
8
+rm -f $tmp
9
+
10
+bindir=${DESTDIR}${PREFIX}/bin
11
+mandir=${DESTDIR}${MANPREFIX}
12
+docdir=${DESTDIR}${PREFIX}/share/doc/ffood
13
+shrdir=${DESTDIR}${PREFIX}/share/ffood
14
+
15
+list_of_bins() {
16
+    echo bin/fffun
17
+}
18
+
19
+list_of_installed_bins() {
20
+    list_of_bins | sed -e "s/bin/$(sed -e 's/\//\\\//g' <<<$bindir)/"
21
+}
22
+
23
+list_of_docs() {
24
+    echo doc/fffun.1.md
25
+    echo doc/ffood.3.md
26
+}
27
+
28
+list_of_shrs() {
29
+    echo ffood.sh
30
+    echo include
31
+}
32
+
33
+clean() {
34
+    test -f built.list && {
35
+        cat built.list | xargs rm -f
36
+        rm -f built.list
37
+    } || :
38
+}
39
+
40
+dist() {
41
+    local dirname=ffood-${VERSION}
42
+    mkdir -p $dirname
43
+    cp -R   bin \
44
+            config.mk \
45
+            doc \
46
+            include \
47
+            Makefile \
48
+            ffood.sh.in \
49
+            README \
50
+            LICENSE \
51
+            setup \
52
+            test \
53
+            $dirname
54
+    tar -cf $dirname.tar $dirname
55
+    gzip $dirname.tar
56
+    rm -rf $dirname
57
+    echo $dirname.tar.gz >> built.list
58
+}
59
+
60
+install() {
61
+    mkdir -p $bindir \
62
+             $docdir \
63
+             $shrdir
64
+    list_of_bins | xargs cp -vrt $bindir
65
+    list_of_docs | xargs cp -vrt $docdir
66
+    list_of_shrs | xargs cp -vrt $shrdir
67
+    list_of_installed_bins | xargs chmod 755
68
+    test -f .autoclean && clean || :
69
+}
70
+
71
+manpages() {
72
+    ronn -r doc/*.[1-9].md
73
+    ls doc/*.[1-9] >> built.list
74
+}
75
+
76
+install_manpages() {
77
+    cp -vr doc/*.1 $mandir/man1
78
+    cp -vr doc/*.3 $mandir/man3
79
+    test -f .autoclean && clean || :
80
+}
81
+
82
+ffood() {
83
+    local srcpath dstpath
84
+    find -type f -name '*.in' \
85
+        | while read srcpath;
86
+          do
87
+              dstpath=${srcpath%.in}
88
+              perl -pe "s|__FFOOD_DIR__|$shrdir|;
89
+                        s|__VERSION__|$VERSION|;" < $srcpath > $dstpath
90
+              echo $dstpath >> built.list
91
+          done
92
+}
93
+
94
+run_test() {
95
+    pushd test
96
+    find -maxdepth 1 -type f \! -name '*.in' | while read test;
97
+    do
98
+        chmod 0755 $test
99
+        $test || exit $?
100
+    done
101
+    popd
102
+}
103
+
104
+uninstall() {
105
+    list_of_installed_bins | xargs rm -f
106
+    rm -rf $shrdir/ffood
107
+    rm -rf $docdir/ffood
108
+    rm -f $mandir/man1/fffun.1
109
+    rm -f $mandir/man3/ffood.3
110
+}
111
+
112
+case $1 in
113
+    clean|dist|install|install_manpages|manpages|ffood|uninstall)
114
+        $1
115
+        ;;
116
+    test)
117
+        run_test
118
+        ;;
119
+    *)
120
+        echo "usage: $(basename $0) clean|dist|install|ffood|test|uninstall" >&2
121
+esac

+ 2
- 0
test/data/iniread/oracle1 View File

@@ -0,0 +1,2 @@
1
+hello
2
+hello1

+ 2
- 0
test/data/iniread/oracle10 View File

@@ -0,0 +1,2 @@
1
+someThing
2
+also=someThing

+ 3
- 0
test/data/iniread/oracle11 View File

@@ -0,0 +1,3 @@
1
+things.that
2
+things.this
3
+words.this

+ 2
- 0
test/data/iniread/oracle12 View File

@@ -0,0 +1,2 @@
1
+things
2
+words

+ 2
- 0
test/data/iniread/oracle13 View File

@@ -0,0 +1,2 @@
1
+that
2
+this

+ 3
- 0
test/data/iniread/oracle2 View File

@@ -0,0 +1,3 @@
1
+box
2
+cat
3
+man

+ 2
- 0
test/data/iniread/oracle3 View File

@@ -0,0 +1,2 @@
1
+something
2
+also=something

+ 2
- 0
test/data/iniread/oracle4 View File

@@ -0,0 +1,2 @@
1
+someThing
2
+also=someThing

+ 2
- 0
test/data/iniread/oracle5 View File

@@ -0,0 +1,2 @@
1
+someThing
2
+also=someThing

+ 3125
- 0
test/data/iniread/oracle6
File diff suppressed because it is too large
View File


+ 15
- 0
test/data/iniread/oracle7 View File

@@ -0,0 +1,15 @@
1
+#!/usr/bin/python
2
+
3
+
4
+class Myclass(object):
5
+
6
+    def __init__(self, status="OK"):
7
+        self.status = status
8
+
9
+    def check(self):
10
+        print "I guess I'm %s" % self.status
11
+
12
+
13
+if __name__ == "__main__":
14
+    c = Myclass()
15
+    c.check()

+ 15
- 0
test/data/iniread/oracle8 View File

@@ -0,0 +1,15 @@
1
+#!/usr/bin/python
2
+
3
+
4
+class Myclass(object):
5
+
6
+	def __init__(self, status="OK"):
7
+		self.status = status
8
+
9
+	def check(self):
10
+		print "I guess I'm %s" % self.status
11
+
12
+
13
+if __name__ == "__main__":
14
+	c = Myclass()
15
+	c.check()

+ 5
- 0
test/data/iniread/oracle9 View File

@@ -0,0 +1,5 @@
1
+[funny things
2
+or=other[funny[things
3
+here in the middle of
4
+sed]ction
5
+=before

+ 3
- 0
test/data/iniread/test1 View File

@@ -0,0 +1,3 @@
1
+# plain # --
2
+hello
3
+hello1

+ 12
- 0
test/data/iniread/test10 View File

@@ -0,0 +1,12 @@
1
+# path # -p things.this
2
+[things]
3
+nothing
4
+this=someThing
5
+this=also=someThing
6
+that=nothing
7
+that=also=nothing
8
+[words]
9
+word
10
+this=curseword
11
+this=bad=word
12
+another word

+ 12
- 0
test/data/iniread/test11 View File

@@ -0,0 +1,12 @@
1
+# list paths # -L paths
2
+[things]
3
+nothing
4
+this=someThing
5
+this=also=someThing
6
+that=nothing
7
+that=also=nothing
8
+[words]
9
+word
10
+this=curseword
11
+this=bad=word
12
+another word

+ 12
- 0
test/data/iniread/test12 View File

@@ -0,0 +1,12 @@
1
+# list sections # -L sections
2
+[things]
3
+nothing
4
+this=someThing
5
+this=also=someThing
6
+that=nothing
7
+that=also=nothing
8
+[words]
9
+word
10
+this=curseword
11
+this=bad=word
12
+another word

+ 12
- 0
test/data/iniread/test13 View File

@@ -0,0 +1,12 @@
1
+# list keys # -L keys
2
+[things]
3
+nothing
4
+this=someThing
5
+this=also=someThing
6
+that=nothing
7
+that=also=nothing
8
+[words]
9
+word
10
+this=curseword
11
+this=bad=word
12
+another word

+ 12
- 0
test/data/iniread/test2 View File

@@ -0,0 +1,12 @@
1
+# sections only # -s words
2
+[greetings]
3
+hello
4
+hello1
5
+[words]
6
+box
7
+cat
8
+man
9
+[sword]
10
+short
11
+long
12
+broad

+ 6
- 0
test/data/iniread/test3 View File

@@ -0,0 +1,6 @@
1
+# keys only # -k this
2
+nothing
3
+this=something
4
+this=also=something
5
+that=nothing
6
+that=also=nothing

+ 12
- 0
test/data/iniread/test4 View File

@@ -0,0 +1,12 @@
1
+# both keys and sections # -s things -k this
2
+[things]
3
+nothing
4
+this=someThing
5
+this=also=someThing
6
+that=nothing
7
+that=also=nothing
8
+[words]
9
+word
10
+this=curseword
11
+this=bad=word
12
+another word

+ 12
- 0
test/data/iniread/test5 View File

@@ -0,0 +1,12 @@
1
+# keys, sections and spaces # -s things -k this
2
+[things]
3
+    nothing
4
+	this=someThing
5
+    this=also=someThing
6
+	that=nothing
7
+    that=also=nothing
8
+[words]
9
+    word
10
+	this=curseword
11
+	this=bad=word
12
+	another word

+ 3127
- 0
test/data/iniread/test6
File diff suppressed because it is too large
View File


+ 17
- 0
test/data/iniread/test7 View File

@@ -0,0 +1,17 @@
1
+# tricks with strict and script # -S -s needs_strict -k py
2
+[needs_strict]
3
+py =#!/usr/bin/python
4
+py =
5
+py =
6
+py =class Myclass(object):
7
+py =
8
+py =    def __init__(self, status="OK"):
9
+py =        self.status = status
10
+py =
11
+py =    def check(self):
12
+py =        print "I guess I'm %s" % self.status
13
+py =
14
+py =
15
+py =if __name__ == "__main__":
16
+py =    c = Myclass()
17
+py =    c.check()

+ 17
- 0
test/data/iniread/test8 View File

@@ -0,0 +1,17 @@
1
+# tricks with strict and script # -S -s needs_strict -k py
2
+[needs_strict]
3
+py =#!/usr/bin/python
4
+py =
5
+py =
6
+py =class Myclass(object):
7
+py =
8
+py =	def __init__(self, status="OK"):
9
+py =		self.status = status
10
+py =
11
+py =	def check(self):
12
+py =		print "I guess I'm %s" % self.status
13
+py =
14
+py =
15
+py =if __name__ == "__main__":
16
+py =	c = Myclass()
17
+py =	c.check()

+ 12
- 0
test/data/iniread/test9 View File

@@ -0,0 +1,12 @@
1
+# tricks with strict and script # -s "funny/ in"
2
+[funny/ in]
3
+    [funny things
4
+    or=other[funny[things
5
+    here in the middle of
6
+    sed]ction
7
+=before
8
+[other section]
9
+which is
10
+not
11
+ [funny/ in]
12
+    but other 

+ 40
- 0
test/iniread.in View File

@@ -0,0 +1,40 @@
1
+#!/bin/bash
2
+
3
+. /usr/share/beakerlib/beakerlib.sh
4
+
5
+. __FFOOD_DIR__/qecc.sh
6
+ffood import core
7
+
8
+
9
+do_test() {
10
+    local n=$1
11
+    local head=$(cat "test$n" | head -1 | sed -e 's/\s*#\s*/#/g')
12
+    local name=$(cut -d\# -f 2 <<<"$head")
13
+    local args=$(cut -d\# -f 3 <<<"$head")
14
+    rlPhaseStartTest "$name"
15
+        rlRun "iniread $args < test$n > result$n"
16
+        rlRun "diff -u oracle$n result$n"
17
+        rlGetPhaseState || rlLogInfo "cat test$n"
18
+    rlPhaseEnd
19
+}
20
+
21
+
22
+rlJournalStart
23
+
24
+    rlPhaseStartSetup
25
+        tmp=$(mktemp -d)
26
+        cp $(dirname $0)/data/iniread/* $tmp
27
+        pushd $tmp
28
+    rlPhaseEnd
29
+
30
+    for n in $(seq 1 13);
31
+    do
32
+        do_test $n
33
+    done
34
+
35
+    rlPhaseStartCleanup
36
+        popd
37
+        rm -rf $tmp
38
+    rlPhaseEnd
39
+
40
+rlJournalEnd

+ 66
- 0
test/test_iniread.py View File

@@ -0,0 +1,66 @@
1
+#!/usr/bin/python
2
+
3
+import operator
4
+import subprocess
5
+import unittest
6
+
7
+from sznqalibs import hoover
8
+
9
+
10
+class PyinireadDriver(hoover.BaseTestDriver):
11
+
12
+    def _get_data(self):
13
+        out = ""
14
+        with open(self._args['file']) as fh:
15
+            for x in fh.readlines():
16
+                if not x.startswith("#"):
17
+                    out += x
18
+        self.data['stdout'] = out
19
+
20
+
21
+class InireadDriver(hoover.BaseTestDriver):
22
+
23
+    plain_args = ['file']
24
+    params = ['-k', '-s']
25
+    switches = ['-d', '-1']
26
+
27
+    def _get_data(self):
28
+        args = ['fffun', 'iniread']
29
+        for key in self._args['order'].split(','):
30
+            value = self._args[key]
31
+            if key in self.switches:
32
+                if value:
33
+                    args.append(key)
34
+            elif key in self.params:
35
+                if value is not None:
36
+                    args += [key, value]
37
+            else:
38
+                if value is not None:
39
+                    args.append(value)
40
+        self.data['stdout'] = subprocess.check_output(args)
41
+
42
+
43
+class TestCase(unittest.TestCase):
44
+
45
+    def setUp(self):
46
+        self.driver_class = InireadDriver
47
+
48
+    def test_simple(self):
49
+        argsrc = hoover.Cartman({
50
+            'order': ['-k,-s,file', '-s,-k,file'],
51
+            '-k': ['somekey', None, ''],
52
+            '-s': ['somesection', None, ''],
53
+            'file': './data/iniread/test1',
54
+        }, {
55
+            'order': hoover.Cartman.Iterable,
56
+            '-k': hoover.Cartman.Iterable,
57
+            '-s': hoover.Cartman.Iterable,
58
+            'file': hoover.Cartman.Scalar,
59
+        })
60
+        tests = [(operator.eq, InireadDriver, PyinireadDriver)]
61
+        tracker = hoover.regression_test(argsrc, tests)
62
+        self.assertFalse(tracker.errors_found(), tracker.format_report())
63
+
64
+
65
+if __name__ == '__main__':
66
+    unittest.main()