From ba8d9e23a8d284675b4613204d686a9c76dc5189 Mon Sep 17 00:00:00 2001 From: "Kyle J. McKay" Date: Wed, 18 Aug 2021 11:26:28 -0700 Subject: [PATCH] Project.pm: tighten up is_empty check The "kludge" to accomodate $Girocco::Config::empty_commit_message can leave non-empty projects undetectable. Refuse to consider them "empty" if they have more than two loose objects (create-initial-empty-commit makes exactly two loose objects). While still not perfect, the check for the new conditions remains relatively fast (no external processes needed) and will correctly return a false "is_empty" status now for "empty" projects that have been modified outside Girocco. Signed-off-by: Kyle J. McKay fixup! Project.pm: tighten up is_empty check --- Girocco/Project.pm | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/Girocco/Project.pm b/Girocco/Project.pm index dbad925..925a6ad 100644 --- a/Girocco/Project.pm +++ b/Girocco/Project.pm @@ -1531,7 +1531,8 @@ sub is_empty { # As a "kludge" to accomodate the $Girocco::Config::empty_commit_message # setting, if the packed-refs file does not exist or contains no # refs, and the .delaygc file exists and the .allowgc file does not - # then the project will be considered empty unless it's a mirror. + # then the project will be considered empty unless it's a mirror + # or it contains more than two loose objects. # But if a true value is passed as the first argument, disable this kludge. my $self = shift; @@ -1551,15 +1552,41 @@ sub is_empty { return 0 if $foundref; } (-d $self->{path}.'/refs') or return 1; + _contains_files($self->{path}.'/refs') or return 1; # Begin kludge to accomodate $empty_commit_message setting if (!$nokludge && !$self->{mirror} && -e $self->{path}.'/.delaygc' && ! -e $self->{path}.'/.allowgc') { # Sure looks like an empty push project # The non-kludge is to make sure there's only exactly one ref, HEAD is a # symbolic-ref to that ref and the commit has no parents and an empty tree # while still requiring the !mirror, .delaygc && !.allowgc conditions too. - return 1; + # In the meanwhile, if it has more than two loose objects + # (that's how many create-initial-empty-commit makes), + # consider it to be non-empty. + return _looks_like_empty_project($self->{path}); + } + return 0; # has at least one ref (and the kludge did not activate) +} + +sub _looks_like_empty_project +{ + my $pd = shift; + -d $pd or return 1; + my $objcnt = 0; + if (opendir my $odh, "$pd/objects") { + while (defined(my $os = readdir($odh))) { + $os =~ /^[0-9a-f]{2}$/ or next; + if (opendir my $sdh, "$pd/objects/$os") { + while (defined(my $of = readdir($sdh))) { + $of =~ /^[0-9a-f]{38,}$/ or next; + last if ++$objcnt > 2; + } + closedir $sdh; + } + last if $objcnt > 2; + } + closedir $odh; } - return !_contains_files($self->{path}.'/refs'); + return $objcnt <= 2; } # returns array: -- 2.11.4.GIT