Apache serve arquivos de ramificações git repo

4

Existe alguma maneira de servir arquivos de filiais em um repositório git sem verificá-los em diretórios diferentes?

Eu adoraria a conveniência de poder criar uma nova ramificação, enviá-la para um repositório do servidor de teste e fazer algo como navegar até http: // branchname .test.com. Eu posso usar regras de reescrita para lidar com o subdomínio do nome da ramificação para apontar para diferentes caminhos de raiz, mas o Apache não pode ler repos nuas, é claro.

gitfs pode funcionar, mas parece abandonado.

Eu não preciso especialmente do Apache.

    
por Van Gale 01.02.2010 / 21:51

3 respostas

2

A abordagem mais simples seria verificar cada ramificação e criar clones para cada ramificação em subdiretórios. É muito fácil fazer isso com um script executado pelo cron (ou em um gancho post-commit) como:

#!/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

Depois do trabalho, você receberá vários diretórios com ramificações em /srv/repos .

git clone --local é muito rápido e ideal mesmo em repositórios enormes como o kernel do Linux, porque ele não cria todos os objetos no repositório, mas cria links para eles, assim você não desperdiçará espaço em cópias do repositório. Você perderá espaço em cópias com check-out, mas a) provavelmente não são muito grandes e b) isso tornará o acesso baseado na Web muito mais fácil e rápido.

    
por 01.02.2010 / 22:26
3

Você pode servir conteúdo diretamente do repositório usando uma combinação de git-show (ou git cat-file) e Apache CGI ou similar. Eu configurei um exemplo usando o .htaccess e um script zsh simples, como segue:

.htaccess

Options +ExecCGI
AddHandler cgi-script .sh

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

index.sh

#!/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 :

Isso pressupõe que seu site esteja em site.git na mesma pasta dos dois arquivos acima. Há muitas melhorias que podem ser feitas no script - como comentadas. Isso é mais uma prova de conceito.

    
por 30.01.2013 / 11:18
1

Também dê uma olhada em Divergence , um aplicativo de rack que mapeia git branches para subdomínios. Eu ainda não usei o meu eu, mas parece se encaixar muito bem às suas necessidades.

    
por 04.02.2013 / 22:07