commit a964a391d65fce7963a55c9964bbbe6a5520a2ff
parent 3d69b3355b084a09aaa2a64a4b7d47e9296d4b01
Author: lumidify <nobody@lumidify.org>
Date: Mon, 23 Mar 2020 15:33:23 +0100
Fixes; allow to check only individual files
Diffstat:
M | lumia.pl | | | 143 | +++++++++++++++++++++++++++++++++++++++++++------------------------------------ |
1 file changed, 78 insertions(+), 65 deletions(-)
diff --git a/lumia.pl b/lumia.pl
@@ -1,25 +1,16 @@
#!/usr/bin/env perl
-# FIXME: add ckold to check what files don't exist anymore and remove them from cksums
-# FIXME: write cksums as we go along during check_add_new, not just at end
# FIXME: some way to avoid writing .lumidify* in dirs but still index them? e.g. Code/CMSG
# FIXME: cksum don't create malformed line if permission denied
-# FIXME: dirs in ignore still created when extracting
# FIXME: make generic function to traverse dirs and call other function on each dir
-# FIXME: extract - actually copy files, don't write again and regen cksums.cksum
-# FIXME: check cksums.cksum when reading files
-# FIXME: check if .lumidify* are writable first so cksums aren't generated uselessly
# FIXME: handle rm, etc. on .lumidify* files
-# FIXME: handle files with newline?
# FIXME: ignore all except for a certain file/folder
-# FIXME: store modified date and recksum filed with changed date
+# FIXME: store modified date and checksum filed with changed date
# FIXME: sha256 works with leading zeroes, maybe switch?
# FIXME: allow different hash types
# FIXME: don't write anything if cksum fails (will create malformed line)
# FIXME: add option to just check dir structure or maybe check if everything exists
-# WARNING: convert regenerates cksums.cksum
# FIXME: add option to compare cksums of two dirs
-# FIXME: add option to check only individual files
use strict;
use warnings;
@@ -34,12 +25,21 @@ use Data::Dumper;
use Scalar::Util qw(looks_like_number);
use Getopt::Long;
+# the file used to store checksums for files
+my $CKSUM_FILE = ".lumidify_archive_cksums";
+# the file used to store directory names
+my $DIR_FILE = ".lumidify_archive_dirs";
+# the file read to ignore files or directories
+my $IGNORE_FILE = ".lumidify_archive_ignore";
+# the file containing checksums of $CKSUM_FILE and $DIR_FILE
+my $DOUBLE_CKSUM_FILE = ".lumidify_archive_cksums.cksum";
+
my $CKSUM_CMD = 'cksum -q';
my %SPECIAL_FILES = (
- ".lumidify_archive_cksums" => 1,
- ".lumidify_archive_cksums.cksum" => 1,
- ".lumidify_archive_ignore" => 1,
- ".lumidify_archive_dirs" => 1
+ $CKSUM_FILE => 1,
+ $DIR_FILE => 1,
+ $IGNORE_FILE => 1,
+ $DOUBLE_CKSUM_FILE => 1
);
# escape a filename for writing into the checksum files
@@ -86,18 +86,14 @@ sub make_file_iter_basic {
}, @files;
}
-# make a basic directory iterator, which only returns all directories
-sub make_dir_iter {
- make_file_iter_basic sub {-d $_[0]}, @_;
-}
-
# make an interator that only returns the directories which are present
-# in the .lumidify_archive_dirs files
+# in the $DIR_FILE files, in addition to the files and directories that
+# were originally passed as arguments
# note: this returns nonexistent directories if those are still
# specified in the lumia files
sub make_lumia_iter {
make_file_iter sub {1}, sub {
- my $path = "$_[0]/.lumidify_archive_dirs";
+ my $path = "$_[0]/$DIR_FILE";
return [] if !-f $path;
my $dirs = read_file($path, {});
return if !defined $dirs;
@@ -117,10 +113,7 @@ sub make_lumia_iter {
# remove all special lumia files from the given directory
sub clean_files {
my $dir = shift;
- my $match_lumia_files = sub {
- exists $SPECIAL_FILES{basename $_[0]};
- };
- my $iter = make_file_iter $match_lumia_files, $dir;
+ my $iter = make_file_iter_basic sub {exists $SPECIAL_FILES{basename $_[0]};}, $dir;
while (my $file = $iter->()) {
if (!unlink $file) {
warn "WARNING: Unable to remove file \"$file\"!";
@@ -202,9 +195,9 @@ sub read_cksum_file {
# read the checksums and directory names in $dir
sub read_cksums {
my $dir = shift;
- my $cksums = read_cksum_file("$dir/.lumidify_archive_cksums", {});
+ my $cksums = read_cksum_file("$dir/$CKSUM_FILE", {});
return undef if !defined $cksums;
- $cksums = read_file("$dir/.lumidify_archive_dirs", $cksums);
+ $cksums = read_file("$dir/$DIR_FILE", $cksums);
return undef if !defined $cksums;
return $cksums;
}
@@ -246,19 +239,40 @@ sub check_cksums {
# check the checksums of all files in $top_dir
sub check_files {
- my $top_dir = shift;
- my $iter = make_lumia_iter $top_dir;
- while (my $dir = $iter->()) {
- check_cksums $dir, ".lumidify_archive_cksums.cksum";
- check_cksums $dir, ".lumidify_archive_cksums";
+ my $iter = make_lumia_iter @_;
+ while (my $file = $iter->()) {
+ if (-d $file) {
+ check_cksums $file, "$DOUBLE_CKSUM_FILE";
+ check_cksums $file, "$CKSUM_FILE";
+ } else {
+ my $dir = dirname $file;
+ my $base = basename $file;
+ if (exists $SPECIAL_FILES{$base}) {
+ warn "ERROR: File is reserved for lumia.pl: $file\n";
+ next;
+ }
+ my $cksums = read_cksum_file("$dir/$CKSUM_FILE");
+ next if !defined $cksums;
+ if (!exists $cksums->{$base}) {
+ warn "ERROR: File doesn't exist in checksums: $file\n";
+ next;
+ }
+ my $output = get_cksum "$file";
+ next if !defined $output;
+ if ($output eq $cksums->{$base}) {
+ print "OK $file\n";
+ } else {
+ print "FAILED $file\n";
+ }
+ }
}
}
# write the checksums of the special lumia files given as arguments
-# to ".lumidify_archive_cksums.cksum" in $dir
+# to "$DOUBLE_CKSUM_FILE" in $dir
sub write_special_cksums {
my ($dir, @files) = @_;
- my $cksum_file = "$dir/.lumidify_archive_cksums.cksum";
+ my $cksum_file = "$dir/$DOUBLE_CKSUM_FILE";
my $cksums = {};
if (-f $cksum_file) {
$cksums = read_cksum_file $cksum_file, {};
@@ -276,7 +290,7 @@ sub write_special_cksums {
# - if $file_func is set, it is called for each new file
# - if $before_dir_func is set, it is called before processing the
# files in each directory that has new files OR if a directory
-# is entirely new (well, it only checks if ".lumidify_archive_cksums.cksum" exists)
+# is entirely new (well, it only checks if "$DOUBLE_CKSUM_FILE" exists)
# - if $after_dir_func is set, it is called after processing the
# files in each directory that has new files
sub check_new_files {
@@ -294,9 +308,9 @@ sub check_new_files {
}
return {};
};
- my $ignore = $read_file_noerror->("$dir/.lumidify_archive_ignore", \&read_file);
- my $lumia_dirs = $read_file_noerror->("$dir/.lumidify_archive_dirs", \&read_file);
- my $lumia_files = $read_file_noerror->("$dir/.lumidify_archive_cksums", \&read_cksum_file);
+ my $ignore = $read_file_noerror->("$dir/$IGNORE_FILE", \&read_file);
+ my $lumia_dirs = $read_file_noerror->("$dir/$DIR_FILE", \&read_file);
+ my $lumia_files = $read_file_noerror->("$dir/$CKSUM_FILE", \&read_cksum_file);
my @dirs;
my $found = 0;
while (my $file = readdir $dh) {
@@ -317,7 +331,7 @@ sub check_new_files {
}
closedir $dh;
# also call $before_dir_func if the directory has not been initialized yet
- if (!$found && !-f "$dir/.lumidify_archive_cksums.cksum" && defined $before_dir_func) {
+ if (!$found && !-f "$dir/$DOUBLE_CKSUM_FILE" && defined $before_dir_func) {
$before_dir_func->($dir);
}
if ($found && defined $after_dir_func) {
@@ -338,7 +352,7 @@ sub check_add_new_files {
my ($dir, $file) = @_;
my $fullpath = "$dir/$file";
if (-d $fullpath) {
- my $dir_file = "$dir/.lumidify_archive_dirs";
+ my $dir_file = "$dir/$DIR_FILE";
my $fh;
if (!open $fh, ">>", $dir_file) {
warn "ERROR: Unable to append to file \"$dir_file\"!";
@@ -350,7 +364,7 @@ sub check_add_new_files {
} else {
my $cksum_output = get_cksum $fullpath;
return if !defined $cksum_output;
- my $cksum_file = "$dir/.lumidify_archive_cksums";
+ my $cksum_file = "$dir/$CKSUM_FILE";
my $fh;
if (!open $fh, ">>", $cksum_file) {
warn "ERROR: Unable to append to file \"$cksum_file\"!";
@@ -362,8 +376,8 @@ sub check_add_new_files {
}
print "Added \"$fullpath\"\n";
}, sub {
- if (-f "$_[0]/.lumidify_archive_cksums.cksum") {
- if (!check_cksums $_[0], ".lumidify_archive_cksums.cksum", 1) {
+ if (-f "$_[0]/$DOUBLE_CKSUM_FILE") {
+ if (!check_cksums $_[0], "$DOUBLE_CKSUM_FILE", 1) {
warn "Checksum files corrupt in \"$_[0]\", not adding new checksums!\n";
return 0;
}
@@ -373,11 +387,11 @@ sub check_add_new_files {
return 1;
}, sub {
if ($changed_dirs) {
- write_special_cksums $_[0], ".lumidify_archive_dirs";
+ write_special_cksums $_[0], "$DIR_FILE";
$changed_dirs = 0;
}
if ($changed_files) {
- write_special_cksums $_[0], ".lumidify_archive_cksums";
+ write_special_cksums $_[0], "$CKSUM_FILE";
$changed_files = 0;
}
};
@@ -417,13 +431,13 @@ sub write_cksums {
# No, this isn't efficient...
if ($files_modified) {
my %file_cksums = map {$_ => $contents->{$_}} grep({defined $contents->{$_}} keys %$contents);
- write_cksum_file("$dir/.lumidify_archive_cksums", \%file_cksums);
- write_special_cksums $dir, ".lumidify_archive_cksums";
+ write_cksum_file("$dir/$CKSUM_FILE", \%file_cksums);
+ write_special_cksums $dir, "$CKSUM_FILE";
}
if ($dirs_modified) {
my %dir_cksums = map {$_ => undef} grep({!defined $contents->{$_}} keys %$contents);
- write_file "$dir/.lumidify_archive_dirs", \%dir_cksums;
- write_special_cksums $dir, ".lumidify_archive_dirs";
+ write_file "$dir/$DIR_FILE", \%dir_cksums;
+ write_special_cksums $dir, "$DIR_FILE";
}
}
@@ -434,7 +448,7 @@ sub check_old_files {
while (my $dir = $iter->()) {
# if $dir doesn't exist, the iterator already issued a warning
if (-e $dir) {
- my $cksums = read_cksum_file("$dir/.lumidify_archive_cksums", {}) // {};
+ my $cksums = read_cksum_file("$dir/$CKSUM_FILE", {}) // {};
foreach my $file (keys %$cksums) {
if (!-e "$dir/$file") {
warn "Nonexistent file: \"$dir/$file\"!\n";
@@ -453,26 +467,26 @@ sub remove_old_files {
if (!-e $dir) {
my $parent = dirname $dir;
my $child = basename $dir;
- my $lumia_dirs = read_file("$parent/.lumidify_archive_dirs", {}) // {};
+ my $lumia_dirs = read_file("$parent/$DIR_FILE", {}) // {};
if (exists $lumia_dirs->{$child}) {
delete $lumia_dirs->{$child};
- write_file "$parent/.lumidify_archive_dirs", $lumia_dirs;
- print "Removed \"$dir\" from \"$parent/.lumidify_archive_dirs\"\n";
- write_special_cksums $parent, ".lumidify_archive_dirs";
+ write_file "$parent/$DIR_FILE", $lumia_dirs;
+ print "Removed \"$dir\" from \"$parent/$DIR_FILE\"\n";
+ write_special_cksums $parent, "$DIR_FILE";
}
} else {
- my $cksums = read_cksum_file("$dir/.lumidify_archive_cksums", {}) // {};
+ my $cksums = read_cksum_file("$dir/$CKSUM_FILE", {}) // {};
my $found = 0;
foreach my $file (keys %$cksums) {
if (!-e "$dir/$file") {
delete $cksums->{$file};
- print "Removed \"$dir/$file\" from \"$dir/.lumidify_archive_cksums\"\n";
+ print "Removed \"$dir/$file\" from \"$dir/$CKSUM_FILE\"\n";
$found = 1;
}
}
if ($found) {
- write_cksum_file "$dir/.lumidify_archive_cksums", $cksums;
- write_special_cksums $dir, ".lumidify_archive_cksums";
+ write_cksum_file "$dir/$CKSUM_FILE", $cksums;
+ write_special_cksums $dir, "$CKSUM_FILE";
}
}
}
@@ -775,13 +789,13 @@ sub make_dirs {
push(@{$dirs{$parent}}, basename($dir));
}
foreach my $parent (keys %dirs) {
- my $parent_dirs = read_file "$parent/.lumidify_archive_dirs", {};
+ my $parent_dirs = read_file "$parent/$DIR_FILE", {};
next if !defined $parent_dirs;
foreach my $dir (@{$dirs{$parent}}) {
$parent_dirs->{$dir} = "";
}
- write_file "$parent/.lumidify_archive_dirs", $parent_dirs;
- write_special_cksums $parent, ".lumidify_archive_dirs";
+ write_file "$parent/$DIR_FILE", $parent_dirs;
+ write_special_cksums $parent, "$DIR_FILE";
}
}
@@ -842,11 +856,10 @@ if ($ARGV[0] eq "mv") {
}
remove_old_files $dir;
} elsif ($ARGV[0] eq "check") {
- my $dir = ".";
- if ($#ARGV > 0) {
- $dir = $ARGV[1];
+ if ($#ARGV < 1) {
+ die "At least one path required";
}
- check_files $dir;
+ check_files @ARGV[1..$#ARGV];
} elsif ($ARGV[0] eq "clean") {
my $dir = ".";
if ($#ARGV > 0) {