Skip to content

Commit 2bcea19

Browse files
cp -r test ok now
1 parent 50bb003 commit 2bcea19

File tree

1 file changed

+40
-19
lines changed
  • bin/oli/src/commands

1 file changed

+40
-19
lines changed

bin/oli/src/commands/cp.rs

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,11 @@ impl CopyCmd {
138138
);
139139
}
140140
Err(e) if e.kind() == ErrorKind::NotFound => {
141-
dst_op.create_dir(&final_dst_path).await?;
141+
let mut path_to_create = final_dst_path.clone();
142+
if !path_to_create.ends_with('/') {
143+
path_to_create.push('/');
144+
}
145+
dst_op.create_dir(&path_to_create).await?;
142146
}
143147
Err(e) => {
144148
// Another error occurred trying to stat the base destination.
@@ -149,43 +153,60 @@ impl CopyCmd {
149153
// Proceed with recursive copy logic. dst_root is the target directory.
150154
let dst_root = Path::new(&final_dst_path);
151155
let mut ds = src_op.lister_with(&src_path).recursive(true).await?;
152-
let prefix = src_path.strip_prefix('/').unwrap_or(src_path.as_str());
153156

154157
while let Some(de) = ds.try_next().await? {
155158
let meta = de.metadata();
156159
let depath = de.path();
157160

158-
// Calculate relative path from the source root
159-
let relative_path = depath.strip_prefix(prefix).with_context(|| {
160-
anyhow::anyhow!(
161-
"Internal error: Failed to strip prefix '{}' from path '{}'",
162-
prefix,
163-
depath
161+
// Calculate relative path using Path::strip_prefix
162+
let src_root_path = Path::new(&src_path);
163+
let entry_path = Path::new(depath);
164+
let relative_path = entry_path.strip_prefix(src_root_path).with_context(|| {
165+
format!(
166+
"Internal error: Lister path '{}' does not start with source path '{}'",
167+
depath, src_path
164168
)
165-
})?;
166-
let relative_path = relative_path.strip_prefix('/').unwrap_or(relative_path);
169+
})?; // relative_path is a &Path
167170

168-
let current_dst_path = dst_root.join(relative_path).to_string_lossy().to_string();
171+
let current_dst_path_path = dst_root.join(relative_path);
172+
let current_dst_path = current_dst_path_path.to_string_lossy().to_string();
169173

170174
if meta.mode().is_dir() {
171-
dst_op.create_dir(&current_dst_path).await?;
175+
let mut dir_path_to_create = current_dst_path.clone();
176+
if !dir_path_to_create.ends_with('/') {
177+
dir_path_to_create.push('/');
178+
}
179+
dst_op.create_dir(&dir_path_to_create).await?;
172180
continue;
173181
}
174182

175-
if let Some(parent) = Path::new(&current_dst_path).parent() {
176-
if parent != dst_root {
177-
dst_op.create_dir(&parent.to_string_lossy()).await?;
183+
// Explicitly stat the source file to get fresh metadata
184+
let fresh_meta = src_op.stat(depath).await.with_context(|| {
185+
format!(
186+
"Failed to stat source file '{}' before recursive copy",
187+
depath
188+
)
189+
})?;
190+
191+
// Use the Path object `current_dst_path_path` to check parent
192+
if let Some(parent_path) = current_dst_path_path.parent() {
193+
if parent_path != dst_root {
194+
let mut parent_dir_string = parent_path.to_string_lossy().into_owned();
195+
if !parent_dir_string.ends_with('/') {
196+
parent_dir_string.push('/');
197+
}
198+
dst_op.create_dir(&parent_dir_string).await?;
178199
}
179200
}
180201

181-
let reader = src_op.reader_with(de.path()).chunk(8 * 1024 * 1024).await?;
202+
let reader = src_op.reader_with(depath).chunk(8 * 1024 * 1024).await?;
182203
let buf_reader = reader
183-
.into_futures_async_read(0..meta.content_length())
204+
.into_futures_async_read(0..fresh_meta.content_length())
184205
.await?;
185206

186-
let copy_progress = CopyProgress::new(meta, de.path().to_string());
207+
let copy_progress = CopyProgress::new(&fresh_meta, depath.to_string());
187208
let mut writer = dst_op
188-
.writer(&current_dst_path) // Use the calculated path
209+
.writer(&current_dst_path)
189210
.await?
190211
.into_futures_async_write();
191212

0 commit comments

Comments
 (0)