ebfdb31ff35dc0bbcef7a39bbb3b51129f61abc0
[bak-git.git] / server.pl
1 #!/usr/bin/perl
2
3 =head1 bak-git
4
5 Simpliest possible backup from remote host (with natcat as
6 only depenency) to ad-hoc remote server
7
8 Install on client with:
9
10   echo install | nc 10.60.0.92 9001 > bak ; chmod 755 bak
11
12 =cut
13
14 use warnings;
15 use strict;
16 use autodie;
17 use IO::Socket::INET;
18 use File::Path;
19
20 my $dir = shift @ARGV || die "usage: $0 /backup/directory\n";
21
22 chdir $dir;
23 system 'git init' unless -e '.git';
24
25 my $server = IO::Socket::INET->new(
26         Proto     => 'tcp',
27         LocalPort => 9001,
28         Listen    => SOMAXCONN,
29         Reuse     => 1
30 ) || die $!;
31
32 while (my $client = $server->accept()) {
33         my ($pwd,$command,$path,$message) = split(/\s+/,<$client>,4);
34         my $ip = $client->peerhost;
35
36         $message ||= '';
37         $path = "$pwd/$path" unless $path =~ m{^/};
38
39         if ( $command eq 'install' ) {
40                 print $client '#!/bin/sh',$/,'echo `pwd` $* | nc 10.60.0.92 9001',$/;
41                 next;
42         }
43
44         warn "$ip [$command] $path | $message\n";
45
46         if ( ! -d $ip ) {
47                 system 'ssh-copy-id', "root\@$ip";
48         }
49
50
51         my $dir = $path;
52         $dir =~ s{/[^/]+$}{};
53
54         mkpath "$ip/$dir" unless -e "$ip/$dir";
55
56         if ( ! $command ) {
57                 system "find $ip -type f | sed 's,$ip,,' > /tmp/$ip.list";
58                 system "rsync -avv --files-from /tmp/$ip.list root\@$ip:/ $ip/"
59         } elsif ( $command eq 'add' ) {
60                 system 'rsync', '-avv', "root\@$ip:$path", "$ip/$path";
61                 system 'git', 'add', "$ip/$path";
62         } elsif ( $command eq 'commit' ) {
63                 system 'rsync', '-avv', "root\@$ip:$path", "$ip/$path";
64                 $message ||= "$command $ip $path";
65                 system 'git', 'commit', '-m', $message, "$ip/$path";
66         } elsif ( $command =~ m{(diff|status|log)} ) {
67                 print $client `git $command $ip`;
68         } else {
69                 print $client "Unknown command: $command\n";
70         }
71
72 }
73