about summary refs log tree commit diff stats
path: root/tools/gitolite.html
diff options
context:
space:
mode:
Diffstat (limited to 'tools/gitolite.html')
-rw-r--r--tools/gitolite.html503
1 files changed, 356 insertions, 147 deletions
diff --git a/tools/gitolite.html b/tools/gitolite.html
index 58d6d96..94abda0 100644
--- a/tools/gitolite.html
+++ b/tools/gitolite.html
@@ -23,7 +23,7 @@
 
         <pre>
         # mkdir -p /srv/gitolite
-        # useradd -U -d /srv/gitolite gitolite
+        # useradd -r -s /bin/bash -m -d /srv/gitolite gitolite
         # chown gitolite:gitolite /srv/gitolite
         </pre>
 
@@ -38,10 +38,20 @@
         <p>Copy public key that will be used for
         authenticating gitolite administrator, read
         <a href="openssh.html#ssh">ssh</a> how to
-        create one.</p>
+        create one, key don't need to have password.
+        If the server is on remote a remote
+        machine you can use scp to copy the public key;</p>
 
         <pre>
-        $ sudo install -o gitolite -g gitolite /home/bob/.ssh/gitolite.pub /srv/gitolite/gitolite.pub
+        $ scp /home/bob/.ssh/gitolite.pub admin@core.privat-network.net:/home/admin/
+        bob@core.privat-network.net's password:
+        gitolite.pub                              100%  390     0.4KB/s   00:00
+        </pre>
+
+        <p>Then on remote machine;</p>
+
+        <pre>
+        # cp /home/admin/gitolite.pub /srv/gitolite.pub
         </pre>
 
         <pre>
@@ -62,7 +72,7 @@
         </pre>
 
         <pre>
-        $ ssh -v -i ~/.ssh/gitulite_rsa gitolite@localhost -p 2222
+        $ ssh -v -i ~/.ssh/gitolite gitolite@localhost -p 2222
         </pre>
 
         <h2 id="admin">3. Gitolite Administration</h2>
@@ -72,7 +82,7 @@
         Start by cloning gitolite-adimin;</p>
 
         <pre>
-        $ git clone gitolite:gitolite-admin
+        $ git clone git-admin:gitolite-admin
         </pre>
 
         <h3>3.1. Recover Admin Account</h3>
@@ -127,38 +137,55 @@
         edit conf/gitolite.conf;</p>
 
         <pre>
-        @dev            =   alice david
-        @interns        =   clair
-        @dev            =   bob
-        @teamleads      =   mike
+        @guests         =   gitweb
+        @interns        =   bob alice
+        @dev            =   fred mary joe
+        @teamleads      =   mary
         @staff          =   @interns @dev @teamleads
 
-        @proj-repos     =   sysdoc storm atom
+        repo  @secret
+            - = @guests
+            option deny-rules = 1
 
         repo @floss
-                R                       =   @all
+            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 @proto
-                RW+                     =   @staff
+        repo gitolite-admin
+            RW+     =   gitolite
 
-        repo @proj-repos
-                RW+                     =   @teamleads
-                -   master              =   @dev
-                -   refs/tags/v[0-9]    =   @dev
-                RW+ develop/            =   @dev
-                RW+ feature/            =   @dev
-                RW+ hot-fix/            =   @dev
-                RW                      =   @dev
-                R                       =   @managers
+        repo c9-doc c9-ports c9-pmwiki
+            config gitweb.owner         =   "c9 team"
+            config gitweb.category      =   "c9"
 
-        repo atom sysdoc
-            option hook.post-receive     =  deployweb
+        repo c9-doc
+            config gitweb.description   =   "c9 documentation"
+            option hook.post-receive     =  deploy-web-doc
 
-        repo testing
-            RW+     =   @staff
+        repo c9-ports
+            config gitweb.description   =   "c9 ports"
 
-        repo gitolite-admin
-            RW+     =   mike
+        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.category      =   "c9"
+            config gitweb.description   =   "c9 open assistant"
+
+        @secret    =   gitolite-admin
+        @project   =   c9-doc c9-ports c9-pmwiki c9-assistant
         </pre>
 
         <p>Commit and push;</p>
@@ -174,13 +201,13 @@
 
         <pre>
         # cd /srv/gitolite/repositories/
-        # mv void.git sysdoc.git
+        # mv void.git c9-doc.git
         </pre>
 
         <p>On workstation edit conf/gitolite.conf;</p>
 
         <pre>
-        repo sysdoc
+        repo c9-doc
                 RW+     =       bob
         </pre>
 
