Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions crates/openshell-cli/src/ssh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -970,6 +970,28 @@ pub async fn sandbox_sync_up_files(
if files.is_empty() {
return Ok(());
}

if files.len() == 1
&& local_upload_path_is_file_like(local_path)
&& let Some(path) = dest
&& !path.ends_with('/')
{
let (parent, target_name) = split_sandbox_path(path);
if parent != "/" {
return ssh_tar_upload(
server,
name,
Some(parent),
UploadSource::SinglePath {
local_path: base_dir.join(&files[0]),
tar_name: target_name.into(),
},
tls,
)
.await;
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

ssh_tar_upload(
server,
name,
Expand Down
13 changes: 9 additions & 4 deletions e2e/rust/tests/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,8 @@ async fn upload_respects_gitignore_by_default() {
}

/// Verify that uploading a single tracked file from inside a git repo does not
/// expand to the entire repository.
/// expand to the entire repository, and that the destination basename is
/// respected (cp-style semantics).
#[tokio::test]
async fn upload_single_file_from_git_repo_only_uploads_that_file() {
let mut guard =
Expand Down Expand Up @@ -330,7 +331,7 @@ async fn upload_single_file_from_git_repo_only_uploads_that_file() {
let local_path = repo.join("nested/config.txt");
let local_str = local_path.to_str().expect("local path is UTF-8");
guard
.upload_with_gitignore(local_str, "/sandbox/single-file", &repo)
.upload_with_gitignore(local_str, "/sandbox/renamed.txt", &repo)
.await
.expect("upload single tracked file with gitignore");

Expand All @@ -339,12 +340,16 @@ async fn upload_single_file_from_git_repo_only_uploads_that_file() {
let download_str = download_dir.to_str().expect("download path is UTF-8");

guard
.download("/sandbox/single-file", download_str)
.download("/sandbox/renamed.txt", download_str)
.await
.expect("download uploaded single file");

let uploaded = fs::read_to_string(download_dir.join("config.txt")).expect("read config.txt");
let uploaded = fs::read_to_string(download_dir.join("renamed.txt")).expect("read renamed.txt");
assert_eq!(uploaded, "single-file-from-repo");
assert!(
!download_dir.join("config.txt").exists(),
"original basename config.txt should not appear — file must be renamed to dest basename"
);
assert!(
!download_dir.join("tracked.txt").exists(),
"tracked.txt should not have been uploaded"
Expand Down