From b0298618a3d2eb3787590206fbad381a5ce9d940 Mon Sep 17 00:00:00 2001 From: Sitaram Chamarty Date: Fri, 16 Nov 2012 13:24:55 +0530 Subject: [PATCH] namespace support; see http://sitaramc.github.com/gitolite/namespaces.html --- src/commands/mirror | 3 +++ src/gitolite-shell | 2 +- src/lib/Gitolite/Conf/Load.pm | 32 +++++++++++++++++++++++++ src/lib/Gitolite/Triggers/Mirroring.pm | 2 ++ src/lib/Gitolite/Triggers/Namespaces.pm | 32 +++++++++++++++++++++++++ 5 files changed, 70 insertions(+), 1 deletion(-) create mode 100755 src/lib/Gitolite/Triggers/Namespaces.pm diff --git a/src/commands/mirror b/src/commands/mirror index d091979..e455cb6 100755 --- a/src/commands/mirror +++ b/src/commands/mirror @@ -51,6 +51,9 @@ if ( $cmd eq 'push' ) { trace(1, `cat gl-perms 2>/dev/null | ssh $host CREATOR=$creator perms -c \\'$repo\\'`); } + my ($ns, $rr) = repo_namespace($repo); + trace(1, "'$repo' is a namespace in '$rr', skipping push"), exit 0 if $rr; + my $errors = 0; for (`git push --mirror $host:$repo 2>&1`) { $errors = 1 if $?; diff --git a/src/gitolite-shell b/src/gitolite-shell index a3ec321..3566b1a 100755 --- a/src/gitolite-shell +++ b/src/gitolite-shell @@ -128,7 +128,7 @@ sub main { if ($ENV{REQUEST_URI}) { _system( "git", "http-backend" ); } else { - my $repodir = "'$rc{GL_REPO_BASE}/$repo.git'"; + my $repodir = "'$rc{GL_REPO_BASE}/" . ( $rc{REALREPO} || $repo ) . ".git'"; _system( "git", "shell", "-c", "$verb $repodir" ); } trigger( 'POST_GIT', $repo, $user, $aa, 'any', $verb ); diff --git a/src/lib/Gitolite/Conf/Load.pm b/src/lib/Gitolite/Conf/Load.pm index 2611630..be9b213 100644 --- a/src/lib/Gitolite/Conf/Load.pm +++ b/src/lib/Gitolite/Conf/Load.pm @@ -11,6 +11,7 @@ package Gitolite::Conf::Load; option repo_missing + repo_namespace creator vrefs @@ -203,6 +204,37 @@ sub repo_missing { return not -d "$rc{GL_REPO_BASE}/$repo.git"; } +sub repo_namespace { + my $repo = shift; + sanity($repo); + + my $ref = git_config( $repo, "^gitolite-options\\.namespace\\.pattern.*" ); + return () if not %$ref; # no namespace options provided + + for my $k (sort keys %$ref) { + my $v = $ref->{$k} || ''; + _die "bad namespace option value '$v'" if not $v =~ /^(\S+) is (\S+) in (\S+)$/; + my ($p, $ns, $rr) = ($1, $2, $3); + + # interpret $p and match $repo against it + $p =~ s(\*)((.*))g; + $p =~ s(%)(([^/]*))g; + $p = "^$p\$"; + + my @matches; + next unless @matches = ($repo =~ qr($p)); + $ns =~ s(@(\d+))($matches[$1-1] or _die "bad namespace option-value '$v'")ge; + $rr =~ s(@(\d+))($matches[$1-1] or _die "bad namespace option-value '$v'")ge; + + # check if namespace processing was explicitly disabled + return () if $rr eq $repo; + + return ($ns, $rr); + } + + _die "no namespace options matched for '$repo'"; +} + # ---------------------------------------------------------------------- sub load_common { diff --git a/src/lib/Gitolite/Triggers/Mirroring.pm b/src/lib/Gitolite/Triggers/Mirroring.pm index 80a2448..1991403 100644 --- a/src/lib/Gitolite/Triggers/Mirroring.pm +++ b/src/lib/Gitolite/Triggers/Mirroring.pm @@ -146,6 +146,7 @@ sub post_git { # slave was eliminated earlier anyway, so that leaves 'master' # find all slaves and push to each of them + push_to_slaves( $rc{REALREPO} ) if $rc{REALREPO}; push_to_slaves($repo); return; @@ -165,6 +166,7 @@ sub post_git { trace( 3, "case 2, slave redirect" ); # find all slaves and push to each of them + push_to_slaves( $rc{REALREPO} ) if $rc{REALREPO}; push_to_slaves($repo); return; diff --git a/src/lib/Gitolite/Triggers/Namespaces.pm b/src/lib/Gitolite/Triggers/Namespaces.pm new file mode 100755 index 0000000..59f2060 --- /dev/null +++ b/src/lib/Gitolite/Triggers/Namespaces.pm @@ -0,0 +1,32 @@ +package Gitolite::Triggers::Namespaces; + +use Gitolite::Rc; +use Gitolite::Common; +use Gitolite::Conf::Load; + +use strict; +use warnings; + +# allow the server to use namespaces without the users needing to know +# ---------------------------------------------------------------------- + +# see http://sitaramc.github.com/gitolite/namespaces.html for instructions and +# important warnings + +sub pre_git { + my $repo = $_[1]; + + my ($ns, $rr) = repo_namespace($repo); + return if not $ns; + + $ENV{GIT_NAMESPACE} = $ns; + $rc{REALREPO} = $rr; + trace( 1, "GIT_NAMESPACE = $ns, REALREPO = $rr"); +} + +sub post_git { + delete $ENV{GIT_NAMESPACE}; +} + + +1;