@@ -191,12 +218,44 @@
         $ git push
         </pre>
 
+        <h4>3.3.3 Delete Repository</h4>
+
+        <pre>
+        # cd /srv/gitolite/repositories/
+        # rm -rf c9-doc.git
+        </pre>
+
+        <p>On workstation edit conf/gitolite.conf and remove c9-doc.</p>
+
         <h2 id="hooks">4. Gitolite Hooks</h2>
 
+        <p>This document creates three scripts, one is run when gitolite receives
+        push to a project with hook active, second script is run under root
+        user to allow operations where gitolite user have no rights, third one
+        is project specific.</p>
+
+        <p>This example try to have a separate creation of a package and its deployment,
+        in case deploy script is not on the same machine other method can be used to send
+        the package.</p>
+
+        <p>A normal package will have a files.tar with all or new files to extract,
+        if necessary a deleted file with the list of files to be removed and a
+        project file with data about the package like new hash commit, or witch
+        script to call to deploy.</p>
+
+        <p>Package is created under gitolite
+        <a href="conf/srv/gitolite/hook.sh">/srv/gitolite/deploy/hook.sh</a>
+        script and
+        <a href="conf/srv/gitolite/deploy.sh">/srv/gitolite/deploy/deploy.sh</a>,
+        deploy in this example is called called by cron.</p>
+
+        <h3 id="gtl-activate">4.1. Activate Hooks</h3>
+
         <p>Example from
         <a href="http://gitolite.com/gitolite/cookbook.html#v3.6-variation-repo-specific-hooks">Cookbook</a>
         how to apply hooks only to certain repos. Uncomment or add
-        this line on /srv/gitolite/.gitolite.rc, within the %RC block;</p>
+        this line on <a href="conf/srv/gitolite/.gitolite.rc">/srv/gitolite/.gitolite.rc</a>,
+        within the %RC block;</p>
 
         <pre>
         LOCAL_CODE => "$rc{GL_ADMIN_BASE}/local",
@@ -206,194 +265,244 @@
         or add it to the ENABLE list if it doesn't exist.</p>
 
         <pre>
-        GIT_CONFIG_KEYS         => '.*',
-        </pre>
-
-        <pre>
         # allow repo-specific hooks to be added
         'repo-specific-hooks',
         </pre>
 
-        <p>Put your hooks into your gitolite-admin clone, as follows:</p>
+        <p>Create directory on gitolite-admin clone;</p>
 
         <pre>
         $ cd ~/gitolite-admin
         $ mkdir -p local/hooks/repo-specific
         </pre>
 
-        <p>Create the same directory on remote as gitolite;</p>
+        <p>Now add your hooks to that directory, but instead of using the
+        git "standard" names (pre-receive, post-receive, post-update),
+        you use descriptive names (e.g. "deploy", "RSS-post", etc).</p>
+
+        <p>On remote run;</p>
 
         <pre>
         # su - gitolite
-        $ mkdir local/hooks/repo-specific
+        $ mkdir .gitolite/local/hooks/repo-specific
+        $ gitolite setup
         </pre>
 
-        <p>Now add your hooks to that directory, but instead of using the
-        git "standard" names (pre-receive, post-receive, post-update),
-        you use descriptive names (e.g. "deploy", "RSS-post", etc).</p>
+        <h3 id="gtl-deploy">4.2. Deploy and Hook script</h3>
 
-        <h3 id="gtl-deploy">4.1. Deploy Hook</h3>
+        <p>Create deploy directory on remote, /srv/gitolite/deploy
+        was chosen to have less impact on the package system;</p>
 
-        <p>This manual create two users; one gitolite that handle git
-        central server and system www for web servers. To avoid permission
-        problems this example use gitolite hooks and cron. By using cron
-        we have permission to use chown, this way files end up with right
-        www user ownership and permissions.</p>
+        <pre>
+        $ sudo -u gitolite mkdir /srv/gitolite/deploy
+        </pre>
+
+        <p>Script
+        <a href="conf/srv/gitolite/hook.sh">/srv/gitolite/deploy/hook.sh</a>
+        receives call create_package "project-name" "git-dir"
+        "valid oldrev/invalid" "newrev" "script/to/call.sh" from gitolite hook
+        and creates a package.</p>
 
-        <p>This hook allows to select wich branch is deployed and if exists,
-        calls a script inside project folder with user www. This allows to
-        do post deploy (checkout) tasks such as composer update.</p>
+        <pre>
+        $ sudo -u gitolite cp conf/srv/gitolite/hook.sh /srv/gitolite/deploy/
+        </pre>
 
