@@ -57,6 +57,50 @@ def nobreak_span(text):
5757 return f'<span class="prefer-nobreak">{ text } </span>'
5858
5959
60+ def get_recent_changes (contributors , * args ):
61+ """
62+ Returns a markdown list of the most recent RECENT_CHANGES_COUNT commits.
63+ """
64+ recent_changes_output = subprocess .run ([
65+ 'git' , 'log' ,
66+ # Show only last RECENT_CHANGES_COUNT commits
67+ '-n' , str (RECENT_CHANGES_COUNT ),
68+ # Get hash, date, message, author and coauthors, separated by tabs
69+ # NB When there are no trailers, the line ends with a tab
70+ # NB Coauthors usually have the format "name <email>" and there is
71+ # no way to tell git to strip the email, so it needs to be done
72+ # in post processing
73+ '--format=%H%x09%as%x09%s%x09%an%x09%(trailers:key=co-authored-by,valueonly=true,separator=%x09)' ,
74+ 'HEAD' ,
75+ * args
76+ ], capture_output = True , text = True , check = True ).stdout .splitlines ()
77+
78+ skipped_authors = set ()
79+ recent_changes = '## Recent changes\n '
80+
81+ for line in recent_changes_output :
82+ [sha , date , message , * raw_authors ] = line .split ('\t ' )
83+ author_indices = []
84+ for raw_author in map (cleanup_author_part , raw_authors ):
85+ if raw_author == '' :
86+ continue
87+ author_index = get_real_author_index (raw_author , contributors )
88+ if author_index is None :
89+ skipped_authors .add (raw_author )
90+ continue
91+ author_indices .append (author_index )
92+
93+ if not author_indices :
94+ continue
95+
96+ formatted_authors = format_multiple_authors_attribution ([
97+ contributors [idx ]['displayName' ] for idx in author_indices
98+ ])
99+ recent_changes += f'- { date } . { formatted_authors } . <i><a target="_blank" href={ github_page_for_commit (sha )} >{ message } .</a></i>\n '
100+
101+ return (recent_changes , skipped_authors )
102+
103+
60104def get_author_element_for_file (filename , include_contributors , contributors , contributors_file ):
61105 """
62106 Extracts git usernames of contributors to a particular file
@@ -104,37 +148,9 @@ def get_author_element_for_file(filename, include_contributors, contributors, co
104148 created_date = file_log_output [- 1 ]
105149 modified_date = file_log_output [0 ]
106150
107- recent_changes_output = subprocess .run ([
108- 'git' , 'log' ,
109- # Show only last RECENT_CHANGES_COUNT commits
110- '-n' , str (RECENT_CHANGES_COUNT ),
111- # Get hash, date, message, author and coauthors, separated by tabs
112- # NB When there are no trailers, the line ends with a tab
113- # NB Coauthors usually have the format "name <email>" and there is
114- # no way to tell git to strip the email, so it needs to be done
115- # in post processing
116- '--format=%H%x09%as%x09%s%x09%an%x09%(trailers:key=co-authored-by,valueonly=true,separator=%x09)' ,
117- 'HEAD' , '--' , filename
118- ], capture_output = True , text = True , check = True ).stdout .splitlines ()
119- recent_changes = '## Recent changes\n '
120- for recent_changes_line in recent_changes_output :
121- [sha , date , message , * raw_authors ] = recent_changes_line .split ('\t ' )
122- author_indices = []
123- for raw_author in map (cleanup_author_part , raw_authors ):
124- # Line ended with a tab
125- if raw_author == '' :
126- continue
127- author_index = get_real_author_index (raw_author , contributors )
128- if author_index is None :
129- skipped_authors .add (raw_author )
130- continue
131- author_indices .append (author_index )
132- if len (author_indices ) == 0 :
133- continue
134- formatted_authors = format_multiple_authors_attribution ([
135- contributors [author_index ]['displayName' ] for author_index in author_indices
136- ])
137- recent_changes += f'- { date } . { formatted_authors } . <i><a target="_blank" href={ github_page_for_commit (sha )} >{ message } .</a></i>\n '
151+ recent_changes , recent_skipped_authors = get_recent_changes (
152+ contributors , '--' , filename )
153+ skipped_authors .update (recent_skipped_authors )
138154
139155 if skipped_authors :
140156 print_skipping_contributors_warning (skipped_authors , contributors_file )
@@ -164,6 +180,20 @@ def add_author_info_to_chapter_rec_mut(roots, chapter, contributors, config):
164180 source_file_name = potential_source_file_name
165181
166182 if source_file_name in config ['suppress_processing' ]:
183+ # Suppress processing for this page
184+ return
185+
186+ if source_file_name in config ['sitewide_changes' ]:
187+ # Insert recent sitewide changes on page
188+ footer_recent_sitewide , skipped_authors = get_recent_changes (
189+ contributors , '--invert-grep' , '--grep=^chore:' )
190+
191+ if skipped_authors :
192+ print_skipping_contributors_warning (
193+ skipped_authors , config ['contributors_file' ])
194+
195+ # Append to end of file
196+ chapter ['content' ] += '\n ' + footer_recent_sitewide
167197 return
168198
169199 header_info_element , footer_info_element = get_author_element_for_file (
@@ -172,6 +202,7 @@ def add_author_info_to_chapter_rec_mut(roots, chapter, contributors, config):
172202 for ext in config ['attribute_file_extensions' ])),
173203 contributors ,
174204 config ['contributors_file' ])
205+
175206 # Assumption: The title is the first header in the file
176207 chapter_heading_start = chapter ['content' ].index ('# ' )
177208 chapter_heading_end = chapter ['content' ].index ('\n ' , chapter_heading_start )
@@ -225,6 +256,8 @@ def add_author_info_to_root_section(roots, section, contributors, config):
225256 'attribute_file_extensions' , [])
226257 metadata_config ['suppress_processing' ] = metadata_config .get (
227258 'suppress_processing' , [])
259+ metadata_config ['sitewide_changes' ] = metadata_config .get (
260+ 'sitewide_changes' , [])
228261 metadata_config ['contributors_file' ] = metadata_config .get (
229262 'contributors_file' , 'CONTRIBUTORS.toml' )
230263
0 commit comments