pub async fn add_file(&mut self, file: &IgnoreFile) -> Result<(), Error> {
		let applies_in = get_applies_in_path(&self.origin, file);
		let applies_in_str = applies_in.display().to_string();

		if self.ignores.get(&applies_in_str).is_none() {
			self.ignores.insert(
				applies_in_str.clone(),
				Ignore {
					gitignore: Gitignore::empty(),
					builder: Some(GitignoreBuilder::new(&applies_in)),
				},
			);
		}

		let Some(Ignore {
			builder: Some(ref mut builder),
			..
		}) = self.ignores.get_mut(&applies_in_str)
		else {
			return Ok(());
		};

		trace!(?file, "reading ignore file");
		let content = read_to_string(&file.path)
			.await
			.map_err(|err| Error::Read {
				file: file.path.clone(),
				err,
			})?;

		let _span = trace_span!("loading ignore file", ?file).entered();
		for line in content.lines() {
			if line.is_empty() || line.starts_with('#') {
				continue;
			}

			trace!(?line, "adding ignore line");
			builder
				.add_line(Some(applies_in.clone()), line)
				.map_err(|err| Error::Glob {
					file: Some(file.path.clone()),
					err,
				})?;
		}

		self.recompile(file)?;

		Ok(())
	}
Reads and adds an ignore file, if the builder is available.

Does nothing silently otherwise.
crates/ignore-files/src/filter.rs