public-inbox.git  about / heads / tags
an "archives first" approach to mailing lists
blob 6bd9fb6c4bf11fc1093d64360ccc430853a007c0 1240 bytes (raw)
$ git show HEAD:lib/PublicInbox/MdirSort.pm	# shows this blob on the CLI

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
 
# Copyright (C) all contributors <meta@public-inbox.org>
# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>

# used for sorting MH (and (TODO) Maildir) names
# TODO: consider sort(1) to parallelize sorting of gigantic directories
package PublicInbox::MdirSort;
use v5.12;
use Time::HiRes ();
use parent qw(Exporter);
use Fcntl qw(S_ISREG);
our @EXPORT = qw(mdir_sort);
my %ST = (sequence => 0, size => 1, atime => 2, mtime => 3, ctime => 4);

sub mdir_sort ($$;$) {
	my ($ent, $sort, $max) = @_;
	my @st;
	my @ent = map {
		@st = Time::HiRes::stat $_;
		# name, size, {a,m,c}time
		S_ISREG($st[2]) ? [ $_, @st[7..10] ] : ();
	} @$ent;
	@ent = grep { $_->[1] <= $max } @ent if $max;
	use sort 'stable';
	for my $s (@$sort) {
		if ($s =~ /\A(\-|\+|)name\z/) {
			if ($1 eq '-') {
				@ent = sort { $b->[0] cmp $a->[0] } @ent;
			} else {
				@ent = sort { $a->[0] cmp $b->[0] } @ent;
			}
		} elsif ($s =~ /\A(\-|\+|)
				(sequence|size|ctime|mtime|atime)\z/x) {
			my $key = $ST{$2};
			if ($1 eq '-') {
				@ent = sort { $b->[$key] <=> $a->[$key] } @ent;
			} else {
				@ent = sort { $a->[$key] <=> $b->[$key] } @ent;
			}
		} else {
			die "E: unrecognized sort parameter: `$s'";
		}
	}
	@$ent = map { $_->[0] } @ent;
}

1;

git clone https://public-inbox.org/public-inbox.git
git clone http://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.onion/public-inbox.git