-        <p>Create <a href="../conf/srv/gitoliteolite/deployweb">deployweb</a>
-        in gitolite-admin/local/hooks/repo-specific;</p>
+        <p>Script
+        <a href="conf/srv/gitolite/deploy.sh">/srv/gitolite/deploy/deploy.sh</a>
+        loops for each package, extracts, order commit hashes to create final
+        snapshot of files and call script to handle deploy.</p>
 
         <pre>
-        $ vim ~/gitolite-admin/local/hooks/repo-specific/deployweb
+        $ sudo -u gitolite cp conf/srv/gitolite/deploy.sh /srv/gitolite/deploy/
         </pre>
 
+        <h3 id="gtl-setup">4.3. Setup project hook</h3>
+
+        <p>Project hooks create a package by calling hook.sh script and
+        deploy a package being called by deploy.sh. Deploy script is a
+        simple example that handle multiple web projects.</p>
+
+        <h4>4.3.1. Hook Script</h4>
+
+        <p>Create
+        <a href="conf/srv/gitolite/deploy-web-doc">gitolite-admin/local/hooks/repo-specific/deploy-web-doc</a>;</p>
+
         <pre>
         #!/bin/bash
-
         ######################################################################
         #
         # Put this file in your gitolite-admin;
-        # ~/gitolite-admin/local/hooks/repo-specific/deployweb
+        # ~/gitolite-admin/local/hooks/repo-specific/deploy-web-doc
         #
-        while read oldrev newrev refname
-        do
-                BRANCH=$(git rev-parse --symbolic --abbrev-ref $refname)
-                echo "Commit was for branch $BRANCH"
+        # 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"
 
-                if [[ "$BRANCH" == "master" ]];then
+        ######################################################################
 
-                        # Get project name from current directory (without .git)
-                        PROJECT=$(basename "$PWD")
-                        PROJECT=${PROJECT%.git}
 
-                        echo "Project $PROJECT added to deploy list."
-                        echo $PWD &gt; /srv/gitolite/deploy/$PROJECT
-                fi
+        url="$host/.last_deploy"
+        source /srv/gitolite/deploy/hook.sh
+        read oldrev newrev refname
+        push_branch=$(git rev-parse --symbolic --abbrev-ref $refname)
 
-        done
-        </pre>
+        #SCRIPT_VARS=$(set)
+        #echo "project: $PROJECT"
+        #echo "local dir: $PWD" &gt; /srv/gitolite/deploy/${GL_REPO}
+        #echo "${SCRIPT_VARS}" &gt;&gt; /srv/gitolite/deploy/${GL_REPO}
 
-        <p>Create deploy directory on remote;</p>
+        if [[ $push_branch = $branch_to_deploy  ]]; then
 
-        <pre>
-        # su - gitolite
-        $ mkdir deploy
+            # 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
         </pre>
 
-        <p>Add scripts to the repos you want them to be active in
-        your conf file. For example:</p>
+        <p>Activate this hook, the idea is to start with this one as a template working
+        and then implement the final one. Edit gitolite admin configuration file and
+        activate:</p>
 
         <pre>
-        repo atom @baz
-            option hook.post-receive     =  deployweb
+        repo c9-doc
+            config gitweb.description   =   "c9 documentation"
+            option hook.post-receive     =  deploy-web-doc
         </pre>
 
         <p>Add, commit, and push the admin repo;</p>
 
         <pre>
-        $ git add -u && git commit -m "deploy hook"
+        $ git add local/hooks/repo-specific/hook-deployweb
+        $ git add -u && git commit -m "added deploy c9 hook"
         </pre>
 
-        <p>On remote run;</p>
+        <p>Now we can test if our script is functioning by creating a branch on c9-doc
+        making a random change and push;<p>
 
         <pre>
-        # su - gitolite
-        $ gitolite setup
+        $ cd c9-doc
+        $ git checkout -b deploy_branch
         </pre>
 
-        <p>Create deploy script that cron will call
-        every minute, this script will check inside
-        /srv/gitolite/deploy folder for projects that have
-        been updated.</p>
+        <h4>4.3.2. Deploy Script</h4>
 
-        <p>Create <a href="../conf/srv/gitolite/deploy.sh">deploy.sh</a> in
-        /usr/share/gitolite;</p>
+        <p>Create
+        <a href="conf/srv/gitolite/deploy-web.sh">/srv/gitolite/deploy/scripts/deploy-web.sh</a>;</p>
 
         <pre>
