diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py index eade9e04559..5ab1874e9ed 100755 --- a/src/etc/htmldocck.py +++ b/src/etc/htmldocck.py @@ -110,6 +110,9 @@ There are a number of supported commands: * `@has-dir PATH` checks for the existence of the given directory. +* `@files FOLDER_PATH [ENTRIES]`, checks that `FOLDER_PATH` contains exactly + `[ENTRIES]`. + All conditions can be negated with `!`. `@!has foo/type.NoSuch.html` checks if the given file does not exist, for example. @@ -321,12 +324,15 @@ class CachedFiles(object): else: return self.last_path + def get_absolute_path(self, path): + return os.path.join(self.root, path) + def get_file(self, path): path = self.resolve_path(path) if path in self.files: return self.files[path] - abspath = os.path.join(self.root, path) + abspath = self.get_absolute_path(path) if not(os.path.exists(abspath) and os.path.isfile(abspath)): raise FailedCheck('File does not exist {!r}'.format(path)) @@ -340,7 +346,7 @@ class CachedFiles(object): if path in self.trees: return self.trees[path] - abspath = os.path.join(self.root, path) + abspath = self.get_absolute_path(path) if not(os.path.exists(abspath) and os.path.isfile(abspath)): raise FailedCheck('File does not exist {!r}'.format(path)) @@ -356,7 +362,7 @@ class CachedFiles(object): def get_dir(self, path): path = self.resolve_path(path) - abspath = os.path.join(self.root, path) + abspath = self.get_absolute_path(path) if not(os.path.exists(abspath) and os.path.isdir(abspath)): raise FailedCheck('Directory does not exist {!r}'.format(path)) @@ -538,6 +544,41 @@ def get_nb_matching_elements(cache, c, regexp, stop_at_first): return check_tree_text(cache.get_tree(c.args[0]), pat, c.args[2], regexp, stop_at_first) +def check_files_in_folder(c, cache, folder, files): + files = files.strip() + if not files.startswith('[') or not files.endswith(']'): + raise InvalidCheck("Expected list as second argument of @{} (ie '[]')".format(c.cmd)) + + folder = cache.get_absolute_path(folder) + + # First we create a set of files to check if there are duplicates. + files = shlex.split(files[1:-1].replace(",", "")) + files_set = set() + for file in files: + if file in files_set: + raise InvalidCheck("Duplicated file `{}` in @{}".format(file, c.cmd)) + files_set.add(file) + folder_set = set([f for f in os.listdir(folder) if f != "." and f != ".."]) + + # Then we remove entries from both sets (we clone `folder_set` so we can iterate it while + # removing its elements). + for entry in set(folder_set): + if entry in files_set: + files_set.remove(entry) + folder_set.remove(entry) + + error = 0 + if len(files_set) != 0: + print_err(c.lineno, c.context, "Entries not found in folder `{}`: `{}`".format( + folder, files_set)) + error += 1 + if len(folder_set) != 0: + print_err(c.lineno, c.context, "Extra entries in folder `{}`: `{}`".format( + folder, folder_set)) + error += 1 + return error == 0 + + ERR_COUNT = 0 @@ -566,6 +607,13 @@ def check_command(c, cache): else: raise InvalidCheck('Invalid number of @{} arguments'.format(c.cmd)) + elif c.cmd == 'files': # check files in given folder + if len(c.args) != 2: # @files + raise InvalidCheck("Invalid number of @{} arguments".format(c.cmd)) + elif c.negated: + raise InvalidCheck("@{} doesn't support negative check".format(c.cmd)) + ret = check_files_in_folder(c, cache, c.args[0], c.args[1]) + elif c.cmd == 'count': # count test if len(c.args) == 3: # @count = count test expected = int(c.args[2]) diff --git a/tests/rustdoc/files-creation-hidden.rs b/tests/rustdoc/files-creation-hidden.rs index bcabbfc91e8..498d9cdaef1 100644 --- a/tests/rustdoc/files-creation-hidden.rs +++ b/tests/rustdoc/files-creation-hidden.rs @@ -1,5 +1,6 @@ #![crate_name="foo"] +// @files foo '["index.html", "all.html", "sidebar-items.js"]' // @!has "foo/struct.Foo.html" #[doc(hidden)] pub struct Foo; diff --git a/tests/rustdoc/files-creation-private.rs b/tests/rustdoc/files-creation-private.rs index ca2327e0f91..e2fdbc068f8 100644 --- a/tests/rustdoc/files-creation-private.rs +++ b/tests/rustdoc/files-creation-private.rs @@ -1,5 +1,9 @@ #![crate_name="foo"] +// @files "foo" \ +// '["index.html", "all.html", "sidebar-items.js", "foo", "bar", "private", "struct.Bar.html"]' +// @files "foo/bar" '["index.html", "sidebar-items.js"]' + // @!has "foo/priv/index.html" // @!has "foo/priv/struct.Foo.html" mod private { diff --git a/tests/rustdoc/issue-111064-reexport-trait-from-hidden-2.rs b/tests/rustdoc/issue-111064-reexport-trait-from-hidden-2.rs index d6832bb7a09..65c26d6a837 100644 --- a/tests/rustdoc/issue-111064-reexport-trait-from-hidden-2.rs +++ b/tests/rustdoc/issue-111064-reexport-trait-from-hidden-2.rs @@ -2,6 +2,12 @@ #![no_core] #![crate_name = "foo"] +// @files "foo" "['sidebar-items.js', 'all.html', 'hidden', 'index.html', 'struct.Bar.html', \ +// 'visible']" +// @files "foo/hidden" "['inner']" +// @files "foo/hidden/inner" "['trait.Foo.html']" +// @files "foo/visible" "['index.html', 'sidebar-items.js', 'trait.Foo.html']" + // @!has 'foo/hidden/index.html' // @!has 'foo/hidden/inner/index.html' // FIXME: Should be `@!has`: https://github.com/rust-lang/rust/issues/111249 diff --git a/tests/rustdoc/issue-111249-file-creation.rs b/tests/rustdoc/issue-111249-file-creation.rs index d2042b231e4..afd65ddaf94 100644 --- a/tests/rustdoc/issue-111249-file-creation.rs +++ b/tests/rustdoc/issue-111249-file-creation.rs @@ -2,6 +2,12 @@ #![feature(no_core)] #![no_core] +// @files "foo" "['all.html', 'visible', 'index.html', 'sidebar-items.js', 'hidden', \ +// 'struct.Bar.html']" +// @files "foo/visible" "['trait.Foo.html', 'index.html', 'sidebar-items.js']" +// @files "foo/hidden" "['inner']" +// @files "foo/hidden/inner" "['trait.Foo.html']" + // The following five should not fail! // @!has 'foo/hidden/index.html' // @!has 'foo/hidden/inner/index.html'