@@ -5,6 +5,33 @@ use std::path::{Path, PathBuf};
5
5
6
6
mod cargo_metadata;
7
7
8
+ static TOP_BOILERPLATE : & ' static str = r##"
9
+ <!DOCTYPE html>
10
+ <html>
11
+ <head>
12
+ <meta charset="UTF-8">
13
+ <title>Copyright notices for The Rust Toolchain</title>
14
+ </head>
15
+ <body>
16
+
17
+ <h1>Copyright notices for The Rust Toolchain</h1>
18
+
19
+ <p>This file describes the copyright and licensing information for the source
20
+ code within The Rust Project git tree, and the third-party dependencies used
21
+ when building the Rust toolchain (including the Rust Standard Library).</p>
22
+
23
+ <h2>Table of Contents</h2>
24
+ <ul>
25
+ <li><a href="#in-tree-files">In-tree files</a></li>
26
+ <li><a href="#out-of-tree-dependencies">Out-of-tree dependencies</a></li>
27
+ </ul>
28
+ "## ;
29
+
30
+ static BOTTOM_BOILERPLATE : & ' static str = r#"
31
+ </body>
32
+ </html>
33
+ "# ;
34
+
8
35
/// The entry point to the binary.
9
36
///
10
37
/// You should probably let `bootstrap` execute this program instead of running it directly.
@@ -32,40 +59,22 @@ fn main() -> Result<(), Error> {
32
59
33
60
let mut buffer = Vec :: new ( ) ;
34
61
35
- writeln ! ( buffer, "# COPYRIGHT for Rust" ) ?;
36
- writeln ! ( buffer) ?;
37
- writeln ! (
38
- buffer,
39
- "This file describes the copyright and licensing information for the source code within The Rust Project git tree, and the third-party dependencies used when building the Rust toolchain (including the Rust Standard Library)"
40
- ) ?;
41
- writeln ! ( buffer) ?;
42
- writeln ! ( buffer, "## Table of Contents" ) ?;
43
- writeln ! ( buffer) ?;
44
- writeln ! ( buffer, "* [In-tree files](#in-tree-files)" ) ?;
45
- writeln ! ( buffer, "* [Out-of-tree files](#out-of-tree-files)" ) ?;
46
- // writeln!(buffer, "* [License Texts](#license-texts)")?;
47
- writeln ! ( buffer) ?;
48
-
49
- writeln ! ( buffer, "## In-tree files" ) ?;
50
- writeln ! ( buffer) ?;
62
+ writeln ! ( buffer, "{}" , TOP_BOILERPLATE ) ?;
63
+
51
64
writeln ! (
52
65
buffer,
53
- " The following licenses cover the in-tree source files that were used in this release:"
66
+ r#"<h2 id="in-tree-files">In-tree files</h2><p> The following licenses cover the in-tree source files that were used in this release:</p>"#
54
67
) ?;
55
- writeln ! ( buffer) ?;
56
68
render_tree_recursive ( & collected_tree_metadata. files , & mut buffer, 0 , & mut license_set) ?;
57
69
58
- writeln ! ( buffer) ?;
59
-
60
- writeln ! ( buffer, "## Out-of-tree files" ) ?;
61
- writeln ! ( buffer) ?;
62
70
writeln ! (
63
71
buffer,
64
- " The following licenses cover the out-of-tree crates that were used in this release:"
72
+ r#"<h2 id="out-of-tree-dependencies">Out-of-tree dependencies</h2><p> The following licenses cover the out-of-tree crates that were used in this release:</p>"#
65
73
) ?;
66
- writeln ! ( buffer) ?;
67
74
render_deps ( collected_cargo_metadata. iter ( ) , & mut buffer, & mut license_set) ?;
68
75
76
+ writeln ! ( buffer, "{}" , BOTTOM_BOILERPLATE ) ?;
77
+
69
78
std:: fs:: write ( & dest_file, & buffer) ?;
70
79
71
80
Ok ( ( ) )
@@ -79,43 +88,27 @@ fn render_tree_recursive(
79
88
depth : usize ,
80
89
license_set : & mut BTreeSet < String > ,
81
90
) -> Result < ( ) , Error > {
82
- let prefix = std:: iter:: repeat ( "> " ) . take ( depth + 1 ) . collect :: < String > ( ) ;
83
-
91
+ writeln ! ( buffer, r#"<div style="border:1px solid black; padding: 5px;">"# ) ?;
84
92
match node {
85
93
Node :: Root { children } => {
86
94
for child in children {
87
95
render_tree_recursive ( child, buffer, depth, license_set) ?;
88
96
}
89
97
}
90
98
Node :: Directory { name, children, license } => {
91
- render_tree_license (
92
- & prefix,
93
- std:: iter:: once ( name) ,
94
- license. iter ( ) ,
95
- buffer,
96
- license_set,
97
- ) ?;
99
+ render_tree_license ( std:: iter:: once ( name) , license. iter ( ) , buffer, license_set) ?;
98
100
if !children. is_empty ( ) {
99
- writeln ! ( buffer, "{prefix}" ) ?;
100
- writeln ! ( buffer, "{prefix}*Exceptions:*" ) ?;
101
+ writeln ! ( buffer, "<p><b>Exceptions:</b></p>" ) ?;
101
102
for child in children {
102
- writeln ! ( buffer, "{prefix}" ) ?;
103
103
render_tree_recursive ( child, buffer, depth + 1 , license_set) ?;
104
104
}
105
105
}
106
106
}
107
107
Node :: CondensedDirectory { name, licenses } => {
108
- render_tree_license (
109
- & prefix,
110
- std:: iter:: once ( name) ,
111
- licenses. iter ( ) ,
112
- buffer,
113
- license_set,
114
- ) ?;
108
+ render_tree_license ( std:: iter:: once ( name) , licenses. iter ( ) , buffer, license_set) ?;
115
109
}
116
110
Node :: Group { files, directories, license } => {
117
111
render_tree_license (
118
- & prefix,
119
112
directories. iter ( ) . chain ( files. iter ( ) ) ,
120
113
std:: iter:: once ( license) ,
121
114
buffer,
@@ -124,26 +117,26 @@ fn render_tree_recursive(
124
117
}
125
118
Node :: File { name, license } => {
126
119
render_tree_license (
127
- & prefix,
128
120
std:: iter:: once ( name) ,
129
121
std:: iter:: once ( license) ,
130
122
buffer,
131
123
license_set,
132
124
) ?;
133
125
}
134
126
}
127
+ writeln ! ( buffer, "</div>" ) ?;
135
128
136
129
Ok ( ( ) )
137
130
}
138
131
139
132
/// Draw a series of sibling files/folders, as markdown, into the given Vec.
140
133
fn render_tree_license < ' a > (
141
- prefix : & str ,
142
134
names : impl Iterator < Item = & ' a String > ,
143
135
licenses : impl Iterator < Item = & ' a License > ,
144
136
buffer : & mut Vec < u8 > ,
145
137
license_set : & mut BTreeSet < String > ,
146
138
) -> Result < ( ) , Error > {
139
+ // de-duplicate and sort SPDX and Copyright strings
147
140
let mut spdxs = BTreeSet :: new ( ) ;
148
141
let mut copyrights = BTreeSet :: new ( ) ;
149
142
for license in licenses {
@@ -154,15 +147,21 @@ fn render_tree_license<'a>(
154
147
}
155
148
}
156
149
150
+ writeln ! ( buffer, "<p><b>File/Directory:</b> " ) ?;
157
151
for name in names {
158
- writeln ! ( buffer, "{prefix}**`{ name}`** " ) ?;
152
+ writeln ! ( buffer, "<code>{ name}</code> " ) ?;
159
153
}
160
- for spdx in spdxs. iter ( ) {
161
- writeln ! ( buffer, "{prefix}License: `{spdx}` " ) ?;
154
+ writeln ! ( buffer, "</p>" ) ?;
155
+
156
+ writeln ! ( buffer, "<p><b>License:</b> " ) ?;
157
+ for ( i, spdx) in spdxs. iter ( ) . enumerate ( ) {
158
+ let suffix = if i == spdxs. len ( ) - 1 { "" } else { ", " } ;
159
+ writeln ! ( buffer, "{spdx}{suffix}" ) ?;
162
160
}
163
- for ( i, copyright) in copyrights. iter ( ) . enumerate ( ) {
164
- let suffix = if i == copyrights. len ( ) - 1 { "" } else { " " } ;
165
- writeln ! ( buffer, "{prefix}Copyright: {copyright}{suffix}" ) ?;
161
+ writeln ! ( buffer, "</p>" ) ?;
162
+
163
+ for copyright in copyrights. iter ( ) {
164
+ writeln ! ( buffer, "<p><b>Copyright:</b> {copyright}</p>" ) ?;
166
165
}
167
166
168
167
Ok ( ( ) )
@@ -175,30 +174,25 @@ fn render_deps<'a, 'b>(
175
174
license_set : & mut BTreeSet < String > ,
176
175
) -> Result < ( ) , Error > {
177
176
for dep in deps {
178
- let authors_list = dep. authors . join ( ", " ) . replace ( "<" , " \\ <" ) . replace ( ">" , " \\ >" ) ;
177
+ let authors_list = dep. authors . join ( ", " ) ;
179
178
let url = format ! ( "https://crates.io/crates/{}/{}" , dep. name, dep. version) ;
180
179
writeln ! ( buffer) ?;
181
180
writeln ! (
182
181
buffer,
183
- "### [{ name} {version}]({url})" ,
182
+ r#"<h3><a href="{url}">{ name} {version}</a></h3>"# ,
184
183
name = dep. name,
185
184
version = dep. version,
186
185
url = url,
187
186
) ?;
188
- writeln ! ( buffer) ?;
189
- writeln ! ( buffer, "* Authors: {}" , authors_list) ?;
190
- writeln ! ( buffer, "* License: {}" , dep. license) ?;
187
+ writeln ! ( buffer, "<h4>Authors</h4><p>{}</p>" , escape_html( & authors_list) ) ?;
188
+ writeln ! ( buffer, "<h4>License</h4><p>{}</p>" , escape_html( & dep. license) ) ?;
191
189
license_set. insert ( dep. license . clone ( ) ) ;
192
190
for ( name, contents) in & dep. notices {
193
191
writeln ! ( buffer) ?;
194
- writeln ! ( buffer, "#### {} " , name. to_string_lossy( ) ) ?;
192
+ writeln ! ( buffer, "<h4>{}</h3> " , name. to_string_lossy( ) ) ?;
195
193
writeln ! ( buffer) ?;
196
194
writeln ! ( buffer, "<details><summary>Click to expand</summary>" ) ?;
197
- writeln ! ( buffer) ?;
198
- writeln ! ( buffer, "```" ) ?;
199
- writeln ! ( buffer, "{}" , contents) ?;
200
- writeln ! ( buffer, "```" ) ?;
201
- writeln ! ( buffer) ?;
195
+ writeln ! ( buffer, "<pre>\n {}\n </pre>" , contents) ?;
202
196
writeln ! ( buffer, "</details>" ) ?;
203
197
}
204
198
}
@@ -236,3 +230,13 @@ fn env_path(var: &str) -> Result<PathBuf, Error> {
236
230
anyhow:: bail!( "missing environment variable {var}" )
237
231
}
238
232
}
233
+
234
+ /// Escapes any invalid HTML characters
235
+ fn escape_html ( input : & str ) -> String {
236
+ static MAPPING : [ ( char , & ' static str ) ; 3 ] = [ ( '&' , "&" ) , ( '<' , "<" ) , ( '>' , ">" ) ] ;
237
+ let mut output = input. to_owned ( ) ;
238
+ for ( ch, s) in & MAPPING {
239
+ output = output. replace ( * ch, s) ;
240
+ }
241
+ output
242
+ }
0 commit comments