#!/usr/bin/perl
#hash-backup.pl 
#Copyright (C) 2007 Ilya V. Schurov, based on original idea by Yurii G. Kudryashov

#This program is free software: you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation, either version 3 of the License, or
#(at your option) any later version.

#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.

#You should have received a copy of the GNU General Public License
#along with this program.  If not, see <http://www.gnu.org/licenses/>.

$SCRIPT="hash-backup.pl";

use Digest::SHA;
use Getopt::Compact;
use File::Find;
use File::Copy;
use File::Basename;
use File::Path;
use Cwd 'abs_path';

# hash-backup.pl [OPTIONS] <working_folder> <storage> <backup-tree>
$opt=new Getopt::Compact('args'=>"<working_folder> <storage> <backup-tree>",'cmd'=>$SCRIPT,
	'struct'=>
	[ 
		[
			[qw(a alg)], 
			qq(Specify hash algorithm (SHA-1 by default)), 
		"=s"]
		],
		'modes'=>[qw(debug)]
	);

if($#ARGV<2)
{
	print $opt->usage();
	exit(1);
}
$working_folder=$ARGV[0];
$storage=$ARGV[1];
$backup_tree_dir=$ARGV[2];
$alg=$opt->opts()->{'alg'} || 'sha1';
$DEBUG=$opt->opts()->{'debug'};
$digest=new Digest::SHA($alg);

#FIXME fail test

debug_msg("Using $alg algorithm\n");

find({'wanted'=>\&process_dir,'no_chdir'=>1},$working_folder,);

sub process_dir
{
	my $file=$_;
	my $fullfilename=$File::Find::name;
	my $dir=$File::Find::dir;
	my $hash;
	my $dirname;
	my $relname;

	$relname=$fullfilename;
	$relname=~s/^$working_folder(\/?)//;
	$dirname=dirname($relname);	
	if(-f){
		debug_msg("file: $file, fullfilename: $fullfilename, dir: $dir, relname: $relname, dirname: $dirname\n");
		$digest->addfile($file);
		$hash=$digest->hexdigest();
		debug_msg("file $file hashed with result: $hash\n");
		if(! -e "$storage/$hash.file")
		{
			copy($file,"$storage/$hash.file");
		}
		mkpath("$backup_tree_dir/$dirname"); #FIXME: rights
		print "!$backup_tree_dir/$relname\n";
		if(-l "$backup_tree_dir/$relname")
		{
				unlink("$backup_tree_dir/$relname");
				debug_msg("$backup_tree_dir/$relname unlinked\n");
		}

		symlink(abs_path("$storage/$hash.file"),"$backup_tree_dir/$relname") || die("Can't symlink $storage/$hash.file to $backup_tree_dir/$relname: $!");
		debug_msg("$file processed\n");
	}
}

sub debug_msg
{
	print @_ if $DEBUG;
}
