Skip to main content

turbopack_core/
file_source.rs

1use anyhow::{Result, bail};
2use turbo_rcstr::RcStr;
3use turbo_tasks::Vc;
4use turbo_tasks_fs::{FileContent, FileSystemEntryType, FileSystemPath, LinkContent};
5
6use crate::{
7    asset::{Asset, AssetContent},
8    ident::AssetIdent,
9    source::Source,
10};
11
12/// The raw [Source]. It represents raw content from a path without any
13/// references to other [Source]s.
14#[turbo_tasks::value]
15pub struct FileSource {
16    path: FileSystemPath,
17    query: RcStr,
18    fragment: RcStr,
19}
20
21impl FileSource {
22    pub fn new(path: FileSystemPath) -> Vc<Self> {
23        FileSource::new_with_query_and_fragment(path, RcStr::default(), RcStr::default())
24    }
25    pub fn new_with_query(path: FileSystemPath, query: RcStr) -> Vc<Self> {
26        FileSource::new_with_query_and_fragment(path, query, RcStr::default())
27    }
28}
29
30#[turbo_tasks::value_impl]
31impl FileSource {
32    #[turbo_tasks::function]
33    pub fn new_with_query_and_fragment(
34        path: FileSystemPath,
35        query: RcStr,
36        fragment: RcStr,
37    ) -> Vc<Self> {
38        Self::cell(FileSource {
39            path,
40            query,
41            fragment,
42        })
43    }
44}
45
46#[turbo_tasks::value_impl]
47impl Source for FileSource {
48    #[turbo_tasks::function]
49    fn ident(&self) -> Vc<AssetIdent> {
50        AssetIdent::from_path(self.path.clone())
51            .with_query(self.query.clone())
52            .with_fragment(self.fragment.clone())
53            .into_vc()
54    }
55
56    #[turbo_tasks::function]
57    fn description(&self) -> Vc<RcStr> {
58        Vc::cell(format!("file content of {}", self.path).into())
59    }
60}
61
62#[turbo_tasks::value_impl]
63impl Asset for FileSource {
64    #[turbo_tasks::function]
65    async fn content(&self) -> Result<Vc<AssetContent>> {
66        let file_type = &*self.path.get_type().await?;
67        match file_type {
68            FileSystemEntryType::Symlink => match &*self.path.read_link().await? {
69                LinkContent::Link { target, link_type } => Ok(AssetContent::Redirect {
70                    target: target.clone(),
71                    link_type: *link_type,
72                }
73                .cell()),
74                _ => bail!("Invalid symlink"),
75            },
76            FileSystemEntryType::File => {
77                Ok(AssetContent::File(self.path.read().to_resolved().await?).cell())
78            }
79            FileSystemEntryType::NotFound => {
80                Ok(AssetContent::File(FileContent::NotFound.resolved_cell()).cell())
81            }
82            _ => bail!("Invalid file type {:?}", file_type),
83        }
84    }
85}