juan reyero

git-server — create a central git repository

I have several computers, and an online server at juanreyero.com. All my code is managed with git, and it is very convenient to have a central repository in the server that I can use as the canonical source for all my computers. This script builds a repository on the server with the current repository, and clones it back; from then on, all copies of the repository in all my computers are cloned from the server, and all I have to do is git pull before I start working, and git push after I finish, to ensure that they are all in sync.

For a project prj (that is, in a directory prj), what it does is:

# In the server
mkdir -p prj.git
GIT_DIR=prj.git git-init

# In local
cd prj
git push --all juanreyero@juanreyero.com:git/prj.git
cd ..
mv prj ~/tmp
git clone juanreyero@juanreyero.com:git/prj.git

It takes the remote user, remote machine and remote git base directory form an environment variable GITS that, in my case, looks like:

echo $GITS
juanreyero@juanreyero.com:git

The script:

#!/usr/bin/perl -w

use strict;
use Cwd qw(getcwd abs_path);
use Getopt::Long;

my $server = $ENV{GITS};
my $bring = 0;
my $help = 0;
my $tmp = "$ENV{HOME}/tmp";

GetOptions('h'        => \$help,
           'help'     => \$help,
           'b'        => \$bring,
           'bring'    => \$bring,
           's=s'      => \$server,
           't=s'      => \$tmp,
           'tmpdir=s' => \$tmp,
           'server=s' => \$server);

if ($help) {
    print qq(git-server --- Sends or brings projects to/from server.
         When sending it creates the remote project, pushes from the
         local, then moves the local to ~/tmp/ and clones back from
         the server.  When bringing clones locally all the
         repositories in the remote directory. 

Usage:  git-server [options] [dir]

Options:
-h
--help                    This help
-t dir
--tmpdir=dir              Where to back up the project before cloning 
                          back from the server
-b
--bring                   Clones here the projects in the server,
                          instead of sending out the repository to the
                          server (and then cloning here). 
-s user\@server:dir
--server=user\@server:dir  Where and how to find the remote repository.  
                          Defaults to the value of the environment
                          variable GITS
dir                       the directory in the server.  Defaults to
                          the last part of the current path. 
);
    die "\n"; 
}

sub git_bring
{
    my ($user, $server, $server_dir, $dir) = @_;
    $server_dir = "$server_dir/$dir";
    print "Fetching projects from $server/$server_dir\n";
    my $prjlist = `ssh -l $user $server 'ls $server_dir'`;

    my @prjs = split /\s+/, $prjlist;
    foreach my $prj (@prjs) {
        my $prjname = $prj;
        $prjname =~ s/\.git$//;
        print "Cloning $prjname\n";
        system "git clone $server/$dir/$prj $prjname";
    }
}

sub git_send
{
    my ($user, $server, $server_dir, $dir) = @_;
    unless ($dir) {
        die "Cannot send current dir.\n";
    }
    $dir =~ s/\/$//;
    unless (-d "$dir/.git") {
        die "Should first build a repository in $dir.  Try:\n" . 
            "  cd $dir; git init; git add .; git commit\n";
    }

    print "Building remote repository at $user\@$server:$server_dir/$dir.git\n";
    system("ssh -l $user $server 'cd $server_dir; mkdir -p $dir.git; GIT_DIR=$dir.git git init'");
    print "Sending it...";
    system("cd $dir;git push --all $user\@$server:$server_dir/$dir.git;cd ..");

    $tmp =~ s/\/$//;
    print "$tmp\n";
    unless (-d $tmp) {
        mkdir($tmp);
    }
    print "Moving $dir to $tmp/$dir\n";
    if (-d "$tmp/$dir") {
        die "Please take $tmp/$dir out of the way\n";
    }
    system("mv $dir $tmp");
    print "And cloning it back\n";
    system("git clone $user\@$server:$server_dir/$dir.git $dir");
}

my $dir = '';
if (@ARGV) {
    $dir = shift @ARGV;
}

my $user;
($user, $server) = split /\@/, $server;

$server =~ s/:(.*)$//;
my $server_dir = $1;
$server_dir =~ s/\/$//;

if ($bring) {
    git_bring($user, $server, $server_dir, $dir);
}
else {
    git_send($user, $server, $server_dir, $dir);
}
Juan Reyero Barcelona, 2009-11-07
 

blog comments powered by Disqus