use std::sync::Arc;
use super::core::GithubCore;
use opendal_core::raw::oio::Entry;
use opendal_core::raw::*;
use opendal_core::*;
pub struct GithubLister {
core: Arc<GithubCore>,
ctx: OperationContext,
path: String,
recursive: bool,
}
impl GithubLister {
pub fn new(core: Arc<GithubCore>, ctx: OperationContext, path: &str, recursive: bool) -> Self {
Self {
core,
ctx,
path: path.to_string(),
recursive,
}
}
}
impl oio::PageList for GithubLister {
async fn next_page(&self, ctx: &mut oio::PageContext) -> Result<()> {
let resp = self.core.list(&self.ctx, &self.path).await?;
let has_dir = resp.entries.iter().any(|e| e.type_field == "dir");
ctx.done = true;
if !self.recursive || !has_dir {
for entry in resp.entries {
let path = build_rel_path(&self.core.root, &entry.path);
let entry = if entry.type_field == "dir" {
let path = format!("{path}/");
Entry::new(&path, MetadataBuilder::dir().build())
} else {
if path.ends_with(".gitkeep") {
continue;
}
let mut m = MetadataBuilder::file(entry.size);
m.etag(entry.sha);
Entry::new(&path, m.build())
};
ctx.entries.push_back(entry);
}
if !self.path.ends_with('/') {
ctx.entries.push_back(Entry::new(
&format!("{}/", self.path),
MetadataBuilder::dir().build(),
));
}
return Ok(());
}
let tree = self
.core
.list_with_recursive(&self.ctx, &resp.git_url)
.await?;
for t in tree {
let path = if self.path == "/" {
t.path
} else {
format!("{}/{}", self.path.trim_end_matches('/'), t.path)
};
let entry = if t.type_field == "tree" {
let path = format!("{path}/");
Entry::new(&path, MetadataBuilder::dir().build())
} else {
if path.ends_with(".gitkeep") {
continue;
}
let size = t.size.ok_or_else(|| {
Error::new(
ErrorKind::Unexpected,
"github tree response does not contain blob size",
)
})?;
let mut m = MetadataBuilder::file(size);
m.etag(t.sha);
Entry::new(&path, m.build())
};
ctx.entries.push_back(entry);
}
if !self.path.ends_with('/') {
ctx.entries.push_back(Entry::new(
&format!("{}/", self.path),
MetadataBuilder::dir().build(),
));
}
Ok(())
}
}