Fix repository paths containing spaces (#62)

This commit is contained in:
Georg Bauer
2026-08-15 11:41:04 +02:00
parent efdf5ee4c3
commit 8e2feac18e
3 changed files with 62 additions and 21 deletions

View File

@@ -374,9 +374,10 @@ answer before uploading it to App Store Connect.
- [ ] Switch a repository between **History** and **Files**. Each mode displays
the expected content and switching back preserves normal navigation.
- [ ] In Files, traverse several nested folders using rows, the navigation-bar
Back button, and the left-edge swipe. Folder contents and titles match the
repository hierarchy.
- [ ] In Files, traverse several nested folders using rows, including a folder
and file whose names contain spaces (for example below Chezmoi's
`private_Library`), the navigation-bar Back button, and the left-edge
swipe. Folder contents, files, and titles match the repository hierarchy.
- [ ] In the repository root and in several nested folders, switch between
**Files** and **History**. Each folder history contains only commits that
affect that folder or its descendants. Switch back to Files and verify the

View File

@@ -12,6 +12,10 @@ use crate::{
};
use gitea_openapi::apis;
fn encode_path(path: &str) -> String {
apis::urlencode(path).replace('+', "%20")
}
impl Client {
pub async fn current_user_repositories_page(
&self,
@@ -99,7 +103,7 @@ impl Client {
"repos/{}/{}/contents/{}",
apis::urlencode(&repository.owner),
apis::urlencode(&repository.repository),
apis::urlencode(path),
encode_path(path),
);
self.execute(self.request(Method::GET, &endpoint)?)
.await?
@@ -110,15 +114,14 @@ impl Client {
}
pub async fn repository_file(&self, repository: &RepositoryId, path: &str) -> Result<Vec<u8>> {
apis::repository_api::repo_get_raw_file(
&self.configuration(),
&repository.owner,
&repository.repository,
path,
None,
)
.await
.map_err(Error::generated)?
let endpoint = format!(
"repos/{}/{}/raw/{}",
apis::urlencode(&repository.owner),
apis::urlencode(&repository.repository),
encode_path(path),
);
self.execute(self.request(Method::GET, &endpoint)?)
.await?
.bytes()
.await
.map(|bytes| bytes.to_vec())

View File

@@ -110,7 +110,7 @@ async fn reads_nested_directory_from_compatible_contents_endpoint() {
let mut buffer = [0; 4096];
let length = stream.read(&mut buffer).unwrap();
let request = String::from_utf8_lossy(&buffer[..length]).into_owned();
let body = r#"[{"name":"guide.md","path":"docs/guide.md","type":"file"}]"#;
let body = r#"[{"name":"guide.md","path":"docs/private guide/guide.md","type":"file"}]"#;
write!(
stream,
"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{body}",
@@ -125,16 +125,53 @@ async fn reads_nested_directory_from_compatible_contents_endpoint() {
.unwrap();
let repository = RepositoryId::new("forgejo", "forgejo").unwrap();
let contents = client
.repository_contents(&repository, "docs/guide")
.repository_contents(&repository, "docs/private guide")
.await
.unwrap();
assert_eq!(contents.len(), 1);
assert_eq!(contents[0].path.as_deref(), Some("docs/guide.md"));
assert_eq!(
contents[0].path.as_deref(),
Some("docs/private guide/guide.md")
);
assert!(
server
.join()
.unwrap()
.starts_with("GET /api/v1/repos/forgejo/forgejo/contents/docs%2Fguide ")
.starts_with("GET /api/v1/repos/forgejo/forgejo/contents/docs%2Fprivate%20guide ")
);
}
#[tokio::test]
async fn reads_file_with_spaces_from_raw_endpoint() {
let listener = TcpListener::bind("127.0.0.1:0").unwrap();
let address = listener.local_addr().unwrap();
let server = thread::spawn(move || {
let (mut stream, _) = listener.accept().unwrap();
let mut buffer = [0; 4096];
let length = stream.read(&mut buffer).unwrap();
let request = String::from_utf8_lossy(&buffer[..length]).into_owned();
let body = "contents";
write!(
stream,
"HTTP/1.1 200 OK\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{body}",
body.len()
)
.unwrap();
request
});
let client = Client::new(&format!("http://{address}"), None).unwrap();
let repository = RepositoryId::new("gitea", "gitea").unwrap();
let contents = client
.repository_file(&repository, "docs/private guide/read me.md")
.await
.unwrap();
assert_eq!(contents, b"contents");
assert!(
server.join().unwrap().starts_with(
"GET /api/v1/repos/gitea/gitea/raw/docs%2Fprivate%20guide%2Fread%20me.md "
)
);
}