about summary refs log tree commit diff stats
path: root/tools/conf/srv
diff options
context:
space:
mode:
Diffstat (limited to 'tools/conf/srv')
-rw-r--r--tools/conf/srv/gitolite/.gitolite.rc200
-rwxr-xr-xtools/conf/srv/gitolite/deploy-web-doc42
-rw-r--r--tools/conf/srv/gitolite/deploy-web.sh75
-rwxr-xr-xtools/conf/srv/gitolite/deploy.sh175
-rw-r--r--tools/conf/srv/gitolite/gitolite.conf80
-rw-r--r--tools/conf/srv/gitolite/hook.sh95
6 files changed, 667 insertions, 0 deletions
diff --git a/tools/conf/srv/gitolite/.gitolite.rc b/tools/conf/srv/gitolite/.gitolite.rc
new file mode 100644
index 0000000..fa18e4e
--- /dev/null
+++ b/tools/conf/srv/gitolite/.gitolite.rc
@@ -0,0 +1,200 @@
+# configuration variables for gitolite
+
+# This file is in perl syntax.  But you do NOT need to know perl to edit it --
+# just mind the commas, use single quotes unless you know what you're doing,
+# and make sure the brackets and braces stay matched up!
+
+# (Tip: perl allows a comma after the last item in a list also!)
+
+# HELP for commands can be had by running the command with "-h".
+
+# HELP for all the other FEATURES can be found in the documentation (look for
+# "list of non-core programs shipped with gitolite" in the master index) or
+# directly in the corresponding source file.
+
+%RC = (
+
+    # ------------------------------------------------------------------
+
+    # default umask gives you perms of '0700'; see the rc file docs for
+    # how/why you might change this
+    UMASK                           =>  027,
+
+    # look for "git-config" in the documentation
+    GIT_CONFIG_KEYS                 =>  '.*',
+
+    # comment out if you don't need all the extra detail in the logfile
+    LOG_EXTRA                       =>  1,
+    # logging options
+    # 1. leave this section as is for 'normal' gitolite logging (default)
+    # 2. uncomment this line to log ONLY to syslog:
+    # LOG_DEST                      => 'syslog',
+    # 3. uncomment this line to log to syslog and the normal gitolite log:
+    # LOG_DEST                      => 'syslog,normal',
+    # 4. prefixing "repo-log," to any of the above will **also** log just the
+    #    update records to "gl-log" in the bare repo directory:
+    # LOG_DEST                      => 'repo-log,normal',
+    # LOG_DEST                      => 'repo-log,syslog',
+    # LOG_DEST                      => 'repo-log,syslog,normal',
+
+    # roles.  add more roles (like MANAGER, TESTER, ...) here.
+    #   WARNING: if you make changes to this hash, you MUST run 'gitolite
+    #   compile' afterward, and possibly also 'gitolite trigger POST_COMPILE'
+    ROLES => {
+        READERS                     =>  1,
+        WRITERS                     =>  1,
+    },
+
+    # enable caching (currently only Redis).  PLEASE RTFM BEFORE USING!!!
+    # CACHE                         =>  'Redis',
+
+    # ------------------------------------------------------------------
+
+    # rc variables used by various features
+
+    # the 'info' command prints this as additional info, if it is set
+        # SITE_INFO                 =>  'Please see http://blahblah/gitolite for more help',
+
+    # the CpuTime feature uses these
+        # display user, system, and elapsed times to user after each git operation
+        # DISPLAY_CPU_TIME          =>  1,
+        # display a warning if total CPU times (u, s, cu, cs) crosses this limit
+        # CPU_TIME_WARN_LIMIT       =>  0.1,
+
+    # the Mirroring feature needs this
+        # HOSTNAME                  =>  "foo",
+
+    # TTL for redis cache; PLEASE SEE DOCUMENTATION BEFORE UNCOMMENTING!
+        # CACHE_TTL                 =>  600,
+
+    # ------------------------------------------------------------------
+
+    # suggested locations for site-local gitolite code (see cust.html)
+
+        # this one is managed directly on the server
+	# LOCAL_CODE                =>  "$ENV{HOME}/local",
+
+        # or you can use this, which lets you put everything in a subdirectory
+        # called "local" in your gitolite-admin repo.  For a SECURITY WARNING
+        # on this, see http://gitolite.com/gitolite/non-core.html#pushcode
+        LOCAL_CODE                =>  "$rc{GL_ADMIN_BASE}/local",
+
+    # ------------------------------------------------------------------
+
+    # List of commands and features to enable
+
+    ENABLE => [
+
+        # COMMANDS
+
+            # These are the commands enabled by default
+            'help',
+            'desc',
+            'info',
+            'perms',
+            'writable',
+
+            # Uncomment or add new commands here.
+            # 'create',
+            # 'fork',
+            # 'mirror',
+            # 'readme',
+            # 'sskm',
+            # 'D',
+
+        # These FEATURES are enabled by default.
+
+            # essential (unless you're using smart-http mode)
+            'ssh-authkeys',
+
+            # creates git-config enties from gitolite.conf file entries like 'config foo.bar = baz'
+            'git-config',
+
+            # creates git-daemon-export-ok files; if you don't use git-daemon, comment this out
+            'daemon',
+
+            # creates projects.list file; if you don't use gitweb, comment this out
+            'gitweb',
+
+        # These FEATURES are disabled by default; uncomment to enable.  If you
+        # need to add new ones, ask on the mailing list :-)
+
+        # user-visible behaviour
+
+            # prevent wild repos auto-create on fetch/clone
+            # 'no-create-on-read',
+            # no auto-create at all (don't forget to enable the 'create' command!)
+            # 'no-auto-create',
+
+            # access a repo by another (possibly legacy) name
+            # 'Alias',
+
+            # give some users direct shell access.  See documentation in
+            # sts.html for details on the following two choices.
+            # "Shell $ENV{HOME}/.gitolite.shell-users",
+            # 'Shell alice bob',
+
+            # set default roles from lines like 'option default.roles-1 = ...', etc.
+            # 'set-default-roles',
+
+            # show more detailed messages on deny
+            # 'expand-deny-messages',
+
+            # show a message of the day
+            # 'Motd',
+
+        # system admin stuff
+
+            # enable mirroring (don't forget to set the HOSTNAME too!)
+            # 'Mirroring',
+
+            # allow people to submit pub files with more than one key in them
+            # 'ssh-authkeys-split',
+
+            # selective read control hack
+            # 'partial-copy',
+
+            # manage local, gitolite-controlled, copies of read-only upstream repos
+            'upstream',
+
+            # updates 'description' file instead of 'gitweb.description' config item
+            # 'cgit',
+
+            # allow repo-specific hooks to be added
+            'repo-specific-hooks',
+
+        # performance, logging, monitoring...
+
+            # be nice
+            # 'renice 10',
+
+            # log CPU times (user, system, cumulative user, cumulative system)
+            # 'CpuTime',
+
+        # syntactic_sugar for gitolite.conf and included files
+
+            # allow backslash-escaped continuation lines in gitolite.conf
+            # 'continuation-lines',
+
+            # create implicit user groups from directory names in keydir/
+            # 'keysubdirs-as-groups',
+
+            # allow simple line-oriented macros
+            # 'macros',
+
+        # Kindergarten mode
+
+            # disallow various things that sensible people shouldn't be doing anyway
+            # 'Kindergarten',
+    ],
+
+);
+
+# ------------------------------------------------------------------------------
+# per perl rules, this should be the last line in such a file:
+1;
+
+# Local variables:
+# mode: perl
+# End:
+# vim: set syn=perl:
diff --git a/tools/conf/srv/gitolite/deploy-web-doc b/tools/conf/srv/gitolite/deploy-web-doc
new file mode 100755
index 0000000..ae8e2db
--- /dev/null
+++ b/tools/conf/srv/gitolite/deploy-web-doc
@@ -0,0 +1,42 @@
+#!/bin/bash
+######################################################################
+#
+# Put this file in your gitolite-admin;
+# ~/gitolite-admin/local/hooks/repo-specific/deploy-web-doc
+#
+# set host to empty to create package for each push
+# or set remote host to create package based on last deployed push
+# host="https://doc.localhost"
+host=""
+# set name of witch branch should be deployed
+branch_to_deploy="deploy_branch"
+
+######################################################################
+
+
+url="$host/.last_deploy"
+source /srv/gitolite/deploy/hook.sh
+read oldrev newrev refname
+push_branch=$(git rev-parse --symbolic --abbrev-ref $refname)
+
+#SCRIPT_VARS=$(set)
+#echo "project: $PROJECT"
+#echo "local dir: $PWD" > /srv/gitolite/deploy/${GL_REPO}
+#echo "${SCRIPT_VARS}" >> /srv/gitolite/deploy/${GL_REPO}
+
+if [[ $push_branch = $branch_to_deploy  ]]; then
+
+    # if host empty we make local tracking
+    if [[ $host = "" ]]; then
+        if [[ $(is_initial ${GL_REPO}) = "true" ]]; then
+            oldrev="initial"
+        fi
+    else
+        if [[ ! $(valid_url $url) = "true" ]]; then
+            echo "Deploy: set $url on remote to start creating packages"
+            exit 1
+        fi
+        oldrev=$(get_remote_rev $url)
+    fi
+    create_package ${GL_REPO} ${PWD} ${oldrev} ${newrev} "deploy-web.sh"
+fi
diff --git a/tools/conf/srv/gitolite/deploy-web.sh b/tools/conf/srv/gitolite/deploy-web.sh
new file mode 100644
index 0000000..01e92ac
--- /dev/null
+++ b/tools/conf/srv/gitolite/deploy-web.sh
@@ -0,0 +1,75 @@
+#!/bin/bash
+
+pkg_path=$1
+
+www_root="/srv/www"
+www_user="nginx"
+www_group="www"
+
+pkg_file="${pkg_path}/project"
+pkg_rm="${pkg_path}/deleted"
+pkg_files="${pkg_path}/files"
+
+if [ ! -f ${pkg_file} ]; then
+    echo "Deploy web: invalid pkg_file ${pkg_file}"
+    exit 1
+fi
+
+pkg_name=$(head -1 ${pkg_file})
+pkg_new=$(head -3 ${pkg_file} | tail -1)
+pkg_new7=$(echo ${pkg_new} | cut -c1-7)
+
+pkg_www="${www_root}/${pkg_name}"
+pkg_back="${pkg_www}/backup_deploy"
+pkg_last="${pkg_www}/.last_deploy"
+
+if [ ! -d ${pkg_www} ]; then
+    echo "Deploy web: invalid pkg_www ${pkg_www}"
+    exit 1
+fi
+
+# first backup all data
+if [[ ! $(ls ${pkg_www} | grep -v "backup_deploy") = "" ]]; then
+    if [ ! -d ${pkg_back} ]; then
+        sudo -u ${www_user} mkdir -p ${pkg_back}
+    fi
+    backup_file="${pkg_back}/${pkg_name}-$(date '+%Y-%j-%H-%M-%S').tar.gz"
+    echo "Deploy web: making backup ${backup_file}"
+    sudo -u ${www_user} tar --exclude ${pkg_back} --xattrs -zcpf ${backup_file} ${pkg_www}
+fi
+
+# remove files and directories that have been deleted
+if [ -f ${pkg_rm} ]; then
+
+    echo "Deploy web: files to delete:"
+    # first we delete files
+    while read deleted_file; do
+        deleted_file="${pkg_www}/${deleted_file}"
+        if [ -f ${deleted_file} ]; then
+            echo "file      rm ${deleted_file}"
+            rm ${deleted_file}
+        fi
+    done <${pkg_rm}
+
+    # delete directories
+    while read deleted_file; do
+        deleted_file="${pkg_www}/${deleted_file}"
+        if [ -d ${deleted_file} ]; then
+            echo "file      rm ${deleted_file}"
+            rm ${deleted_file}
+        fi
+    done <${pkg_rm}
+
+fi
+
+# copy new files to destination
+if [ -d ${pkg_files} ]; then
+    echo "Deploy web: cp from ${pkg_files} to ${pkg_www}"
+    sudo -u ${www_user} cp -r ${pkg_files}/* ${pkg_www}
+fi
+
+echo ${pkg_new} > ${pkg_last}
+echo "Deploy: scripts/deployweb.sh ${pkg_name} ${pkg_new7} deployed."
+
+#remove temporary package
+rm -r ${pkg_path}
diff --git a/tools/conf/srv/gitolite/deploy.sh b/tools/conf/srv/gitolite/deploy.sh
new file mode 100755
index 0000000..df11f4a
--- /dev/null
+++ b/tools/conf/srv/gitolite/deploy.sh
@@ -0,0 +1,175 @@
+#!/bin/bash
+
+# origin package directory
+packages_dir="/srv/gitolite/deploy/packages"
+# temporary work directory
+deploy_dir="/srv/gitolite/deploy/deploy_dir"
+# scripts to deploy packages
+deploy_scripts="/srv/gitolite/deploy/scripts"
+
+function get_script(){
+    # receives package path return script to call
+    local pkg_path=$1
+    echo $(head -2 ${pkg_path}/project | tail -1)
+}
+
+function get_new(){
+    # receives package path return commit hash (new)
+    local pkg_path=$1
+    echo $(head -3 ${pkg_path}/project | tail -1)
+}
+
+function get_dep(){
+    # receives package path return previews commit hash (old)
+    local pkg_path=$1
+
+    new=$(head -3 ${pkg_path}/project | tail -1)
+    old=$(head -4 ${pkg_path}/project | tail -1)
+
+    if [[ ! ${new} = ${old} ]]; then
+        echo ${old} | cut -c1-7
+    fi
+}
+
+function project_extract(){
+
+    # project directory containing extracted packages
+    local prj_dir=$1
+
+    # final extracted package
+    local prj_pkg="${prj_dir}/package"
+
+    # temporary vars for swapping/iterating pkg_news
+    local pkg_new=""
+    local pkg_old=""
+    local pkg_dir=""
+    local pkg_temp=""
+    local pkg_next=1
+    local pkg_del=""
+    local x=0
+    local y=0
+
+    # array with all the news hashes
+    local pkg_news=($(ls ${prj_dir}))
+
+    # total new packages
+    local total=${#pkg_news[@]}
+
+    echo "Deploy: $(basename ${prj_dir}) extracting packages ${pkg_news[*]}"
+
+    # find first package
+    for pkg_new in ${pkg_news[@]}
+    do
+        # get package dependency
+        pkg_dir="${prj_dir}/${pkg_new}"
+        pkg_old=$(get_dep ${pkg_dir})
+        if [[ ! " ${pkg_news[@]} " =~ " ${pkg_old} " ]]; then
+            # pkg_news don't contain package
+            # we found initial package
+            pkg_temp=${pkg_news[0]}
+            pkg_news[0]=${pkg_new}
+            pkg_news[${x}]=${pkg_temp}
+            break
+        fi
+        x=$((${x}+1))
+    done
+
+    # Order packages by dependency start with first package
+    for (( y=0; y<${total}; y++ ))
+    do
+        pkg_next=$(($y+1))
+        if [[ ${pkg_next} = ${total} ]]; then
+            ## we are in the last one
+            break
+        fi
+
+        pkg_new=${pkg_news[$y]}
+        for (( x=pkg_next; x<${total}; x++ ))
+        do
+            pkg_dir="${prj_dir}/${pkg_news[${x}]}"
+            pkg_old=$(get_dep ${pkg_dir})
+            # is dependent on current
+            if [[ ${pkg_old} = ${pkg_new} ]]; then
+                pkg_temp=${pkg_news[${pkg_next}]}
+                pkg_news[${pkg_next}]=${pkg_news[${x}]}
+                pkg_news[${x}]=${pkg_temp}
+                # we can break and pass next one
+                break
+            fi
+        done
+    done
+
+    # create project final package directory
+    mkdir -p ${prj_pkg}/files
+
+    # copy project information of last commit
+    cp ${prj_dir}/${pkg_news[$((${total}-1))]}/project ${prj_pkg}
+
+    # now that packages are ordered we can start creating files
+    for pkg_new in ${pkg_news[@]}
+    do
+        pkg_dir=${prj_dir}/${pkg_new}
+        tar xf ${pkg_dir}/files.tar.xz \
+            --directory ${prj_pkg}/files
+
+        # if deleted files exists
+        if [ -f "${pkg_dir}/deleted" ]; then
+            # first collect all files/directories don't exist
+            while read pkg_del; do
+                # if file don't exist add entry to project deleted file
+                pkg_temp="${prj_pkg}/files/${pkg_del}"
+                if [ ! -f ${pkg_temp} ]; then
+                    if [ ! -d ${pkg_temp} ]; then
+                        # is not a file or directory from previous packages
+                        echo ${pkg_del} >> ${prj_pkg}/deleted
+                    fi
+                fi
+            done <${prj_dir}/${pkg_new}/deleted
+
+            # delete directories and files
+            while read pkg_del; do
+                pkg_temp="${prj_pkg}/files/${pkg_del}"
+                if [ -d ${pkg_temp} ]; then
+                    rm -r ${pkg_temp}
+                elif [ -f ${pkg_temp} ]; then
+                    rm ${pkg_temp}
+                fi
+            done <${prj_dir}/${pkg_new}/deleted
+        fi
+
+        #remove temporary directory
+        rm -r ${prj_dir}/${pkg_new}
+    done
+
+    # call project deploy script
+    call_script=${deploy_scripts}/$(get_script $prj_pkg)
+    echo "Deploy: calling deploy script: ${call_script}"
+    /bin/bash ${call_script} ${prj_pkg}
+
+}
+
+if [[ ! $(ls ${deploy_dir}) = "" ]]; then
+    rm -r ${deploy_dir}/*
+fi
+
+# first extract all packages from origin directory
+for pkg_path in `find ${packages_dir} -type f -name "*.tar.gz"`
+do
+    if [ -f ${pkg_path} ]; then
+        pkg_name=$(basename ${pkg_path})
+        pkg_proj=$(echo ${pkg_name} | cut -d "_" -f 1)
+        pkg_new7=$(echo ${pkg_name} | tail -c -15 | cut -c -7)
+        pkg_temp=${deploy_dir}/${pkg_proj}/${pkg_new7}
+        mkdir -p ${pkg_temp}
+        tar xf ${pkg_path} --directory ${pkg_temp}
+        rm ${pkg_path}
+    fi
+done
+
+# loop for all projects and deploy them
+for prj_dir in `find ${deploy_dir} -maxdepth 1 -mindepth 1 -type d`
+do
+    # order index of hashes based on old commit
+    echo "prj_dir $prj_dir"
+    project_extract ${prj_dir}
+done
diff --git a/tools/conf/srv/gitolite/gitolite.conf b/tools/conf/srv/gitolite/gitolite.conf
new file mode 100644
index 0000000..09133ec
--- /dev/null
+++ b/tools/conf/srv/gitolite/gitolite.conf
@@ -0,0 +1,80 @@
+@guests         =   gitweb
+@interns        =   silvino
+@dev            =   silvino
+@teamleads      =   silvino
+@staff          =   @interns @dev @teamleads
+
+repo  @secret
+    - = @guests
+    option deny-rules = 1
+
+repo @floss
+    RW+                     =   @dev @staff
+    R                       =   @all
+
+repo @project
+    RW+                     =   @teamleads
+    -   master              =   @dev
+    -   refs/tags/v[0-9]    =   @dev
+    RW+ develop/            =   @dev
+    RW+ feature/            =   @dev
+    RW+ hot-fix/            =   @dev
+    RW                      =   @dev
+    R                       =   @interns
+
+repo @mirror
+    RW+ release/            =   @teamleads
+    RW+ develop/            =   @dev
+    RW+ feature/            =   @dev
+    RW+ hot-fix/            =   @dev
+    R                       =   @all
+
+repo gitolite-admin
+    RW+     =   gitolite
+
+repo c9-doc c9-ports c9-pmwiki c9-assistant
+    config gitweb.owner         =   "c9 team"
+    config gitweb.category      =   "c9"
+
+repo linux-pck
+    config gitweb.owner         =   "c9 team"
+    config gitweb.category      =   "mirrors"
+
+repo opt core contrib
+    config gitweb.owner         =   "crux"
+    config gitweb.category      =   "crux"
+
+repo c9-doc
+    config gitweb.description   =   "c9 documentation"
+    option hook.post-receive     =  deploy-web-doc
+
+repo c9-ports
+    config gitweb.description   =   "c9 ports"
+
+repo c9-pmwiki
+    config gitweb.description   =   "c9 wiki"
+    option hook.post-receive     =  deploy-web-doc
+
+repo c9-assistant
+    config gitweb.owner         =   "c9 team"
+    config gitweb.description   =   "c9 open assistant"
+
+repo core
+    config gitweb.description   =   "crux core collection"
+
+repo opt
+    config gitweb.description   =   "crux opt collection"
+
+repo contrib
+    config gitweb.description   =   "crux contrib collection"
+
+repo linux-pck
+    config gitweb.description   =   "PCK or Parabola Community Kernel are multiple patches, pf-kernel and zen-kernel for Linux-libre kernel"
+    option      upstream.url    = git://git.parabola.nu/pck.git
+    option      upstream.nice   = 120
+
+
+@secret    =   gitolite-admin
+@project   =   c9-doc c9-ports c9-pmwiki c9-assistant
+@project   =   core opt contrib
+@mirror    =   linux-pck
diff --git a/tools/conf/srv/gitolite/hook.sh b/tools/conf/srv/gitolite/hook.sh
new file mode 100644
index 0000000..1f977ca
--- /dev/null
+++ b/tools/conf/srv/gitolite/hook.sh
@@ -0,0 +1,95 @@
+#!/bin/bash
+
+# final packages dir
+packages_dir="/srv/gitolite/deploy/packages"
+# hook work directory
+hook_dir="/srv/gitolite/deploy/hook_dir"
+
+function is_initial(){
+    local prj_name=$1
+    if [ ! -d ${hook_dir}/${prj_name} ]; then
+        echo "true"
+    else
+        echo "false"
+    fi
+}
+
+function get_remote_rev(){
+    echo $(wget --no-check-certificate -qO- $1)
+}
+
+function valid_url(){
+    if [[ `wget -S --spider $1 --no-check-certificate 2>&1 | grep 'HTTP/1.1 200 OK'` ]];
+    then
+        echo "true";
+    fi
+}
+
+function create_package(){
+    # project name
+    local prj_name=$1
+    # git repository directory
+    local git_dir=$2
+    # last/old commit revision
+    local pkg_old=$3
+    # new commit revision
+    local pkg_new=$4
+    # script deploy call when extracting this package
+    local pkg_script=$5
+
+    local pkg_new7=$(echo $pkg_new | cut -c1-7)
+
+    # project directory
+    local prj_dir="${hook_dir}/${prj_name}"
+    # package directory
+    local pkg_dir="${prj_dir}/${pkg_new7}"
+    # final tar file
+    local pkg_tar="${packages_dir}/${prj_name}_${pkg_new7}.tar.gz"
+
+    # if temporary work directory exists maybe other process is creating packages
+    if [ -d "$pkg_dir" ]; then
+        echo "Deploy: temporary directory ${pkg_dir} exists, maybe other precess"
+        exit 1
+    fi
+    # create temporary directory for this package
+    mkdir -p ${pkg_dir}
+
+    echo "Deploy: ${prj_name} ${pkg_new7} package call ${pkg_script} on deploy."
+
+    # save metadata to be used by deploy script
+    echo $prj_name > ${pkg_dir}/project
+    echo $pkg_script >> ${pkg_dir}/project
+    echo $pkg_new >> ${pkg_dir}/project
+
+    # if is a valid old commit create a package with changes since then
+    # else create a full package (all files)
+    local is_commit=$(git --git-dir=${git_dir} cat-file -t ${pkg_old} 2>&1)
+    if [[ $is_commit = "commit" ]]; then
+        echo "Deploy: creating package from old commit."
+        # list with files to extract (Added Copied Modified Renamed)
+        file_list=$(git --git-dir=${git_dir} --no-pager diff \
+            --diff-filter=ACMR \
+            --name-only ${pkg_old} ${pkg_new})
+
+        # create tar archive with same name as commit hash with files
+        git --git-dir=${git_dir} archive -o ${pkg_dir}/files.tar.xz ${pkg_new} ${file_list}
+
+        # first we create list of files to be removed
+        git --git-dir=${git_dir} --no-pager diff \
+            --diff-filter=DR \
+            --name-status -t ${pkg_old} ${pkg_new} | cut -f 2 > ${pkg_dir}/deleted
+
+        # save old commit on metadata
+        echo $pkg_old >> ${pkg_dir}/project
+    else
+        echo "Deploy: creating initial package."
+        git --git-dir=${git_dir} archive -o ${pkg_dir}/files.tar.xz ${pkg_new}
+
+    fi
+
+    tar -zcpf ${pkg_tar} --directory=${pkg_dir} .
+
+    echo "Deploy: package ${pkg_tar} ready !"
+    rm -r ${pkg_dir}
+    return 0
+}