Skip to content

Commit 93abb12

Browse files
authored
Automatically clean up book metadata (#976)
We keep information about which branches contribute to which books but before this change we didn't automatically remove the metadata when a branch is no longer involved in building a book we never cleared that metadata. For the most part this just left lines in a YAML file that aren't used except when we remove a branch from a book and then re-add it. In that case since we only use the branch data to figure out if we should rebuild a book we *wouldn't* start to build the book when it is added back unless the branch that it is built from changes. This happened to us recently so it makes sense to clean up these files automatically so it never happens again. Closes #973
1 parent 5b6c8c3 commit 93abb12

File tree

4 files changed

+121
-37
lines changed

4 files changed

+121
-37
lines changed

build_docs.pl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,8 @@ sub build_all {
220220

221221
say "Updating repositories";
222222
my $target_repo = init_target_repo( $repos_dir, $temp_dir, $reference_dir );
223-
init_repos( $repos_dir, $temp_dir, $reference_dir, $target_repo );
223+
my $tracker = init_repos(
224+
$repos_dir, $temp_dir, $reference_dir, $target_repo );
224225

225226
my $build_dir = $Conf->{paths}{build}
226227
or die "Missing <paths.build> in config";
@@ -259,6 +260,8 @@ sub build_all {
259260
say "Checking links";
260261
check_links($build_dir);
261262
}
263+
$tracker->prune_out_of_date( @$contents );
264+
$tracker->write;
262265
push_changes( $build_dir, $target_repo ) if $Opts->{push};
263266
serve_and_open_browser( $build_dir, $redirects ) if $Opts->{open};
264267

@@ -553,7 +556,7 @@ sub init_repos {
553556
say "Removing old repo <" . $dir->basename . ">";
554557
$dir->rmtree;
555558
}
556-
return $target_repo;
559+
return $tracker;
557560
}
558561

559562

integtest/spec/all_books_change_detection_spec.rb

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,58 @@ def self.build_one_book_then_two_books(
285285
let(:new_text) { 'Some text.' }
286286
include_examples 'second build is not a noop'
287287
end
288+
context 'because we add a branch to the book' do
289+
build_one_book_out_of_one_repo_twice(
290+
before_second_build: lambda do |src, _config|
291+
repo = src.repo 'repo'
292+
repo.switch_to_new_branch 'foo'
293+
book = src.book 'Test'
294+
book.branches.push 'foo'
295+
end
296+
)
297+
let(:latest_revision) { 'init' }
298+
let(:new_text) { 'Some text.' }
299+
context 'the second build' do
300+
let(:out) { outputs[1] }
301+
include_examples 'commits changes'
302+
end
303+
file_context 'html/branches.yaml' do
304+
it 'includes the original branch' do
305+
expect(contents).to include('Test/index.asciidoc/master')
306+
end
307+
it 'includes the added branch' do
308+
expect(contents).to include('Test/index.asciidoc/foo')
309+
end
310+
end
311+
end
312+
context 'because we remove a branch from the book' do
313+
build_one_book_out_of_one_repo_twice(
314+
before_first_build: lambda do |src, _config|
315+
repo = src.repo 'repo'
316+
repo.switch_to_new_branch 'foo'
317+
book = src.book 'Test'
318+
book.branches.push 'foo'
319+
end,
320+
before_second_build: lambda do |src, _config|
321+
book = src.book 'Test'
322+
book.branches.delete 'foo'
323+
end
324+
)
325+
let(:latest_revision) { 'init' }
326+
let(:new_text) { 'Some text.' }
327+
context 'the second build' do
328+
let(:out) { outputs[1] }
329+
include_examples 'commits changes'
330+
end
331+
file_context 'html/branches.yaml' do
332+
it 'includes the built branch' do
333+
expect(contents).to include('Test/index.asciidoc/master')
334+
end
335+
it "doesn't include the removed branch" do
336+
expect(contents).not_to include('Test/index.asciidoc/foo')
337+
end
338+
end
339+
end
288340
end
289341
end
290342

integtest/spec/helper/book.rb

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,17 @@ class Book
1212
# Should this book build with asciidoctor (true) or asciidoc (false).
1313
attr_accessor :asciidoctor
1414

15+
##
16+
# The list of branches to build
17+
attr_accessor :branches
18+
1519
def initialize(title, prefix)
1620
@title = title
1721
@prefix = prefix
1822
@index = 'index.asciidoc'
1923
@asciidoctor = true
2024
@sources = []
25+
@branches = ['master']
2126
end
2227

2328
##
@@ -47,7 +52,7 @@ def conf
4752
title: #{@title}
4853
prefix: #{@prefix}
4954
current: master
50-
branches: [ master ]
55+
branches: [ #{@branches.join ', '} ]
5156
index: #{@index}
5257
tags: test tag
5358
subject: Test
@@ -61,7 +66,9 @@ def conf
6166
# The html for a link to a particular branch of this book.
6267
def link_to(branch)
6368
url = "#{@prefix}/#{branch}/index.html"
64-
%(<a class="ulink" href="#{url}" target="_top">#{@title}</a>)
69+
decoration = ''
70+
decoration = ' [master]' unless @branches.length == 1
71+
%(<a class="ulink" href="#{url}" target="_top">#{@title}#{decoration}</a>)
6572
end
6673

6774
private

lib/ES/BranchTracker.pm

Lines changed: 55 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use strict;
44
use warnings;
55
use v5.10;
66

7-
use Path::Class();
7+
use Path::Class qw(dir);
88
use ES::Util qw(run sha_for);
99
use YAML qw(Dump Load);
1010
use Storable qw(dclone);
@@ -15,27 +15,19 @@ my %Repos;
1515
sub new {
1616
#===================================
1717
my ( $class, $file, @repos ) = @_;
18-
my $old = {};
19-
my $yaml = '';
18+
my %shas;
2019

2120
if ( -e $file ) {
2221
my $yaml = $file->slurp( iomode => '<:utf8' );
23-
$old = Load($yaml);
24-
}
25-
26-
my %new;
27-
for (@repos) {
28-
$new{$_} = $old->{$_} || {};
22+
%shas = %{ Load($yaml) };
2923
}
3024

3125
my $self = bless {
3226
file => $file,
33-
shas => \%new,
34-
yaml => $yaml,
27+
shas => \%shas,
3528
}, $class;
36-
$self->write;
37-
return $self;
3829

30+
return $self;
3931
}
4032

4133
#===================================
@@ -56,39 +48,69 @@ sub sha_for_branch {
5648
sub set_sha_for_branch {
5749
#===================================
5850
my ( $self, $repo, $branch, $sha ) = @_;
51+
5952
$self->shas->{$repo}{$branch} = $sha;
60-
$self->write;
6153
}
6254

6355
#===================================
64-
sub delete_branch {
56+
sub prune_out_of_date {
6557
#===================================
66-
my ( $self, $repo, $branch ) = @_;
67-
my $shas = $self->shas;
68-
delete $shas->{$repo}{$branch} || return;
69-
unless ( keys %{ $shas->{$repo} } ) {
70-
delete $shas->{$repo};
58+
# Prunes tracker entries for books that are no longer built.
59+
#===================================
60+
my ( $self, @entries ) = @_;
61+
my %allowed;
62+
_allowed_entries_from_books( \%allowed, @entries );
63+
64+
while ( my ($repo, $branches) = each %{ $self->{shas} } ) {
65+
my $allowed_for_repo = $allowed{$repo} || '';
66+
unless ($allowed_for_repo) {
67+
delete $self->{shas}->{$repo};
68+
next;
69+
}
70+
foreach my $branch ( keys %{ $branches } ) {
71+
# We can't clear the link check information at this point safely
72+
# because we need it for PR builds and we don't have a good way
73+
# tell if it'll be needed again. It is a problem, but not a big one
74+
# right now.
75+
unless ($allowed_for_repo->{$branch} || $branch =~ /^link-check/) {
76+
delete $branches->{$branch};
77+
}
78+
}
79+
# Empty can show up because there is a new book that were not
80+
# building at this time and we don't want that to force a commit so we
81+
# clean them up while we're purging here.
82+
delete $self->{shas}->{$repo} unless keys %{ $branches };
7183
}
72-
$self->write;
7384
}
7485

7586
#===================================
76-
sub write {
87+
sub _allowed_entries_from_books {
7788
#===================================
78-
my $self = shift;
79-
my $to_save = dclone( $self->shas );
80-
# Empty hashes are caused by new repos that are unused which shouldn't
81-
# force a commit.
82-
while (my ($repo, $branches) = each %{ $to_save } ) {
83-
unless ( keys %{ $branches } ) {
84-
delete $to_save->{$repo};
89+
my ( $allowed, @entries ) = @_;
90+
91+
foreach my $book ( @entries ) {
92+
my $title = $book->{title};
93+
foreach ( @{ $book->{branches} } ) {
94+
my ( $branch, $branch_title ) = ref $_ eq 'HASH' ? (%$_) : ( $_, $_ );
95+
foreach my $source ( @{ $book->{sources} } ) {
96+
my $repo = $source->{repo};
97+
my $path = dir('.')->subdir( $source->{path} )->relative('.');
98+
my $mapped_branch = $source->{map_branches}{$branch} || $branch;
99+
$allowed->{$repo}{"$title/$path/$mapped_branch"} = 1;
100+
}
101+
}
102+
if (exists $book->{sections}) {
103+
_allowed_entries_from_books( $allowed, @{ $book->{sections} } );
85104
}
86105
}
87-
my $new = Dump( $to_save );
88-
return if $new eq $self->{yaml};
106+
}
107+
108+
#===================================
109+
sub write {
110+
#===================================
111+
my $self = shift;
89112
$self->file->parent->mkpath;
90-
$self->file->spew( iomode => '>:utf8', $new );
91-
$self->{yaml} = $new;
113+
$self->file->spew( iomode => '>:utf8', Dump( $self->{shas} ) );
92114
}
93115

94116
#===================================

0 commit comments

Comments
 (0)