Apache 从 git repo 分支提供文件

Apache 从 git repo 分支提供文件

有没有办法可以从 git repo 中的分支提供文件,而无需将它们检出到不同的目录中?

我喜欢能够创建一个新分支、将其推送到测试服务器存储库,然后执行诸如浏览到 http://分店名称.test.com。我可以使用重写规则来处理分支名称子域以指向不同的根路径,但 Apache 当然无法读取裸存储库。

吉特夫斯可能会有用,但似乎已被废弃。

我也不特别需要 Apache。

答案1

最简单的方法是检查每个分支并在子目录中为每个分支创建克隆。使用 cron 运行的脚本(或在提交后挂钩中)可以很容易地做到这一点,例如:

#!/bin/sh
ROOT=/srv/repos/control
cd ${ROOT} # it's an internal repo
git fetch
for ref in .git/refs/remotes/origin/*; do
  BRANCH=`basename ${ref}`
  if ! [ -d ../${BRANCH} ]; then
    git clone --local ${ROOT} ../${BRANCH}
    cd ../${BRANCH}
    git branch --track ${BRANCH} remotes/origin/${BRANCH}
    git checkout ${BRANCH}
  else
    cd ../${BRANCH}
    git pull
  fi
done

它工作完成后,你会得到一堆带有分支的目录/srv/repos

git clone --local即使在 Linux 内核等大型存储库上也非常快速且优化,因为它不会在存储库中创建所有对象,而是创建指向它们的硬链接,因此您不会在存储库副本上浪费任何空间。虽然您会在签出的副本上浪费空间,但 a) 它们可能不是很大,b) 这将使基于 Web 的访问更加轻松快捷。

答案2

您可以使用 git-show(或 git cat-file)和 Apache CGI 或类似程序的组合直接从存储库提供内容。我使用 .htaccess 和一个简单的 zsh 脚本设置了一个示例,如下所示:

.htaccess

Options +ExecCGI
AddHandler cgi-script .sh

RewriteEngine On
RewriteRule ^(?!index.sh)(.*)$ /index.sh [L]

索引文件

#!/bin/zsh

# Strips the initial slash, as git show ain't got time for that!
# REQUEST_URI is set by Apache when executing the script.
# You may also be interested in HTTP_HOST which is the request host.
# Don't get confused with HOST which is a default shell variable.
function get_request_uri {
    if [ $REQUEST_URI[0,1] = '/' ]
    then
        REQUEST_URI=$REQUEST_URI:s#/##
    fi

    echo $REQUEST_URI
}

# You may not want to show the folders (represented by trees).
# Or you may want to manipulate the output to produce a proper directory index.
function is_file_folder {
    [ $(git cat-file -t HEAD:$1) = 'tree' ]
}

# Just gets the content of the file.
# For trees will produce a directory listing, one line per file.
# To show different branches, pass them to git show in place of HEAD
function get_file_content {
    local file=$1

    git show HEAD:${file}
}

# Attempts to determine the file type without writing the data to a file.
# Has to resort to manually looking up the type in /usr/share/mime/globs
# to test by extension, you may have to adjust that code to your environment.
function get_file_type {
    local file=$1
    local content=$2

    mime_type=$(echo ${content} | mimetype -b --stdin)
    if [ -e /usr/share/mime/globs ]
    then
        file_mime_type=$(
            grep "\*.${file:e}\$" /usr/share/mime/globs |
                sed -ne 's/:.*$//' -e '1p'
                    )

        # Conflict resolution is also something you should work on.
        if [ $file_mime_type != '' ]
        then
            mime_type=$file_mime_type
        fi
    fi

    echo $mime_type
}

function do_404 {
    echo 'Status: 404 Not Found'
    echo ''
}

# Just does the header because there can be problems
# getting binary data to the client by echoing it.
# A little something for you to explore a fix for :)
function do_200 {
    mime_type=$1

    echo "Content-Type: $mime_type"
    echo ''
}


cd site.git

uri=$(get_request_uri)
file_content=$(get_file_content $uri)

# A non zero exit status from git show probably means the file does not exist.
# Even if the error was something else, you still have nothing to show for it.
if [ $? -ne 0 ]
then
    do_404
fi

# You may not want to do the directory listing. Even if you do, you may
# not want to use the default directory listing (which is very primitive).
# If you wanted to redirect to index or similar, you would also handle that
# here.
if is_file_folder $uri
then
    file_type='text/plain'
else
    file_type=$(get_file_type $uri "$file_content")
fi

do_200 $file_type

# Doing this twice is not optimal, but it is very easy to
# mangle binary data accidentally when passing around the
# $file_content. Just reading the file directly to the client
# seems to sidestep this. Another thing for you to fix :)
get_file_content $uri

# You might want to uncomment the two lines below (commenting out 
# any response code from above first), to show all of the variables
# available to you. This list will include the variables set by this
# script - to filter them out just run this earlier, with an exit after.

# do_200 'text/plain'
# set

# vim: set ai et sw=4 syntax=zsh :

这假设您的站点位于与上述两个文件位于同一文件夹中的 site.git 中。如评论所述,可以对脚本进行大量改进。这更像是一个概念验证。

答案3

另请参阅分歧,一个将 git 分支映射到子域的 rack 应用程序。我自己还没有用过它,但它似乎很适合你的需求。

相关内容