{"id":762,"date":"2009-05-11T11:28:14","date_gmt":"2009-05-11T15:28:14","guid":{"rendered":"http:\/\/dougmunsinger.com\/?p=762"},"modified":"2009-05-11T11:28:14","modified_gmt":"2009-05-11T15:28:14","slug":"subversion-cg-tool-list-repositories","status":"publish","type":"post","link":"https:\/\/wp.dougmunsinger.com\/2009\/05\/11\/subversion-cg-tool-list-repositories\/","title":{"rendered":"another tool for SVN – list_repositories.pl"},"content":{"rendered":"

 <\/p>\n

 <\/p>\n

One of the features of subversion + apache2 is the ability to list repositories – natively. <\/p>\n

SVNParentPath \/apps\/repos
\nSVNListParentPath on<\/p>\n

Unfortunately, once you restrict the httpd.conf to individual repositories and start handling permissions separately you lose that.  Both of these permissions, set at the top level, at the parent path to the repositories, have to be commented out to have the individual permissions on the directories below take effect.<\/p>\n

And listing just the repositories wasn’t enough for what I had in mind – I wanted a read-only table showing an individual developer or a team lead for a project who has what permissions for the subversion repositories. All the users, all the repositories.<\/p>\n

Just your basic cgi.<\/p>\n

 <\/p>\n

\"repos\"<\/a><\/p>\n

 <\/p>\n

 and the script:<\/p>\n


\n<\/a>#! \/bin\/perl -w<\/p>\n

\n# script to parse and display users and repositories and rights (R, RW)<\/p>\n

use strict;
\nuse CGI qw(:standard);
\nuse CGI::Carp qw(fatalsToBrowser);<\/p>\n

\n##----------------------------
\n## Variables
\n##----------------------------<\/p>\n

\n#debug
\nmy $debug = 0; #set to 0 to turn off, 1 (true) to turn on <\/p>\n

# title for page
\nmy $PageTitle = "List of SVN Repositories";<\/p>\n

## repository directory
\nmy $SVN = "\/apps\/repos";
\n## location for htpasswd files
\nmy $HTDIR = "\/apps\/apache2\/conf\/htpasswd";
\n## Set untainted path
\n$ENV{PATH} = '\/apps\/apache2\/bin:\/bin:\/usr\/bin:\/usr\/local\/bin';
\n$ENV{IFS} = "" if $ENV{IFS} ne "";<\/p>\n

# css
\nmy $css = "http:\/\/<your server name>\/css\/main.css";
\nmy $headerimg = "http:\/\/<your server name>\/css\/roger_rabbit_120.jpg";<\/p>\n

\n##------------------------------
\n## MAIN
\n##------------------------------<\/p>\n

&standard_header;
\nmy ($ref_repos, $ref_tabledata, $ref_users) = &CreateTableSpace;
\n&DisplayTable ($ref_repos, $ref_tabledata, $ref_users);
\n&standard_footer;
\nexit;<\/p>\n

##------------------------------
\n## subs
\n##------------------------------<\/p>\n

sub standard_header {
\n    print header();
\n    print start_html(-Title => "$PageTitle", -BGCOLOR=>"White",
\n        -style => {
\n            -src => "${css}"
\n        }
\n    );
\n    print ("<div id="header">n");
\n    print p("<img src="${headerimg}" title="Wells logo" alt="wells logo"\/>n");
\n    print ("<\/div>n");
\n    print ("<div id="headertitle">n");
\n    print h3("Repositories<br\/>nusers | read (R) | read & write (RW)n"); # start_multipart_form() if file upload
\n}<\/p>\n

\nsub standard_footer {
\n    print end_html();
\n}<\/p>\n

\nsub CreateTableSpace {
\n    my $ref_repos = &GetBlankRepos;
\n    my @repos = @$ref_repos; # dereference
\n    my %tabledata = (); # hash to hold table data
\n    my @users = (); # list of users
\n    my %seen = ();
\n    foreach my $rep (@repos) {
\n        open(FILE, "$HTDIR\/${rep}_read") || croak "Failed to open $HTDIR\/${rep}_read for reading...";
\n        my @filelines = <FILE>;
\n        close FILE;
\n        foreach my $line (@filelines) {
\n            # lines are user:passwd
\n            my ($user, $pass) = split (":", $line);
\n            unless ($seen{$user}) {
\n                $seen{$user} = 1; # save as seen
\n                push (@users, $user); # save the user to a list
\n            }
\n            $tabledata{$rep}{$user} = "read";
\n        }
\n        open (FILE, "$HTDIR\/${rep}_write") || croak "Failed to open $HTDIR\/${rep}_write for reading";
\n        my @file_lines = <FILE>;
\n        close FILE;
\n        foreach my $line (@file_lines) {
\n            # lines are user:passwd
\n            my ($user, $pass) = split (":", $line);
\n            unless ($seen{$user}) {
\n                $seen{$user} = 1; # save as seen
\n                push (@users, $user); # save the user to a list
\n            }
\n            $tabledata{$rep}{$user} = "readwrite";
\n        }
\n    }
\n    return (@repos, %tabledata, @users);
\n}<\/p>\n

\nsub GetBlankRepos {
\n    my @repos = ();
\n    # list $SVN
\n    opendir (DIR, $SVN) || croak "Failed to open directory $SVN for reading...";
\n    while (defined(my $file = readdir(DIR))) {
\n        # skip ".", ".." and .<hidden> files...
\n        if ($file =~ \/^.\/) {
\n            next;
\n        } else {
\n            push(@repos, $file);
\n        }
\n    }
\n    return (@repos);
\n}<\/p>\n

sub DisplayTable {
\n    my $ref_repos = shift;  #@repos
\n    my $ref_tabledata = shift; # %tabledata
\n    my $ref_users = shift; # @users
\n    # dereference
\n    my @repos = @$ref_repos;
\n    my %tabledata = %$ref_tabledata;
\n    my @users = @$ref_users;
\n    # repos across the top, users down, R or RW for permissions
\n    # $tabledata{$rep}{$user} = "readwrite";
\n    # start table
\n    print ("<table>n<tbody>n");
\n    # table header
\n    my $cols = ($#repos + 1);
\n    print ("<tr><td>Users<\/td><td colspan="$cols">Repositories<\/td><\/tr>n");
\n    print ("<div id="repotitles"><tr>n<td>&nbsp;<\/td>");
\n    foreach my $rep (@repos) {
\n        print ("<td>$rep<\/td>");
\n    }
\n    print ("n<\/tr>n<\/div>n");
\n    foreach my $user (@users) {
\n        print ("<tr>n<td>$user<\/td>");
\n        foreach my $repo (@repos) {
\n            if ($tabledata{$repo}{$user}) {
\n                if ($tabledata{$repo}{$user} eq "read") {
\n                    print ("<td>R<\/td>");
\n                } elsif ($tabledata{$repo}{$user} eq "readwrite") {
\n                    print ("<td>RW<\/td>");
\n                }
\n            } else {
\n                print ("<td>&nbsp; - &nbsp;<\/td>");
\n            }
\n        }
\n        print ("n<\/tr>n");
\n    }
\n    # finish table
\n    print ("<\/tbody>n<\/table>n");
\n}<\/code><\/p>\n","protected":false},"excerpt":{"rendered":"

    One of the features of subversion + apache2 is the ability to list repositories – natively.  SVNParentPath \/apps\/repos SVNListParentPath on Unfortunately, once you restrict the httpd.conf to individual repositories and start handling permissions separately you lose that.  Both of these permissions, set at the top level, at the parent path to the repositories,…<\/p>\n","protected":false},"author":1,"featured_media":1981,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,18,58,59,61,69],"tags":[105,242,259,261],"class_list":["post-762","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-apache2","category-eclipse","category-solaris","category-subversion","category-tools","category-websphere","tag-cgipm","tag-script","tag-subversion","tag-svn"],"_links":{"self":[{"href":"https:\/\/wp.dougmunsinger.com\/wp-json\/wp\/v2\/posts\/762"}],"collection":[{"href":"https:\/\/wp.dougmunsinger.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wp.dougmunsinger.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wp.dougmunsinger.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wp.dougmunsinger.com\/wp-json\/wp\/v2\/comments?post=762"}],"version-history":[{"count":0,"href":"https:\/\/wp.dougmunsinger.com\/wp-json\/wp\/v2\/posts\/762\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wp.dougmunsinger.com\/wp-json\/wp\/v2\/media\/1981"}],"wp:attachment":[{"href":"https:\/\/wp.dougmunsinger.com\/wp-json\/wp\/v2\/media?parent=762"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wp.dougmunsinger.com\/wp-json\/wp\/v2\/categories?post=762"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wp.dougmunsinger.com\/wp-json\/wp\/v2\/tags?post=762"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}