diff --git a/engine/filesystem_manager.go b/engine/filesystem_manager.go index a5996a8..114cc5a 100644 --- a/engine/filesystem_manager.go +++ b/engine/filesystem_manager.go @@ -95,7 +95,7 @@ func (f *FileSystemManager) ListDirectoryEntries(ctx context.Context, p utils.Fu f.RLock() defer f.RUnlock() - logger.Info("listing directory %s => %s %t %d", p, startFileName, inclusive, limit) + logger.Info("listing directory %s => startFileName:%s inclusive:%t count:%d", p, startFileName, inclusive, limit) lastFileName, err = f.StreamListDirectoryEntries(ctx, p, startFileName, inclusive, limit+1, func(entry *utils.Entry) bool { entries = append(entries, entry) diff --git a/robotfs-cli b/robotfs-cli new file mode 100755 index 0000000..2470e10 --- /dev/null +++ b/robotfs-cli @@ -0,0 +1,329 @@ +#!/bin/bash + +ADDRESS="" + +process_error() { + if [ $1 -ne 200 ] && [ $1 -ne 204 ]; then + echo "Error: HTTP $1" + exit 1 + fi +} + +send_request() { + local method="$1" + local endpoint="$2" + local data="$3" + local file="$4" + + local curl_cmd="curl -s -w '\n%{http_code}'" + + if [ "$method" = "POST" ]; then + if [ ! -z "$file" ]; then + curl_cmd="$curl_cmd -X POST -F 'file=@$file'" + else + curl_cmd="$curl_cmd -X POST -H 'Content-Type: application/json'" + if [ ! -z "$data" ]; then + curl_cmd="$curl_cmd -d '$data'" + fi + fi + fi + + local response=$(eval "$curl_cmd '${ADDRESS}${endpoint}'") + local http_code=$(echo "$response" | tail -n1) + local body=$(echo "$response" | sed '$d') + + process_error "$http_code" + echo "$body" +} + +upload_file() { + local src="$1" + local dst="$2" + + if [ ! -f "$src" ]; then + echo "Error: Source file '$src' does not exist" >&2 + exit 1 + fi + + echo "Uploading: $src -> $dst" + if ! curl -# --write-out "\nUpload completed: %{size_upload} bytes in %{time_total}s\n" \ + -X POST -F "file=@$src" "${ADDRESS}/robotfs/file/upload?path=$dst" > /dev/null; then + echo "Error: Failed to upload file" >&2 + exit 1 + fi +} + +download_file() { + local src="$1" + local dst="$2" + + if [ -d "$dst" ]; then + local filename=$(echo "$src" | sed 's/.*\///') + dst="$dst/$filename" + fi + + local dir=$(dirname "$dst") + if [ ! -d "$dir" ]; then + mkdir -p "$dir" + fi + + echo "Downloading: $src -> $dst" + if ! curl -# --write-out "\nDownload completed: %{size_download} bytes in %{time_total}s\n" \ + -o "$dst" "${ADDRESS}/robotfs/file/download?path=$src&preview=false"; then + echo "Error: Failed to download file" >&2 + exit 1 + fi +} + +list_directory() { + local path="$1" + local start_file="" + local more_available=true + + while [ "$more_available" = "true" ]; do + local url="/robotfs/dir/list?path=${path}&inclusive=true&limit=50" + if [ ! -z "$start_file" ]; then + url="${url}&startFileName=${start_file}" + fi + + local response=$(send_request "GET" "$url") + + echo "$response" | sed 's/.*"entries":\[//;s/\].*$//' | sed 's/},{/}\n{/g' | \ + while IFS= read -r line; do + if [ -z "$line" ]; then + continue + fi + + name=$(echo "$line" | grep -o '"name":"[^"]*"' | cut -d'"' -f4) + is_dir=$(echo "$line" | grep -o '"is_dir":[^,]*' | cut -d':' -f2) + size=$(echo "$line" | grep -o '"size":[^,]*' | cut -d':' -f2) + + if [ "$is_dir" = "true" ]; then + echo " - $name [DIR]" + else + printf " - %s %s [FILE]\n" "$name" "$size" + fi + done + + more_available=$(echo "$response" | grep -o '"more_available":[^,]*' | cut -d':' -f2) + if [ "$more_available" = "true" ]; then + start_file=$(echo "$response" | grep -o '"last_file_name":"[^"]*"' | cut -d'"' -f4) + fi + done +} + +move_item() { + local src="$1" + local dst="$2" + local data="{\"SrcPath\":\"$src\",\"DstPath\":\"$dst\",\"IsDir\":false}" + + echo "Moving: $src -> $dst" + if ! send_request "POST" "/robotfs/file/rename" "$data" > /dev/null; then + echo "Error: Failed to move file" >&2 + exit 1 + fi + echo "Move completed" +} + +copy_item() { + local src="$1" + local dst="$2" + local data="{\"SrcPath\":\"$src\",\"DstPath\":\"$dst\",\"IsDir\":false}" + + echo "Copying: $src -> $dst" + if ! send_request "POST" "/robotfs/file/copy" "$data" > /dev/null; then + echo "Error: Failed to copy file" >&2 + exit 1 + fi + echo "Copy completed" +} + +remove_item() { + local path="$1" + local data="{\"Path\":\"$path\",\"IsDir\":false}" + + echo "Removing: $path" + if ! send_request "POST" "/robotfs/file/delete" "$data" > /dev/null; then + echo "Error: Failed to remove file" >&2 + exit 1 + fi + echo "Remove completed" +} + +move_dir() { + local src="$1" + local dst="$2" + local data="{\"SrcPath\":\"$src\",\"DstPath\":\"$dst\",\"IsDir\":true}" + + echo "Moving directory: $src -> $dst" + if ! send_request "POST" "/robotfs/dir/rename" "$data" > /dev/null; then + echo "Error: Failed to move directory" >&2 + exit 1 + fi + echo "Move completed" +} + +copy_dir() { + local src="$1" + local dst="$2" + local data="{\"SrcPath\":\"$src\",\"DstPath\":\"$dst\",\"IsDir\":true}" + + echo "Copying directory: $src -> $dst" + if ! send_request "POST" "/robotfs/dir/copy" "$data" > /dev/null; then + echo "Error: Failed to copy directory" >&2 + exit 1 + fi + echo "Copy completed" +} + +remove_dir() { + local path="$1" + local data="{\"Path\":\"$path\",\"IsDir\":true}" + + echo "Removing directory: $path" + if ! send_request "POST" "/robotfs/dir/delete" "$data" > /dev/null; then + echo "Error: Failed to remove directory" >&2 + exit 1 + fi + echo "Remove completed" +} + +copy_dir() { + local src="$1" + local dst="$2" + local data="{\"SrcPath\":\"$src\",\"DstPath\":\"$dst\",\"IsDir\":true}" + + echo "Copying directory: $src -> $dst" + if ! send_request "POST" "/robotfs/dir/copy" "$data" > /dev/null; then + echo "Error: Failed to copy directory" >&2 + exit 1 + fi + echo "Copy completed" +} + +make_directory() { + local path="$1" + local data="{\"Path\":\"$path\"}" + + echo "Creating directory: $path" + if ! send_request "POST" "/robotfs/mkdir" "$data" > /dev/null; then + echo "Error: Failed to create directory" >&2 + exit 1 + fi + echo "Create completed" +} + +show_usage() { + echo "Usage: $0