David Caro has uploaded a new change for review.

Change subject: Added the common libraries for the hooks to use
......................................................................

Added the common libraries for the hooks to use

 - bz.sh: functions to query bugzilla
 - conf.sh: configuration amangement functions
 - gerrit.sh: gerrit related functions
 - tools.sh: generic helper functions

Change-Id: I7a10060cff5c25e8bd8e2f73654208a90cec70d8
Signed-off-by: David Caro <dcaro...@redhat.com>
---
A hooks/lib/bz.sh
A hooks/lib/conf.sh
A hooks/lib/gerrit.sh
A hooks/lib/tools.sh
4 files changed, 806 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/gerrit-admin refs/changes/89/15389/1

diff --git a/hooks/lib/bz.sh b/hooks/lib/bz.sh
new file mode 100644
index 0000000..ac9f774
--- /dev/null
+++ b/hooks/lib/bz.sh
@@ -0,0 +1,424 @@
+#!/bin/bash -x
+###########
+## helpful functions to be used on the gerrit hook scripts
+source conf.sh
+source tools.sh
+
+
+#####
+# Usage:
+#   bz.get_bug [-p] bug_id
+#
+#  Get's the bug_id bug xml information from cache, or if not cached, from the
+#  server.
+#
+#  -p  Get it in plain text
+#
+bz.get_bug()
+{
+    local OPTIND
+    local options="&ctype=xml"
+    local btype="xml"
+    local clean_after='false'
+    while getopts "p" option; do
+        case $option in
+            p)
+                options=""
+                btype='plain'
+                ;;
+        esac
+    done
+    shift $((OPTIND-1))
+    local bug_id="${1?No bug id issued}"
+    local bug_cache="$(conf.t_get bz_${bug_id}_${btype})"
+    if [[ "$bug_cache" != "" ]] && [[ -f "$bug_cache" ]]; then
+        cat "$bug_cache"
+    else
+        local cookie_jar="$(conf.t_get bz_cookie_jar)"
+        [[ -f ${cookie_jar?You have to login to bugzilla first, see bz.login} 
]]
+        bug_cache="/tmp/bz_cache.$PPID.${bug_id}.${btype}"
+        wget -qO - \
+            --load-cookies "$cookie_jar" \
+            --save-cookies "$cookie_jar" \
+            "https://bugzilla.redhat.com/show_bug.cgi?id=${bug_id}${options}"; \
+        | tee "$bug_cache"
+        conf.t_put "bz_${bug_id}_${btype}" "$bug_cache"
+    fi
+}
+
+
+######
+# Usage:
+#   bz.update_bug bug_id [data1 [data2 [...]]]
+#
+#  Updates the given bug, returns 0 if updated, 1 otherwise
+#
+#    data
+#      Each of the post arameters to send (usually as name=value).
+#
+bz.update_bug()
+{
+    local bug_id="${1?No bug id passed}"
+    local param post_data rc bug_cache
+    local cookie_jar="$(conf.t_get bz_cookie_jar)"
+    [[ -f ${cookie_jar?You have to login to bugzilla first, see bz.login} ]]
+    shift
+    ## We also need the token and confirm_public_bug to avoid confirmation
+    ## page
+    for param in "token=$(bz.get_token $bug_id)" "confirm_public_bug=1" "$@"
+    do
+        post_data="${post_data:+$post_data&}$param"
+    done
+    wget -qO - \
+        --load-cookies "$cookie_jar" \
+        --save-cookies "$cookie_jar" \
+        --header "Referer: 
https://bugzilla.redhat.com/show_bug.cgi?id=$bug_id"; \
+        --post-data "$post_data" \
+        "https://bugzilla.redhat.com/process_bug.cgi?id=$bug_id"; \
+    | tee /tmp/update_bug_log.${bug_id} 2>/dev/null\
+    | grep -q "Changes submitted for"
+    rc=$?
+    if [[ $rc -eq 0 ]]; then
+        rm -f "/tmp/update_bug_log.${bug_id}"
+    else
+        echo "Error while updating bug #${bug_id} with post_data, response 
data"\
+             "at /tmp/update_bug_log.${bug_id}"
+        echo "Sent data: $post_data"
+    fi
+    ## clean the old bug data from all caches, if any
+    rm -f /tmp/bz_cache.*.${bug_id}.*
+    return $rc
+}
+
+
+######
+# Usage:
+#   bz.is_revert [commit]
+#
+#   Return 0 if the given commit is a revert, 1 otherwise
+#
+bz.is_revert()
+{
+    local commit=${1:-HEAD}
+    local line found
+    local revert_regexp='^This reverts commit ([[:alnum:]]+)$'
+    pushd "${GIT_DIR?}" &>/dev/null
+    while read line; do
+        if [[ "$line" =~ $revert_regexp ]]; then
+            found='true'
+        fi
+    done < <( git show "$commit" --quiet --format=%b )
+    popd &>/dev/null
+    [[ "$found" == "true" ]]
+}
+
+
+
+######
+# Usage:
+#   bz.get_bug_id [commit]
+#
+#  Extracts the bug ids from the Bug-Url in the given commit
+#  NOTE: If the patch is a 'revert', it extracts the bug from the reverted
+#        commit
+#
+bz.get_bug_id()
+{
+    local commit=${1:-HEAD}
+    local line found
+    local bug_regexp1='^Bug-Url: 
(https?://bugzilla\.redhat\.com/)show_bug\.cgi\?id=([[:digit:]]+)$'
+    local bug_regexp2='^Bug-Url: 
(https?://bugzilla\.redhat\.com/)([[:digit:]]+)$'
+    local revert_regexp='^This reverts commit ([[:alnum:]]+)$'
+    pushd "${GIT_DIR?}" &>/dev/null
+    while read line; do
+        if [[ "$line" =~ $revert_regexp ]]; then
+            commit_id="${BASH_REMATCH[1]}"
+            bz.get_bug_id "$commit_id"
+            return $?
+        fi
+        if [[ "$line"  =~ $bug_regexp1 || "$line"  =~ $bug_regexp2 ]]; then
+            echo "${BASH_REMATCH[2]}"
+            found='true'
+        fi
+    done < <( git show --quiet "$commit" --format=%b )
+    popd &>/dev/null
+    [[ "$found" == "true" ]]
+}
+
+
+######
+# Usage:
+#   bz.login [-s server_url] [-b bug_id] user password
+#
+#   Logs into bugzilla if not logged already.
+#
+#   -b bug_id
+#     If you pass a bug_id, the token for that bug will already be set and
+#     cached for further reference
+#
+#   -s server_url
+#     Use that url instead of the default one (https://bugzilla.redhat.com)
+#
+bz.login()
+{
+    local server_url="https://bugzilla.redhat.com";
+    local OPTIND bug_id plain_bug
+    while getopts "s:b:" option; do
+        case $option in
+            s) server_url="$OPTARG";;
+            i)
+                bug_id="$OPTARG"
+                plain_bug="/tmp/bz_cache.$PPID.${bug_id}.plain"
+                conf.t_put "bz_${bug_id}_plain" "$plain_bug"
+                ;;
+        esac
+    done
+    server_url="${server_url}${bug_id:+/show_bug.cgi?id=${bug_id}}"
+    shift $((OPTIND - 1))
+    local cookie_jar="$(conf.t_get bz_cookie_jar)"
+    if ! [[ -f "$cookie_jar" ]] ; then
+        local bz_user="${1?No user passed}"
+        local bz_password="${2?No password passed}"
+        [[ "$cookie_jar" == "" ]] \
+        && cookie_jar="/tmp/bz_cache.$PPID.cookies"
+        conf.t_put "bz_cookie_jar" "$cookie_jar"
+        wget -qO ${plain_bug:-/dev/null} --save-cookies "$cookie_jar" \
+            --post-data 
"Bugzilla_login=${bz_user//@/%40}&Bugzilla_password=${bz_password}&GoAheadAndLogIn=Log+in"
 \
+            "$server_url"
+    fi
+}
+
+
+######
+# Usage:
+#   bz.get_bug_flags bug_id
+#
+# Retrieves all the '+' flags of the given bug
+#
+bz.get_bug_flags()
+{
+    local bugid=${1?}
+    local line fname
+    local status_regexp='status=\"\+\"'
+    local flag_regexp='.*\<flag\ name=\"([^\"].*)\"'
+    while read line; do
+        if [[ "$line" =~ $flag_regexp ]]; then
+            fname="${BASH_REMATCH[1]}"
+        elif [[ "$line" =~ $status_regexp ]]; then
+            echo "$fname"
+        fi
+    done < <( bz.get_bug "$bugid" | grep -aPzo "(?s)^( *)[^#\n]*<flag[^>]*>" )
+}
+
+
+######
+# Usage:
+#   bz.get_bug_status bug_id
+#
+# Retrieves the current status of the bug
+#
+bz.get_bug_status()
+{
+    local bugid=${1?}
+    bz.get_bug "$bugid" \
+    | grep -aPzo "(?<=<bug_status>)[^<]*"
+}
+
+
+######
+# Usage:
+#   bz.check_flags bug_id [flagspec1 [flagspec2 [...]]]
+#
+# Checks that all the flags exist with '+' in the given bug
+#
+#     flagspec
+#       can be a single flag or a sequence ot flags separated by '|' to
+#       express that those flags are interchangeable
+#
+#  Ex: bz.check_flags 12345 flag1 flag2|flag2_bis flag3
+#
+bz.check_flags()
+{
+    local bug_id="${1?No bug id passed}"
+    shift
+    local flags missing_flags and_flag found or_flag
+    ## Check the flags
+    flags=($(bz.get_bug_flags $bug_id))
+    missing_flags=""
+    ## Flags are defined like this: flag1|flag2 flag3
+    ## That means fag1 or flag2 are required and flag3 is required
+    ## ' ' -> and, '|' -> or
+    for and_flag in "$@"; do
+        found=0
+        for or_flag in ${and_flag//|/ }; do
+            if tools.is_in "$or_flag" "${flags[@]}" >/dev/null; then
+                found=1
+            fi
+        done
+        if [[ $found -eq 0 ]]; then
+            missing_flags="${missing_flags:+$missing_flags, }$and_flag"
+        fi
+    done
+    if [[ "$missing_flags" != "" ]]; then
+        echo -e "No ${missing_flags} flag/s"
+        return 1
+    fi
+    echo -e "OK"
+    return 0
+}
+
+
+######
+# Usage:
+#   bz.get_token bug_id
+#
+# Gets the session token to be able to do submits (update a bug)
+#
+bz.get_token()
+{
+    bug_id=${1?No bug id passed}
+    bz.get_bug -p "$bug_id" \
+    | grep -Po "(?<=<input type=\"hidden\" name=\"token\" value=\")[^\"]*"
+}
+
+
+######
+# Usage:
+#   bz.add_tracker bug_id tracker_id external_id
+#
+#     tracker_id
+#       This is the internal tracker id that bugzilla assigns to
+#       each external tracker (RHEV gerrit -> 82, oVirt gerrit -> 81)
+#
+#     external_id
+#       Id for the bug in the external tracker
+#
+# Add a new external bug to the external bugs list
+bz.add_tracker()
+{
+    bug_id="${1?}"
+    tracker_id="${2?}"
+    external_id="${3?}"
+    bz.update_bug "$bug_id" \
+        "external_bug_id=${external_id}" \
+        "external_id=${tracker_id}"
+}
+
+## Update fixed in version field
+bz.update_fixed_in_version()
+{
+    bug_id="${1?}"
+    fixed_in_version="${2?}"
+    bz.update_bug "$bug_id" "cf_fixed_in=${fixed_in_version}"
+}
+
+
+## Update fixed in version field
+bz.update_status_and_version()
+{
+    bug_id="${1?}"
+    bug_status="${2?}"
+    fixed_in_version="${3?}"
+    bz.update_bug "$bug_id" \
+        "bug_status=${bug_status}" \
+        "cf_fixed_in=${fixed_in_version}"
+}
+
+######
+# Usage:
+#  bz.update_status bug_id new_status
+#
+#    bug_id
+#      Id of the bug to update
+#
+#    new_status
+#      New status to set the bug to, only the allowed transitions will end in
+#      a positive result (return code 0)
+#
+#
+#  Legal status transitions:
+#    ASSIGNED -> POST
+#    POST -> MODIFIED
+#
+#  If it's a revert any source status is allowed
+#
+bz.update_status()
+{
+    bug_id="${1?}"
+    new_status="${2?}"
+    commit_id="${3?}"
+    current_status="$(bz.get_bug_status "$bug_id")"
+    if [[ "$current_status" == "$new_status" ]]; then
+        echo "already on $new_status"
+        return 0
+    fi
+    if ! bz.is_revert "$commit_id"; then
+        case $current_status in
+            ASSIGNED)
+                if [[ "$new_status" != "POST" ]]; then
+                    echo "ilegal change from $current_status"
+                    return 1
+                fi
+                ;;
+            POST)
+                if [[ "$new_status" != "MODIFIED" ]]; then
+                    echo "ilegal change from $current_status"
+                    return 1
+                fi
+                ;;
+            *)
+                echo "ilegal change from $current_status"
+                return 1
+        esac
+    fi
+    bz.update_bug "$bug_id" "bug_status=${new_status}"
+}
+
+
+######
+# Usage:
+#  bz.get_external_bugs bug_id [external_name]
+#
+#    bug_id
+#      Id of the parent bug
+#
+#    external_name
+#      External string to get the bugs from. If none given it will get all the
+#      external bugs.
+#      Usually one of:
+#        - "oVirt gerrit"
+#        - "RHEV gerrit"
+#
+bz.get_external_bugs()
+{
+    bug_id="${1?}"
+    external_name="${2:-[^.*]}"
+    bz.get_bug "$bug_id" \
+    | grep -Po "(?<=<external_bugs name=\"$external_name\">)\d*"
+}
+
+
+######
+# Usage:
+#   bz.clean
+#
+#  Cleans up all the cached config and data. Make sure that your last scripts
+#  calls it before exitting
+bz.clean()
+{
+    rm -f /tmp/bz_cache.$PPID.*
+    conf.t_clean
+}
+
+
+######
+# Usage:
+#   bz.get_product bug_id
+#
+#  Return the product name of the given bug
+bz.get_product()
+{
+    bug_id="${1?}"
+    bz.get_bug "$bug_id" \
+    | grep -Po "(?<=<component>)[^<]*"
+}
diff --git a/hooks/lib/conf.sh b/hooks/lib/conf.sh
new file mode 100644
index 0000000..338e34d
--- /dev/null
+++ b/hooks/lib/conf.sh
@@ -0,0 +1,220 @@
+#!/usr/bin/env bash
+## Helper configuration functions
+#
+#
+#######
+# Configuration types
+#######
+#
+# There are two types of configurations taken into account, static and
+# temporary
+#
+#
+#######
+# Static configuration
+#######
+# 
+# Static configurations store those values that will persist after each
+# execution of the hooks, for example users and passwords.
+#
+#
+#
+#######
+# Temporary configurations
+#######
+#
+# Some hooks use temporary configurations to store values for other hooks to
+# recover, for example, when storing cookies.
+#
+
+
+# Get all the available configuration files from less relevant to more relevant
+conf._get_conf_files()
+{
+    fname="${0##*/}"
+    fpath="${0%/*}"
+    local htype="${fname%%.*}"
+    local chain="${fname#*.}"
+    chain="${chain%%.*}"
+    for conf_file in "${fpath}/${htype}.${chain}." \
+                     "${fpath}/${htype}." \
+                     "${fpath}/${chain}." \
+                     "${fpath}/" \
+                     "${GERRIT_SITE:-${HOME:-${fpath}/../../..}}/hooks/"
+    do
+        [[ -f "${conf_file}config" ]] \
+        && echo "${conf_file}config"
+    done
+}
+
+
+conf._get_conf_file()
+{
+    fname="${0##*/}"
+    fpath="${0%/*}"
+    local htype="${fname%%.*}"
+    local chain="${fname#*.}"
+    chain="${chain%%.*}"
+    echo "${fpath}/${htype}.${chain}."
+}
+
+
+######
+# Usage:
+#   conf.get [-c conf_file] name [default_value]
+#
+#  Retrieves the given value from the config
+#
+#  Options:
+#
+#  -c conf_file
+#    Use that config file
+#
+conf.get()
+{
+    local OPTIND value name default conf_file
+    while getopts c: option; do
+        case $option in
+            c) conf_file="$OPTARG";;
+        esac
+    done
+    if [[ "$conf_file" == "" ]]; then
+        for conf_file in $(conf._get_conf_files); do
+            res="$(conf.get -c "$conf_file" "$@")"
+            if [[ "$res" != "" ]]; then
+                echo "$res"
+                return
+            fi
+        done
+        return 1
+    fi
+    shift $((OPTIND-1))
+    local name="$1"
+    local default="$2"
+    if [[ -f "$conf_file" ]] && [[ "$name" != "" ]]; then
+        value="$(bash -c "source \"$conf_file\"; echo \"\$$name\"")"
+        eval "value=\"$value\""
+    fi
+    echo -e "${value:-$default}"
+}
+
+
+######
+# Usage:
+#   conf.put [-c conf_file] name value
+#
+#  writes the given name/value to the configuration
+#
+#  Options:
+#
+#  -c conf_file
+#    Use that config file
+#
+conf.put()
+{
+    local OPTIND=0
+    local conf_file="${0%.*.*}.config"
+    while getopts c: option; do
+        case $option in
+            c) conf_file="$OPTARG";;
+        esac
+    done
+    shift $((OPTIND-1))
+    name="${1?No name passed}"
+    val="${2?No value passed}"
+    if [[ -f "$conf_file" ]] && grep -Eq "^\s*$name=" "$conf_file"; then
+        ## delete the old entry
+        local entry="$(grep "$name=" "$conf_file")"
+        if [[ "${entry: -1}" == '"' ]]; then
+            sed -i -e "/$name=/d" "$conf_file"
+        else
+            ## It's multiline
+            sed -i -e "/$name=/,/.*\"/d" "$conf_file"
+        fi
+    fi
+    # add the new entry
+    echo "$name=\"$val\"" >> "$conf_file"
+}
+
+
+######
+# Usage:
+#   conf.load [-c conf_file]
+#
+#  Loads the config files from less specific to most so the latest prevails
+#
+#  Options:
+#
+#  -c conf_file
+#    Use that config file
+#
+conf.load()
+{
+    local OPTIND conf_file i
+    while getopts c: option; do
+        case $option in
+            c) conf_file="$OPTARG";;
+        esac
+    done
+    shift $((OPTIND-1))
+    ## if not specific conf passed, load from all
+    if [[ "$conf_file" == "" ]]; then
+        ## source the conf files from less specific to more
+        ## so the later ones have the last word
+        conf_files=($(conf._get_conf_files))
+        for i in $(seq "${#conf_files[@]}"); do
+            conf.load -c "${conf_files[$((${#conf_files[@]}-$i))]}"
+        done
+    else
+        ## if not,source that file
+        source "$conf_file"
+    fi
+}
+
+
+#############################################################
+### Temporary config file functions, for the current executione
+##############################################################
+######
+# Usage:
+#   conf.t_put name value
+#
+conf.t_put()
+{
+    local conf_file="${0%.*.*}.config.$PPID"
+    [[ "$0" == "/bin/bash" ]] && conf_file="/tmp/temp.config.$PPID"
+    conf.put -c "$conf_file" "$@"
+}
+
+
+# Usage:
+#   conf.t_get name value default
+#
+conf.t_get()
+{
+    local conf_file="${0%.*.*}.config.$PPID"
+    [[ "$0" == "/bin/bash" ]] && conf_file="/tmp/temp.config.$PPID"
+    conf.get -c "$conf_file" "$@"
+}
+
+
+# Usage:
+#   conf.t_load
+#
+conf.t_load()
+{
+    local conf_file="${0%.*.*}.config.$PPID"
+    [[ "$0" == "/bin/bash" ]] && conf_file="/tmp/temp.config.$PPID"
+    conf.load -c "$conf_file"
+}
+
+
+# Usage:
+#   conf.t_clean
+#
+conf.t_clean()
+{
+    local conf_file="${0%.*.*}.config.$PPID"
+    [[ "$0" == "/bin/bash" ]] && conf_file="/tmp/temp.config.$PPID"
+    [[ -f "$conf_file" ]] && rm -f $conf_file
+}
diff --git a/hooks/lib/gerrit.sh b/hooks/lib/gerrit.sh
new file mode 100644
index 0000000..8791a99
--- /dev/null
+++ b/hooks/lib/gerrit.sh
@@ -0,0 +1,97 @@
+#!/bin/bash
+###########
+## helpful functions to be used on the gerrit hook scripts
+source conf.sh
+
+## Get the bug info
+## NOTE: it is cached for faster access
+gerrit.get_patch()
+{
+    patch_id="${1?}"
+    local patch_cache="$(conf.t_get gerrit_${patch_id})"
+    if [[ "$patch_cache" != "" ]] && [[ -f "$patch_cache" ]]; then
+        cat "$patch_cache"
+    else
+        patch_cache="/tmp/gerrit_cache.$PPID.${patch_id}"
+        ssh "${GERRIT_SRV?}" -p 29418 \
+            gerrit query --current-patch-set "$patch_id" \
+        | tee "$patch_cache"
+        conf.t_put "gerrit_${patch_id}" "$patch_cache"
+    fi
+}
+
+## Check if the patch has the Related-To tag
+gerrit.is_related()
+{
+    local commit=${1:-HEAD}
+    local line
+    local related_regexp='^[^#]*Related-To:(.*)$'
+    pushd "${GIT_DIR?}" &>/dev/null
+    while read line; do
+        if [[ "$line"  =~ $related_regexp ]]; then
+            popd &>/dev/null
+            return 0
+        fi
+    done < <( git log "$commit^1..$commit" --format=%b )
+    popd &>/dev/null
+    return 1
+}
+
+
+## Parse all the aprameters as env variables:
+## $0 --param1 val1 param2 --param-3 val3
+##   => param1="val1" && param_3="val3" && [[ $1 == "param2" ]]
+gerrit.parse_params()
+{
+    source tools.sh
+    while [[ "$1" != "" && "$2" != "" ]]; do
+        if [[ "${1:0:2}" != '--' ]]; then
+            shift
+            continue
+        fi
+        eval "$(tools.sanitize ${1:2})=\"${2//\"/\\\"}\""
+        shift 2
+    done
+}
+
+
+## Write a review, it will use the env commit and project vars, as set by
+##  parse_params
+gerrit.review()
+{
+    local result=${1?}
+    local message="$( echo "${2?}" | fold -w 60 -s )"
+    local project=${3:-$project}
+    local commit=${4:-$commit}
+    local footer="
+ help:$HELP_URL"
+    ssh "${GERRIT_SRV?}" -p 29418 gerrit review \
+        --verified="$result" \
+        --message="\"$message${HELP_URL:+$footer}\"" \
+        --project="${project?}" \
+        "${commit?}"
+}
+
+
+## Get the status of the given patch
+gerrit.status()
+{
+    local id=${1?}
+    gerrit.get_patch "$id" \
+    | grep -Po "(?<=^  status: )\w*"
+}
+
+## Check if a patch is open
+gerrit.is_open()
+{
+    local id=${1?}
+    gerrit.get_patch "$id" \
+    | grep -Pq "^  open: true"
+}
+
+
+## Clean up all temporary files for the current run
+gerrit.clean()
+{
+    rm -f /tmp/gerrit_cache.$PPID.*
+}
diff --git a/hooks/lib/tools.sh b/hooks/lib/tools.sh
new file mode 100644
index 0000000..09fbde7
--- /dev/null
+++ b/hooks/lib/tools.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+###########
+## helpful functions to be used on the gerrit hook scripts
+
+## Check if a value is in the given list of elements
+## Usage:
+##    tools.is_in value elem1 [elem2 [...]]
+tools.is_in()
+{
+    local what=$1
+    local where i
+    shift
+    i=0
+    for where in "$@"; do
+        if [[ "$what" == "$where" ]]; then
+            echo "$i"
+            return 0
+        fi
+        i=$(($i + 1))
+    done
+    return 1
+}
+
+
+## Remove the leading and trailing white spaces
+tools.trim(){
+    local word
+    shopt -q -s extglob
+    for word in "$@"; do
+        word="${word##+([[:space:]])}"
+        word="${word%%+([[:space:]])}"
+        echo "$word"
+    done
+    shopt -q -u extglob
+}
+
+
+## Replace all the bad characters from the given word to fit a bash variable
+## name specification
+tools.sanitize()
+{
+    local word
+    for word in "$@"; do
+        word="$( tools.trim "${word}" )"
+        # if you do not make sure that extglob is disabled the patterns with
+        # square brackets will not work...
+        shopt -q -u extglob
+        # some utf-8 chars are not valid in var names, but are included in
+        # ranges, avoid using ranges
+        
word="${word//[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]/_}"
+        [[ $word =~ ^[0-9] ]] \
+            && echo "Malformed $word, should not start with a digit." \
+            && return 1
+        echo "$word"
+    done
+}
+
+
+## Get a simple md5 hash of the given string
+tools.hash()
+{
+    local what="${1?}"
+    local length="${2:-10}"
+    echo "$what" | md5sum | head -c$length
+}


--
To view, visit http://gerrit.ovirt.org/15389
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I7a10060cff5c25e8bd8e2f73654208a90cec70d8
Gerrit-PatchSet: 1
Gerrit-Project: gerrit-admin
Gerrit-Branch: master
Gerrit-Owner: David Caro <dcaro...@redhat.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to