Skip to content

sandbox upload creates a directory instead of a file when source is inside a git repository #1740

Description

@rh-hemartin

What happens

`openshell sandbox upload` creates a directory at the destination path instead of a regular file when the source file lives inside a git repository and the destination basename differs from the source basename. The directory contains the uploaded file under the original source basename.

What should happen

The file should land at the exact destination path with the destination basename, matching cp-style semantics — regardless of whether the source is inside a git repository.

How to reproduce

# Create and detach a sandbox
openshell sandbox create --name my-sandbox -- sleep 300 &
sleep 5

SANDBOX="my-sandbox"
openshell sandbox exec -n "${SANDBOX}" -- mkdir -p /tmp/repro/git-case /tmp/repro/nogit-case

# Case 1 (BUG): source inside a git repository
GITDIR="$(mktemp -d)"
echo '{"hello":"world"}' > "${GITDIR}/source.json"
git -C "${GITDIR}" init -q
git -C "${GITDIR}" add source.json
git -C "${GITDIR}" -c user.email="x@x" -c user.name="x" commit -q -m "init"

openshell sandbox upload "${SANDBOX}" "${GITDIR}/source.json" /tmp/repro/git-case/dest.json
openshell sandbox exec -n "${SANDBOX}" -- ls -la /tmp/repro/git-case/
# dest.json is a directory (BUG)

# Case 2 (OK): source outside any git repository
NOGITDIR="$(mktemp -d)"
echo '{"hello":"world"}' > "${NOGITDIR}/source.json"

openshell sandbox upload "${SANDBOX}" "${NOGITDIR}/source.json" /tmp/repro/nogit-case/dest.json
openshell sandbox exec -n "${SANDBOX}" -- ls -la /tmp/repro/nogit-case/
# dest.json is a regular file (correct)

Case 1 — source in git repo (bug):

drwxr-xr-x. 1 sandbox sandbox  22 Jun  4 dest.json

Case 2 — source outside git repo (correct):

-rw-r--r--. 1 sandbox sandbox  18 Jun  4 dest.json

Context

The cp-style fix from #694 corrected this for the non-git upload path. When the source is inside a git repository, the upload routes through git_sync_files, which still uses the old mkdir -p <dest> behavior. PR #1595 bypassed git_sync_files for symlinks but not for regular tracked files.

  • openshell version: 0.0.54
  • OS: Linux x86_64

Activity

  1. TaylorMutch commented on Jul 13, 2026

    @TaylorMutch
    Collaborator

    📋 triage-agent

    Triage Assessment

    Classification: bug-confirmed

    Summary

    Git-aware single-file uploads still violate the CLI's documented cp/scp-style destination semantics on current main. This is distinct from the earlier general upload fix (#694) and symlink fix (#1595), and no open fix PR was found.

    Investigation

    A regular file inside a Git repository is routed through git_sync_files() and sandbox_sync_up_files(). The Git filter correctly returns the requested file, but the upload path treats the user-supplied destination as a tar extraction directory and preserves the source basename, producing dest.json/source.json. The non-Git path instead splits the destination into parent and target basename, producing the requested dest.json. An existing E2E assertion currently codifies the inconsistent Git-path behavior.

    Recommendation

    Reuse the existing single-file destination planning and archive renaming for Git-filtered regular files, without changing directory uploads or .gitignore filtering. Update the E2E case to assert destination renaming as well as single-file scoping.

  2. added
    area:cliCLI-related work
    test:e2eRequires end-to-end coverage
    and removed
    state:triage-neededOpened without agent diagnostics and needs triage
    on Jul 13, 2026
  3. added theissue type on Jul 13, 2026
  4. rh-dnagornuks commented on Jul 15, 2026

    @rh-dnagornuks

    Hello, I made a PR against my own fork to fix this issue. Would the changes made there be acceptable upstream? I already submitted a vouch request here.

  5. rh-dnagornuks commented on Jul 21, 2026

    @rh-dnagornuks

    Hi, just wanted to follow up. I still have the fix ready to submit upstream once my vouch request is approved. Let me know if there's anything I should change in the fix. Thank you!

  6. github-actions commented on Aug 28, 2026

    @github-actions

    This issue has had no activity for 14 days and is now marked stale. It may be closed in 7 days if there is no further activity. Comment or remove the state:stale label to keep it open.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:cliCLI-related workstate:staleInactive item at risk of automatic closure.test:e2eRequires end-to-end coverage

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions