Edgewall Software
Modify

Opened 7 years ago

Last modified 3 years ago

#10730 new enhancement

Provide Git hooks to call trac-admin

Reported by: Peter Suter Owned by:
Priority: normal Milestone: next-stable-1.2.x
Component: plugin/git Version:
Severity: normal Keywords: hook
Cc: hvr@… Branch:
Release Notes:
API Changes:

Description

As mentioned on TracGit#hooks and as discussed in #10594, we should provide a post-receive hook script for Git to call trac-admin.

References

Attachments (1)

trac-git-hook-post-receive.sh (2.2 KB ) - added by Jun Omae 5 years ago.

Download all attachments as: .zip

Change History (17)

comment:1 by Peter Suter, 7 years ago

Quoting cboos from #10594:

Given that Git on Windows is run either via msysGit or via Cygwin, we only need something like the trac-svn-hook script. Such a script is also the key component if we want to support some kind of "pushlog" (#9205).

comment:2 by Christian Boos, 7 years ago

Milestone: next-stable-1.0.x
Owner: set to Christian Boos

I'll have a try, possibly even for 1.0 (but not for the beta).

comment:3 by hvr@…, 7 years ago

Cc: hvr@… added

comment:4 by anonymous, 7 years ago

Here's a nice hook (see discussion of Nilesh and Giotti) for gitolite http://nileshgr.com/2012/08/08/trac-and-git-the-right-way.html The hook is at http://pastie.org/4782090

comment:5 by giotti, 7 years ago

This hook is useful when running multiple repositories for one, or several Trac environments in conjunction with gitolite (https://github.com/sitaramc/gitolite#readme).

The hook assumes that the "filename" of the git-repository has the same name as the Trac environment, followed by a separator (defined in the script), and the name of the repository. However, the name of the repository inside Trac, should omit the environment name (i.e. let it appear how you want inside Trac). If the repository name consists of only one word (e.g. there is only one repository for the environment), the hook will fall back to the default name provided in the script (Trac uses (Default), unless something was changed).

When using this post-receive hook, the git repositories' directory name should be named according to the pattern:

<environment name><separator><trac-repository-name>,

whereas the repository name inside, or as called in Trac should skip the <environment name> resulting in just:

<trac-repository-name>

Example: If you have the environments Android and iOS, each with two git repositories Repo-One and Repo-Two; the git repositories should be named: Android-Repo-One, Android-Repo-Two, iOS-Repo-One, and iOS-Repo-Two in gitolite.conf, but just Repo-One and Repo-Two inside Trac.

As you can see in the above example, you can re-use the separator in the name of the git-repository, if you please. However, the hook will fail on environments with the name containing the separator, i.e. a push to the repository Environment-One-Repo-One results in the hook trying to run trac-admin for the environment Environment, instead of Environment-One.

I'm not sure, whether "off-loading" the last bit of the Trac-environment-path to the repository name poses a security risk, e.g. if someone would push a repository with i.e. a semicolon in the name, but I believe gitolite should catch any attempts to push to a non-existing repository and exit prior to running the hook.

giotti

Here's the hook:

Code highlighting:

#!/bin/bash
# Gitolite-Trac post-receive hook
# Script written by Nilesh Govindrajan; http://nileshgr.com
# Updated by giotti to support multiple repositories.
# Assumptions:
# 1: all trac environments are saved under one common directory
#       defined in tracenv. e.g. /path/to/all/my/trac/envs
# 2: all repositories of an environment follow the naming-pattern
#       <environment><delimeter><repository name>[<delimeter><repository name continued>...],
#       e.g. someproject-somerepository, or someproject-somerepository-with-extra-text
# 3: The Name of the repo itself (defined in trac) is the same as the git-repository
#       without the environment name; e.g. somerepository, or
#       somerepository-with-extra-text, instead of someproject-somerepository
# 4: Capitalization is the same throughout gitolite and trac (see todo in
#       changelog.
#
# Changelog:
# 1.02
# - Added skipping the hook, when gitolite-admin is detected
# - Added multi-repository support for all environments in one directory-tree
# - TODO: implement capitalization mapping of trac <-> git,
#       e.g. when repo is "Foo-Bar" and trac env is "foo" with repo "Bar"
# This script is released under the GNU GPL v3
# Licensed changed to BSD as suggested by Giotti

set -u
tracenv=/var/www/trac/projects # Full path to trac environment except for the last bit
tracadmin=/usr/local/bin/trac-admin # Path to trac-admin
tracdefault='"(default)"' # Trac default repository name (usually: "(default)")
logfile=/var/www/trac/log/post-receive.log # you can always log to /dev/null
delimeter="-" # you can select a different separation-delimeter here (e.g. "_")

date > ${logfile} # init logfile (if you want a continuous log, change ">" to ">>"

# Check that the repo in question is something other than gitolite-admin, otherwise exit.
if [ "${GL_REPO}" != "gitolite-admin" ]
then
 reponame="${GL_REPO}"
else
 echo "gitolite-admin modification detected. Exiting post-receive hook..." >> ${logfile}
 exit 0
fi

# save current IFS
OIFS=$IFS
# split $GL_REPO by delimeter
IFS="$delimeter" && parts=($GL_REPO)

#create new repo-string containing all array parts except the first (e.g. ${parts[0]})
reponame="${parts[*]:1}"
if [ -z "$reponame" ]; then reponame=$tracdefault; fi # (or set to trac-default)

# append first part of GL_REPO parts to tracenv
tracenv="$tracenv/${parts[0]}"

# restore original IFS
IFS=$OIFS

# log our selection
echo "GL_REPO was set to: ${GL_REPO}. Using repo-name: $reponame on trac-environment: $tracenv" >> ${logfile}

while read -s line
do
        [ -z "$line" ] && break
        commithash=$(echo $line | cut -d' ' -f2)
        # prepare changeset command
        cmd1="$tracadmin $tracenv changeset added $reponame $commithash"
        # prepare resync command to be called, when deleting commits & using "git push -f"
        cmd2="$tracadmin $tracenv repository resync $reponame"
        # run either changeset or repository resync
        eval "$cmd1" || eval "$cmd2"
        # log commands
        echo "CMD1: $cmd1" >> ${logfile}
        echo "CMD2: $cmd2" >> ${logfile}

done

Source: https://gist.github.com/3768589

in reply to:  5 comment:6 by giotti, 7 years ago

Replying to giotti:

I'm not sure, whether "off-loading" the last bit of the Trac-environment-path to the repository name poses a security risk, e.g. if someone would push a repository with i.e. a semicolon in the name, but I believe gitolite should catch any attempts to push to a non-existing repository and exit prior to running the hook.

Sorry for the FUD. A hook is only symlinked to the hooks-directory of existing repositories. In addition, GL_REPO would be unset, since it would be impossible to connect to a non-existing repository. According to sitaram from #gitolite@freenode:

[…]forget gitolite, why would *git* execute a hook on a non-existing repo? In fact, how can a hook even *exist* when the repo doesn't?[…]

and

if a hook is running in a repo called foo/bar, gitolite will set GL_REPO to foo/bar, and will not allow it to be somehow set to some other value.

comment:7 by anonymous, 6 years ago

It is a little bit confusing, that there is no trac-post-receive-hook script in the Trac distribution. When one is looking at the GitPlugin page, there are several scripts attached and it is not easy to see, which one is the "best". Trac should come with a "blessed" script, please.

comment:8 by Jun Omae, 5 years ago

I've created post-receive:ticket:10602 which git repository and trac environment can be specified via environment variables and git config. I'll create the same script for Windows and add comments to scripts later.

in reply to:  description comment:9 by Peter Suter, 5 years ago

TracRepositoryAdmin#Git currently also contains some recommendations for a post-receive script. And there's another script at attachment:post-receive-hook.py:wiki:TracGit. If these are problematic they should maybe be removed to avoid confusion.

comment:10 by Jun Omae, 5 years ago

Yeah. I think we should additionally provide those git hook scripts in contrib directory like trunk/contrib/trac-svn-hook.

Also, if many commits are pushed, the hook script in TracRepositoryAdmin#Git is very slow since trac-admin is executed each commit. We should improve it.

by Jun Omae, 5 years ago

in reply to:  8 comment:11 by Jun Omae, 5 years ago

I've created post-receive:ticket:10602 which git repository and trac environment can be specified via environment variables and git config. I'll create the same script for Windows and add comments to scripts later.

trac-git-hook-post-receive.sh. I created post-receive hook as a shell script.

comment:12 by Ryan J Ollos, 5 years ago

Owner: Christian Boos removed

comment:13 by Ryan J Ollos, 3 years ago

Milestone: next-stable-1.0.xnext-stable-1.2.x

Moved ticket assigned to next-stable-1.0.x since maintenance of 1.0.x is coming to a close. Please move the ticket back if it's critical to fix on 1.0.x.

comment:14 by Peter Suter, 3 years ago

#12763 proposes another script.

Maybe someone with the know-how could create a CookBook page to collect and compare the different approaches if there's no clear "winner"?

comment:15 by Peter Suter, 3 years ago

Keywords: hook added

comment:16 by Ryan J Ollos, 3 years ago

#12763 closed as a duplicate and provides an example hook. The hook in comment:11 looks good to me. It would be good to have some logging. trunk/contrib/trac-svn-hook logs to svn-hooks-<reponame>.log, which is helpful in debugging issues.

Modify Ticket

Change Properties
Set your email in Preferences
Action
as new The ticket will remain with no owner.
The ticket will be disowned. Next status will be 'new'.
as The resolution will be set. Next status will be 'closed'.
The owner will be changed from (none) to anonymous. Next status will be 'assigned'.

Add Comment


E-mail address and name can be saved in the Preferences .
 
Note: See TracTickets for help on using tickets.