-        $ vim /usr/share/gitolite/deploy.sh
-        </pre>
+        #!/bin/bash
 
-        <pre>
-    #!/bin/sh
+        pkg_path=$1
 
-    ######################################################################
-    #
-    # Put this file in;
-    # /usr/share/gitolite/deploy.sh
-    #
-    DIR_WWW=/srv/www/
-    DEPLOY_BRANCH=master
-    TARGET_USER=www
+        www_root="/srv/www"
+        www_user="nginx"
+        www_group="www"
 
-    for DP_FILE in /srv/gitolite/deploy/*
-    do
+        pkg_file="${pkg_path}/project"
+        pkg_rm="${pkg_path}/deleted"
+        pkg_files="${pkg_path}/files"
 
-        if [ ! -f "$DP_FILE" ]; then
-            # Nothing to do ;)
-            #echo "Deploy: invalid DP_FILE"
-            exit 1;
+        if [ ! -f ${pkg_file} ]; then
+            echo "Deploy web: invalid pkg_file ${pkg_file}"
+            exit 1
         fi
 
-        # Get project name
-        PROJECT=$(basename "$DP_FILE")
-        echo "Deploy: PROJECT=${PROJECT}"
+        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"
 
-        # Get git repository path and verify if exists
-        DIR_GIT=$(head -n 1 $DP_FILE)
-        if [ ! -d "$DIR_GIT" ]; then
-            echo "Deploy: invalid DIR_GIT: ${DIR_GIT}"
-            exit 2;
+        if [ ! -d ${pkg_www} ]; then
+            echo "Deploy web: invalid pkg_www ${pkg_www}"
+            exit 1
         fi
-        echo "Deploy: DIR_GIT=${DIR_GIT}"
-
-        # Get directory to deploy and verify if exists
-        GIT_WORK_TREE=${DIR_WWW}${PROJECT}/
-        if [ ! -d "$GIT_WORK_TREE" ]; then
-            echo "Deploy: invalid GIT_WORK_TREE: ${GIT_WORK_TREE}"
-            echo "Deploy: creating directory: $GIT_WORK_TREE}"
-            mkdir -p $GIT_WORK_TREE
+
+        # 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
-        echo "Deploy: GIT_WORK_TREE={$GIT_WORK_TREE}"
 
-        # Deploy (checkout)
-        echo "Deploy: starting git checkout"
+        # remove files and directories that have been deleted
+        if [ -f ${pkg_rm} ]; then
 
-        git --git-dir=$DIR_GIT \
-            --work-tree=$GIT_WORK_TREE \
-            checkout -f $DEPLOY_BRANCH
+            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 &lt;${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 &lt;${pkg_rm}
 
+        fi
 
-        # Fix ownership and permissions
-        echo "Deploy: fixing permissions"
+        # 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 "Deploy: setting owner: chown -R ${TARGET_USER}"
-        chown -R ${TARGET_USER}:${TARGET_USER} $GIT_WORK_TREE
+        echo ${pkg_new} > ${pkg_last}
+        echo "Deploy: scripts/deployweb.sh ${pkg_name} ${pkg_new7} deployed."
 
-        echo "Deploy: setting directory permissions: chmod 755"
-        find $GIT_WORK_TREE -type d -print0 | xargs -0 chmod 755
+        #remove temporary package
+        rm -r ${pkg_path}
+        </pre>
 
-        echo "Deploy: setting file permissions: chmod 644"
-        find $GIT_WORK_TREE -type f -print0 | xargs -0 chmod 644
+        <h4>4.3.3. Debuging hooks</h4>
 
-        # Call project script
-        if [ -f "${GIT_WORK_TREE}/deploy.sh" ]; then
-            echo "Deploy: calling ${GIT_WORK_TREE}deploy.sh"
-            cd ${GIT_WORK_TREE}
-            sudo -u ${TARGET_USER} sh ${GIT_WORK_TREE}deploy.sh
-        fi
+        <p>Comment gitolite admin repo script "if" and uncomment debug sections, this allow to
+        source the file with environment of hook.</p>
 
-        # Done with project
-        echo "Deploy: removing deploy file="$DP_FILE
-        rm $DP_FILE
+        <p>Later you can delete this branch locally and remote and start fresh. To test
+        if hook is called each time you push run;</p>
 
-        exit 0;
-    done
+
+        <pre>
+        $ echo $(( ( RANDOM % 10 ) +1 )) >> index.html && git add -u && git commit -m "test deploy" && git push git
         </pre>
 
+        <p>See if a file was created in /srv/gitolite/deploy with name of project and
+        with environmental variables of gitolite script.</p>
+
+        <p>From now on you can test changes directly on
+        /srv/gitolite/.gitolite/local/hooks/repo-specific/hook-deployweb
+        and repeat above command to see the results or create a separate script with
+        all variables generated by above script set so you don't have to push at all.</p>
+
+        <h4 id="gtl-deploy">4.4. Deploy with Cron</h4>
+
         <p>Add cron job to call deploy script every minute;</p>
 
         <pre>
@@ -406,9 +515,9 @@
         #
 
         # this way it will log
-        # * * * * * /usr/share/gitolite/deploy.sh
+        # * * * * * /usr/share/gitolite/deployweb
         # without log
-        * * * * * /usr/share/gitolite/deploy.sh > /dev/null 2>&1
+        * * * * * /usr/share/gitolite/deployweb > /dev/null 2>&1
 
         @hourly   ID=sys.hourly   /usr/sbin/runjobs /etc/cron/hourly
         @daily    ID=sys.daily    /usr/sbin/runjobs /etc/cron/daily
@@ -418,6 +527,106 @@
         # End of file
         </pre>
 
+        <h2 id="gitweb">5. Gitweb</h2>
+
+        <pre>
+        $ prt-get depinst p5-cgi p5-cgi-session libcgi \
+                        fcgiwrap spawn-fcgi highlight
+        </pre>
+
+        <h3>5.1. Configure gitweb</h3>
+
+        <p>Edit /etc/gitweb.conf</p>
+
+        <pre>
+        our $git_temp = "/srv/www/gitweb_tmp";
+
+        our $projects_list = "/srv/gitolite/projects.list";
+        # The directories where your projects are. Must not end with a slash.
+        our $projectroot = "/srv/gitolite/repositories";
+
+        # Base URLs for links displayed in the web interface.
+        our @git_base_url_list = qw(git://core.privat-network.com http://git@core.private-network.com);
+
+        our $projects_list_group_categories = 1;
+        </pre>
+
+        <h3>5.2. Configure nginx</h3>
+
+        <p>Edit /etc/rc.d/fcgiwrap to run as nginx user member of gitolite
+        and www group;</p>
+
+        <pre>
+        USER=nginx
+        GROUP=nginx
+        </pre>
+
+        <pre>
+        # usermod -G www,gitolite nginx
+        </pre>
+
+        <p>Create link from gitweb to web server folder;</p>
+
+        <pre>
+        # ln -s /usr/share/gitweb /srv/www
+        </pre>
+
+        <p>Add this to default or main
+	<a href="nginx.html#virtual-host">nginx virtual host</a>;</p>
+
+        <pre>
+	location /gitweb/gitweb.cgi {
+            alias /srv/www/gitweb;
+	    include fastcgi_params;
+	    gzip off;
+	    fastcgi_param   SCRIPT_FILENAME  /srv/www/gitweb/gitweb.cgi;
+	    fastcgi_param   GITWEB_CONFIG    /etc/gitweb.conf;
+	    fastcgi_pass    unix:/var/run/fcgiwrap.sock;
+	}
+
+	location /gitweb {
+	    alias /srv/www/gitweb;
+	    index gitweb.cgi;
+	}
+	</pre>
+
+        <h3>5.3. Configure gitolite</h3>
+
+        <p>Edit
+        <a href="conf/srv/gitolite/.gitolite.rc">/srv/gitolite/.gitolite.rc</a>,
+        change UMASK and GIT_CONFIG_KEYS to;</p>
+
+        <pre>
+        # 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                 =>  '.*',
+        </pre>
+
+        <p>Fix permissions;</p>
+
+        <pre>
+        $ sudo chown -R gitolite:gitolite /srv/gitolite
+        $ sudo chmod g+rx /srv/gitolite/projects.list
+        $ sudo chmod -R 755 /srv/gitolite/repositories/
+        </pre>
+
+        <p>Edit gitolite-admin/conf/gitolite.conf;</p>
+
+        <pre>
+        repo c9-doc
+            config gitweb.owner         =   c9 team
+            config gitweb.description   =   c9 documentation
+            config gitweb.category      =   c9
+
+        repo c9-ports
+            config gitweb.owner         =   c9 team
+            config gitweb.description   =   c9 ports
+            config gitweb.category      =   c9
+        </pre>
+
         <a href="index.html">Tools Index</a>
         <p>This is part of the c9-doc Manual.
         Copyright (C) 2016