portacode 1.5.6.dev1__tar.gz → 1.5.6.dev3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/PKG-INFO +1 -1
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/_version.py +2 -2
- portacode-1.5.6.dev3/portacode/connection/handlers/file_transfer_handlers.py +206 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/project_state/git_manager.py +44 -18
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/terminal.py +3 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode.egg-info/PKG-INFO +1 -1
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode.egg-info/SOURCES.txt +1 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/.claude/agents/communication-manager.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/.claude/settings.local.json +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/.gitignore +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/.gitmodules +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/LICENSE +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/MANIFEST.in +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/Makefile +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/README.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/backup.sh +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/build_android.sh +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/connect.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/connect.sh +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/docker-compose.yaml +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/docs/cloudflared-domain-connect-containers-audit.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/docs/creative-team-brief-portacode.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/docs/devops-messaging-ab-tests.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/docs/homepage-dashboard-positioning-fixes.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/docs/images/device-transfer-button.png +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/docs/images/device-transfer-modal.png +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/docs/images/pair-device-button.png +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/docs/images/pairing-request.png +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/docs/images/student-workspace.png +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/docs/template-guide.html +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/README.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/simple_device/Dockerfile +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/simple_device/README.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/simple_device/data/device-01/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/simple_device/data/device-01/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/simple_device/docker-compose.yaml +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/Dockerfile +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/README.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/.local/share/portacode/run/gateway.pid +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/.gitignore +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/README.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/db.sqlite3 +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__pycache__/__init__.cpython-311.pyc +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__pycache__/settings.cpython-311.pyc +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__pycache__/urls.cpython-311.pyc +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__pycache__/wsgi.cpython-311.pyc +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/manage.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/requirements.txt +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/templates/treats/home.html +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/__init__.cpython-311.pyc +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/admin.cpython-311.pyc +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/apps.cpython-311.pyc +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/menu.cpython-311.pyc +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/models.cpython-311.pyc +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/urls.cpython-311.pyc +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/views.cpython-311.pyc +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/admin.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/apps.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/menu.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/migrations/__pycache__/__init__.cpython-311.pyc +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/models.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/tests.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/urls.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/views.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-02/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-02/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-02/workspace/README.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-02/workspace/manage.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-02/workspace/requirements.txt +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-02/workspace/templates/treats/home.html +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-02/workspace/treats/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-02/workspace/treats/admin.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-02/workspace/treats/apps.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-02/workspace/treats/menu.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-02/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-02/workspace/treats/models.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-02/workspace/treats/tests.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-02/workspace/treats/urls.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-02/workspace/treats/views.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-03/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-03/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-03/workspace/README.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-03/workspace/manage.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-03/workspace/requirements.txt +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-03/workspace/templates/treats/home.html +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-03/workspace/treats/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-03/workspace/treats/admin.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-03/workspace/treats/apps.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-03/workspace/treats/menu.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-03/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-03/workspace/treats/models.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-03/workspace/treats/tests.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-03/workspace/treats/urls.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-03/workspace/treats/views.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-04/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-04/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-04/workspace/README.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-04/workspace/manage.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-04/workspace/requirements.txt +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-04/workspace/templates/treats/home.html +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-04/workspace/treats/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-04/workspace/treats/admin.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-04/workspace/treats/apps.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-04/workspace/treats/menu.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-04/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-04/workspace/treats/models.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-04/workspace/treats/tests.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-04/workspace/treats/urls.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-04/workspace/treats/views.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-05/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-05/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-05/workspace/README.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-05/workspace/manage.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-05/workspace/requirements.txt +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-05/workspace/templates/treats/home.html +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-05/workspace/treats/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-05/workspace/treats/admin.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-05/workspace/treats/apps.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-05/workspace/treats/menu.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-05/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-05/workspace/treats/models.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-05/workspace/treats/tests.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-05/workspace/treats/urls.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-05/workspace/treats/views.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-06/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-06/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-06/workspace/README.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-06/workspace/manage.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-06/workspace/requirements.txt +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-06/workspace/templates/treats/home.html +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-06/workspace/treats/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-06/workspace/treats/admin.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-06/workspace/treats/apps.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-06/workspace/treats/menu.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-06/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-06/workspace/treats/models.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-06/workspace/treats/tests.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-06/workspace/treats/urls.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-06/workspace/treats/views.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-07/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-07/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-07/workspace/README.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-07/workspace/manage.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-07/workspace/requirements.txt +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-07/workspace/templates/treats/home.html +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-07/workspace/treats/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-07/workspace/treats/admin.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-07/workspace/treats/apps.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-07/workspace/treats/menu.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-07/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-07/workspace/treats/models.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-07/workspace/treats/tests.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-07/workspace/treats/urls.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-07/workspace/treats/views.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-08/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-08/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-08/workspace/README.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-08/workspace/manage.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-08/workspace/requirements.txt +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-08/workspace/templates/treats/home.html +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-08/workspace/treats/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-08/workspace/treats/admin.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-08/workspace/treats/apps.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-08/workspace/treats/menu.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-08/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-08/workspace/treats/models.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-08/workspace/treats/tests.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-08/workspace/treats/urls.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-08/workspace/treats/views.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-09/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-09/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-09/workspace/README.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-09/workspace/manage.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-09/workspace/requirements.txt +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-09/workspace/templates/treats/home.html +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-09/workspace/treats/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-09/workspace/treats/admin.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-09/workspace/treats/apps.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-09/workspace/treats/menu.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-09/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-09/workspace/treats/models.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-09/workspace/treats/tests.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-09/workspace/treats/urls.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-09/workspace/treats/views.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-10/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-10/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-10/workspace/README.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-10/workspace/manage.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-10/workspace/requirements.txt +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-10/workspace/templates/treats/home.html +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-10/workspace/treats/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-10/workspace/treats/admin.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-10/workspace/treats/apps.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-10/workspace/treats/menu.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-10/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-10/workspace/treats/models.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-10/workspace/treats/tests.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-10/workspace/treats/urls.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/data/student-10/workspace/treats/views.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/docker-compose.yaml +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/initial_content/README.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/initial_content/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/initial_content/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/initial_content/galactic_bakeshop/settings.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/initial_content/galactic_bakeshop/urls.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/initial_content/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/initial_content/manage.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/initial_content/requirements.txt +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/initial_content/templates/treats/home.html +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/initial_content/treats/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/initial_content/treats/admin.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/initial_content/treats/apps.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/initial_content/treats/menu.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/initial_content/treats/migrations/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/initial_content/treats/models.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/initial_content/treats/tests.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/initial_content/treats/urls.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/initial_content/treats/views.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/examples/workshop_fleet/instructions/WELCOME.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/README.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/__main__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/cli.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/README.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/client.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/README.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/WEBSOCKET_PROTOCOL.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/automation_v2_handlers.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/base.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/chunked_content.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/cloudflare_forwarding.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/cloudflare_tunnel.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/diff_handlers.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/file_handlers.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/project_aware_file_handlers.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/project_state/README.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/project_state/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/project_state/file_system_watcher.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/project_state/handlers.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/project_state/manager.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/project_state/models.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/project_state/utils.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/project_state_handlers.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/proxmox_infra.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/registry.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/runtime_user.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/session.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/system_handlers.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/tab_factory.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/terminal_handlers.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/test_cloudflare_forwarding.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/test_proxmox_infra.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/test_runtime_user.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/handlers/update_handler.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/multiplex.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/test_webmin_proxy_config.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/connection/webmin_proxy_config.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/data.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/exit_codes.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/keypair.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/link_capture/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/link_capture/__pycache__/__init__.cpython-311.pyc +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/link_capture/bin/__pycache__/link_capture_wrapper.cpython-311.pyc +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/link_capture/bin/elinks +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/link_capture/bin/gio-open +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/link_capture/bin/gnome-open +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/link_capture/bin/gvfs-open +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/link_capture/bin/kde-open +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/link_capture/bin/kfmclient +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/link_capture/bin/link_capture_exec.sh +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/link_capture/bin/link_capture_wrapper.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/link_capture/bin/links +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/link_capture/bin/links2 +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/link_capture/bin/lynx +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/link_capture/bin/mate-open +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/link_capture/bin/netsurf +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/link_capture/bin/sensible-browser +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/link_capture/bin/w3m +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/link_capture/bin/x-www-browser +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/link_capture/bin/xdg-open +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/logging_categories.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/pairing.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/restart.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/service.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/static/js/test-ntp-clock.html +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/static/js/utils/ntp-clock.js +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/test_runtime_paths.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/test_service.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/test_terminal_exposed_services.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/tunneling/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/tunneling/cloudflared_login.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/tunneling/ensure_cloudflared.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/tunneling/ensure_pyyaml.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/tunneling/forwarding_state.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/tunneling/get_domain.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/tunneling/privileged.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/tunneling/service_install.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/tunneling/state.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/updater.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/utils/NTP_ARCHITECTURE.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/utils/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/utils/diff_apply.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/utils/diff_renderer.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/utils/ntp_clock.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode/utils/runtime_paths.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode.egg-info/dependency_links.txt +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode.egg-info/entry_points.txt +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode.egg-info/requires.txt +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/portacode.egg-info/top_level.txt +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/pyproject.toml +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/restore.sh +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/run_tests.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/setup.cfg +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/setup.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/test.sh +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/test_modules/README.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/test_modules/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/test_modules/test_device_online.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/test_modules/test_file_operations.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/test_modules/test_git_status_ui.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/test_modules/test_login_flow.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/test_modules/test_navigate_testing_folder.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/test_modules/test_play_store_screenshots.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/test_modules/test_terminal_buffer_performance.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/test_modules/test_terminal_interaction.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/test_modules/test_terminal_loading_race_condition.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/test_modules/test_terminal_start.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/test_request_id.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/testing_framework/.env.example +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/testing_framework/README.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/testing_framework/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/testing_framework/cli.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/testing_framework/core/__init__.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/testing_framework/core/base_test.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/testing_framework/core/cli_manager.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/testing_framework/core/hierarchical_runner.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/testing_framework/core/playwright_manager.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/testing_framework/core/runner.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/testing_framework/core/shared_cli_manager.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/testing_framework/core/test_discovery.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/testing_framework/requirements.txt +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/todo/UI_UX/opening_a_file_on_desktop_results_in_nothing.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/todo/UI_UX/server_occasionally_stops_communicating_with_all_devices.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/todo/agent_context_management.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/todo/django_server_time_sync.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/todo/issues/device_performance_degradation.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/todo/issues/git_data_not_captured_in_proxmox.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/todo/issues/indefinite_resource_loading.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/todo/issues/portacode_service_silently_down.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/todo/issues/premature_terminal_exit.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/todo/issues/project_cpu_hotspots.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/todo/issues/terminals_exit_upon_starting.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/todo/issues/websocket_client_silently_dead.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/todo/issues/wrong_item_classification_on_client_side.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/todo/smartphone_terminal_input_frustrations.md +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/tools/generate_play_store_assets.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/tools/pairing_tester.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/tools/run_screenshot_suite.sh +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/tools/test_python_ntp_clock.py +0 -0
- {portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/validate.sh +0 -0
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '1.5.6.
|
|
32
|
-
__version_tuple__ = version_tuple = (1, 5, 6, '
|
|
31
|
+
__version__ = version = '1.5.6.dev3'
|
|
32
|
+
__version_tuple__ = version_tuple = (1, 5, 6, 'dev3')
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"""Isolated handlers for websocket file upload and download transfers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
import base64
|
|
7
|
+
import logging
|
|
8
|
+
import os
|
|
9
|
+
import pwd
|
|
10
|
+
import stat
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import Any, Dict, Optional
|
|
13
|
+
|
|
14
|
+
from .base import AsyncHandler, SyncHandler
|
|
15
|
+
from .chunked_content import ChunkAssembler, create_chunked_response
|
|
16
|
+
from .project_state.manager import get_or_create_project_state_manager
|
|
17
|
+
from .runtime_user import get_default_runtime_user
|
|
18
|
+
|
|
19
|
+
logger = logging.getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _schedule_project_state_refresh(handler, changed_path: str) -> None:
|
|
23
|
+
try:
|
|
24
|
+
manager = get_or_create_project_state_manager(handler.context, handler.control_channel)
|
|
25
|
+
loop = asyncio.get_event_loop()
|
|
26
|
+
if loop.is_running():
|
|
27
|
+
loop.create_task(manager.refresh_project_state_for_file_change(str(changed_path)))
|
|
28
|
+
except Exception as exc:
|
|
29
|
+
logger.warning("Failed to refresh project state after transfer for %s: %s", changed_path, exc)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _chown_path_if_possible(path: str | Path, user: Optional[str]) -> None:
|
|
33
|
+
if not user or os.name == "nt":
|
|
34
|
+
return
|
|
35
|
+
try:
|
|
36
|
+
pw_entry = pwd.getpwnam(user)
|
|
37
|
+
os.chown(path, pw_entry.pw_uid, pw_entry.pw_gid)
|
|
38
|
+
except Exception:
|
|
39
|
+
return
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _restore_metadata(path: Path, original_stat: Optional[os.stat_result]) -> None:
|
|
43
|
+
if original_stat is None:
|
|
44
|
+
return
|
|
45
|
+
try:
|
|
46
|
+
os.chmod(path, stat.S_IMODE(original_stat.st_mode))
|
|
47
|
+
except OSError:
|
|
48
|
+
pass
|
|
49
|
+
try:
|
|
50
|
+
os.chown(path, original_stat.st_uid, original_stat.st_gid)
|
|
51
|
+
except OSError:
|
|
52
|
+
pass
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _write_bytes_preserve_metadata(path: str | Path, content: bytes, *, create_user: Optional[str] = None) -> int:
|
|
56
|
+
target = Path(path)
|
|
57
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
58
|
+
existed = target.exists()
|
|
59
|
+
original_stat = target.stat() if existed else None
|
|
60
|
+
|
|
61
|
+
with open(target, "wb") as file_obj:
|
|
62
|
+
file_obj.write(content)
|
|
63
|
+
|
|
64
|
+
if existed:
|
|
65
|
+
_restore_metadata(target, original_stat)
|
|
66
|
+
else:
|
|
67
|
+
_chown_path_if_possible(target, create_user)
|
|
68
|
+
|
|
69
|
+
return len(content)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class FileUploadHandler(SyncHandler):
|
|
73
|
+
"""Upload a file to disk, optionally across multiple websocket chunks."""
|
|
74
|
+
|
|
75
|
+
def __init__(self, control_channel, context):
|
|
76
|
+
super().__init__(control_channel, context)
|
|
77
|
+
self._chunk_assembler = ChunkAssembler()
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def command_name(self) -> str:
|
|
81
|
+
return "file_upload"
|
|
82
|
+
|
|
83
|
+
def execute(self, message: Dict[str, Any]) -> Dict[str, Any]:
|
|
84
|
+
path = message.get("path")
|
|
85
|
+
file_name = message.get("file_name") or (Path(path).name if path else None)
|
|
86
|
+
mime_type = message.get("mime_type") or "application/octet-stream"
|
|
87
|
+
chunked = bool(message.get("chunked", False))
|
|
88
|
+
|
|
89
|
+
try:
|
|
90
|
+
self._chunk_assembler.cleanup_stale_transfers()
|
|
91
|
+
if not path:
|
|
92
|
+
raise ValueError("path parameter is required")
|
|
93
|
+
|
|
94
|
+
content_base64 = message.get("content_base64")
|
|
95
|
+
if chunked:
|
|
96
|
+
content_base64 = self._chunk_assembler.add_chunk(message, "content_base64")
|
|
97
|
+
if content_base64 is None:
|
|
98
|
+
return {
|
|
99
|
+
"event": "file_upload_response",
|
|
100
|
+
"path": path,
|
|
101
|
+
"file_name": file_name,
|
|
102
|
+
"mime_type": mime_type,
|
|
103
|
+
"transfer_id": message.get("transfer_id"),
|
|
104
|
+
"chunked": True,
|
|
105
|
+
"chunk_received": True,
|
|
106
|
+
"success": True,
|
|
107
|
+
"complete": False,
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if content_base64 is None:
|
|
111
|
+
raise ValueError("content_base64 parameter is required")
|
|
112
|
+
|
|
113
|
+
overwrite = bool(message.get("overwrite", False))
|
|
114
|
+
file_path = Path(path)
|
|
115
|
+
parent_dir = file_path.parent
|
|
116
|
+
if not parent_dir.exists():
|
|
117
|
+
raise ValueError(f"Parent directory does not exist: {parent_dir}")
|
|
118
|
+
if not parent_dir.is_dir():
|
|
119
|
+
raise ValueError(f"Parent path is not a directory: {parent_dir}")
|
|
120
|
+
if file_path.exists() and not overwrite:
|
|
121
|
+
raise ValueError(f"Target already exists: {file_path}")
|
|
122
|
+
|
|
123
|
+
try:
|
|
124
|
+
content_bytes = base64.b64decode(content_base64.encode("ascii"), validate=True)
|
|
125
|
+
except Exception as exc:
|
|
126
|
+
raise ValueError(f"Invalid base64 file content: {exc}") from exc
|
|
127
|
+
|
|
128
|
+
bytes_written = _write_bytes_preserve_metadata(
|
|
129
|
+
file_path,
|
|
130
|
+
content_bytes,
|
|
131
|
+
create_user=get_default_runtime_user(message),
|
|
132
|
+
)
|
|
133
|
+
_schedule_project_state_refresh(self, str(file_path))
|
|
134
|
+
|
|
135
|
+
return {
|
|
136
|
+
"event": "file_upload_response",
|
|
137
|
+
"path": str(file_path),
|
|
138
|
+
"file_name": file_name,
|
|
139
|
+
"mime_type": mime_type,
|
|
140
|
+
"bytes_written": bytes_written,
|
|
141
|
+
"file_size": len(content_bytes),
|
|
142
|
+
"chunked": chunked,
|
|
143
|
+
"success": True,
|
|
144
|
+
"complete": True,
|
|
145
|
+
}
|
|
146
|
+
except Exception as exc:
|
|
147
|
+
return {
|
|
148
|
+
"event": "file_upload_response",
|
|
149
|
+
"path": path,
|
|
150
|
+
"file_name": file_name,
|
|
151
|
+
"mime_type": mime_type,
|
|
152
|
+
"chunked": chunked,
|
|
153
|
+
"success": False,
|
|
154
|
+
"complete": True,
|
|
155
|
+
"error": str(exc),
|
|
156
|
+
"message": str(exc),
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
class FileDownloadHandler(AsyncHandler):
|
|
161
|
+
"""Read a file from disk and send it as base64, chunked when large."""
|
|
162
|
+
|
|
163
|
+
@property
|
|
164
|
+
def command_name(self) -> str:
|
|
165
|
+
return "file_download"
|
|
166
|
+
|
|
167
|
+
async def execute(self, message: Dict[str, Any]) -> Dict[str, Any]:
|
|
168
|
+
path = message.get("path")
|
|
169
|
+
try:
|
|
170
|
+
if not path:
|
|
171
|
+
raise ValueError("path parameter is required")
|
|
172
|
+
|
|
173
|
+
file_path = Path(path)
|
|
174
|
+
if not file_path.exists():
|
|
175
|
+
raise ValueError(f"File not found: {path}")
|
|
176
|
+
if not file_path.is_file():
|
|
177
|
+
raise ValueError(f"Path is not a file: {path}")
|
|
178
|
+
|
|
179
|
+
content_bytes = file_path.read_bytes()
|
|
180
|
+
content_base64 = base64.b64encode(content_bytes).decode("ascii")
|
|
181
|
+
base_response = {
|
|
182
|
+
"event": "file_download_response",
|
|
183
|
+
"path": str(file_path),
|
|
184
|
+
"file_name": file_path.name,
|
|
185
|
+
"mime_type": message.get("mime_type") or "application/octet-stream",
|
|
186
|
+
"file_size": len(content_bytes),
|
|
187
|
+
"success": True,
|
|
188
|
+
}
|
|
189
|
+
if "request_id" in message:
|
|
190
|
+
base_response["request_id"] = message["request_id"]
|
|
191
|
+
|
|
192
|
+
for response in create_chunked_response(base_response, "content_base64", content_base64):
|
|
193
|
+
await self.send_response(response, project_id=message.get("project_id"))
|
|
194
|
+
return None
|
|
195
|
+
except Exception as exc:
|
|
196
|
+
response = {
|
|
197
|
+
"event": "file_download_response",
|
|
198
|
+
"path": path,
|
|
199
|
+
"success": False,
|
|
200
|
+
"chunked": False,
|
|
201
|
+
"error": str(exc),
|
|
202
|
+
"message": str(exc),
|
|
203
|
+
}
|
|
204
|
+
if "request_id" in message:
|
|
205
|
+
response["request_id"] = message["request_id"]
|
|
206
|
+
return response
|
|
@@ -16,6 +16,7 @@ from pathlib import Path
|
|
|
16
16
|
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
|
|
17
17
|
|
|
18
18
|
from .models import GitDetailedStatus, GitFileChange
|
|
19
|
+
from ..runtime_user import get_default_runtime_user, wrap_argv_for_user
|
|
19
20
|
|
|
20
21
|
logger = logging.getLogger(__name__)
|
|
21
22
|
|
|
@@ -138,6 +139,30 @@ class GitManager:
|
|
|
138
139
|
continue
|
|
139
140
|
except Exception as e:
|
|
140
141
|
logger.debug("Error tracking git processes: %s", e)
|
|
142
|
+
|
|
143
|
+
def _run_git_write(self, args: List[str]) -> subprocess.CompletedProcess:
|
|
144
|
+
"""Run a mutating git command as the configured runtime user."""
|
|
145
|
+
runtime_user = get_default_runtime_user()
|
|
146
|
+
cwd = self.repo.working_tree_dir if self.repo and self.repo.working_tree_dir else self.project_path
|
|
147
|
+
argv = wrap_argv_for_user(["git", *args], runtime_user, cwd=cwd)
|
|
148
|
+
return subprocess.run(
|
|
149
|
+
argv,
|
|
150
|
+
cwd=cwd,
|
|
151
|
+
check=True,
|
|
152
|
+
capture_output=True,
|
|
153
|
+
text=True,
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
def _remove_file_as_runtime_user(self, file_path: str) -> None:
|
|
157
|
+
runtime_user = get_default_runtime_user()
|
|
158
|
+
argv = wrap_argv_for_user(["rm", "-f", file_path], runtime_user, cwd=os.path.dirname(file_path) or None)
|
|
159
|
+
subprocess.run(
|
|
160
|
+
argv,
|
|
161
|
+
cwd=os.path.dirname(file_path) or None,
|
|
162
|
+
check=True,
|
|
163
|
+
capture_output=True,
|
|
164
|
+
text=True,
|
|
165
|
+
)
|
|
141
166
|
|
|
142
167
|
def reinitialize(self):
|
|
143
168
|
"""Reinitialize git repo detection (useful when .git directory is created after initialization)."""
|
|
@@ -992,10 +1017,10 @@ class GitManager:
|
|
|
992
1017
|
if self._is_submodule(file_path):
|
|
993
1018
|
logger.info("Detected submodule, using git add command directly: %s", rel_path)
|
|
994
1019
|
# For submodules, use git add directly to stage only the submodule reference
|
|
995
|
-
self.
|
|
1020
|
+
self._run_git_write(["add", rel_path])
|
|
996
1021
|
else:
|
|
997
1022
|
# Use git add -A on the specific file to handle deletions as well
|
|
998
|
-
self.
|
|
1023
|
+
self._run_git_write(["add", "-A", "--", rel_path])
|
|
999
1024
|
|
|
1000
1025
|
logger.info("Successfully staged file: %s", rel_path)
|
|
1001
1026
|
return True
|
|
@@ -1017,7 +1042,7 @@ class GitManager:
|
|
|
1017
1042
|
if self._is_submodule(file_path):
|
|
1018
1043
|
logger.info("Detected submodule, using git restore for unstaging: %s", rel_path)
|
|
1019
1044
|
# For submodules, always use git restore --staged (works with submodules)
|
|
1020
|
-
self.
|
|
1045
|
+
self._run_git_write(["restore", "--staged", rel_path])
|
|
1021
1046
|
else:
|
|
1022
1047
|
# Check if repository has any commits (HEAD exists)
|
|
1023
1048
|
try:
|
|
@@ -1028,10 +1053,10 @@ class GitManager:
|
|
|
1028
1053
|
|
|
1029
1054
|
if has_head:
|
|
1030
1055
|
# Reset the file from HEAD (unstage) - for repos with commits
|
|
1031
|
-
self.
|
|
1056
|
+
self._run_git_write(["restore", "--staged", rel_path])
|
|
1032
1057
|
else:
|
|
1033
1058
|
# For repositories with no commits, use git rm --cached to unstage
|
|
1034
|
-
self.
|
|
1059
|
+
self._run_git_write(["rm", "--cached", rel_path])
|
|
1035
1060
|
|
|
1036
1061
|
logger.info("Successfully unstaged file: %s", rel_path)
|
|
1037
1062
|
return True
|
|
@@ -1058,13 +1083,13 @@ class GitManager:
|
|
|
1058
1083
|
|
|
1059
1084
|
if has_head:
|
|
1060
1085
|
# Restore both index and working tree from HEAD
|
|
1061
|
-
self.
|
|
1086
|
+
self._run_git_write(["restore", "--staged", "--worktree", "--", rel_path])
|
|
1062
1087
|
logger.info("Successfully reverted file: %s", rel_path)
|
|
1063
1088
|
else:
|
|
1064
1089
|
# For repositories with no commits, we can't revert to HEAD
|
|
1065
1090
|
# Instead, just remove the file to "revert" it to non-existence
|
|
1066
1091
|
if os.path.exists(file_path):
|
|
1067
|
-
|
|
1092
|
+
self._remove_file_as_runtime_user(file_path)
|
|
1068
1093
|
logger.info("Successfully removed file (no HEAD to revert to): %s", rel_path)
|
|
1069
1094
|
else:
|
|
1070
1095
|
logger.info("File already does not exist (no HEAD to revert to): %s", rel_path)
|
|
@@ -1100,12 +1125,12 @@ class GitManager:
|
|
|
1100
1125
|
if submodule_paths:
|
|
1101
1126
|
logger.info("Staging submodules using git add directly: %s", submodule_paths)
|
|
1102
1127
|
for submodule_path in submodule_paths:
|
|
1103
|
-
self.
|
|
1128
|
+
self._run_git_write(["add", submodule_path])
|
|
1104
1129
|
|
|
1105
1130
|
# Stage regular files using git add -A to capture deletions
|
|
1106
1131
|
if rel_paths:
|
|
1107
1132
|
logger.info("Staging regular files: %s", rel_paths)
|
|
1108
|
-
self.
|
|
1133
|
+
self._run_git_write(["add", "-A", "--", *rel_paths])
|
|
1109
1134
|
|
|
1110
1135
|
logger.info("Successfully staged %d files (%d submodules, %d regular)",
|
|
1111
1136
|
len(file_paths), len(submodule_paths), len(rel_paths))
|
|
@@ -1149,11 +1174,11 @@ class GitManager:
|
|
|
1149
1174
|
if has_head:
|
|
1150
1175
|
# Use git restore --staged for all files (works for both regular files and submodules)
|
|
1151
1176
|
if all_rel_paths:
|
|
1152
|
-
self.
|
|
1177
|
+
self._run_git_write(["restore", "--staged", *all_rel_paths])
|
|
1153
1178
|
else:
|
|
1154
1179
|
# For repositories with no commits, use git rm --cached
|
|
1155
1180
|
if all_rel_paths:
|
|
1156
|
-
self.
|
|
1181
|
+
self._run_git_write(["rm", "--cached", *all_rel_paths])
|
|
1157
1182
|
|
|
1158
1183
|
logger.info("Successfully unstaged %d files (%d submodules, %d regular)",
|
|
1159
1184
|
len(file_paths), len(submodule_paths), len(rel_paths))
|
|
@@ -1190,14 +1215,14 @@ class GitManager:
|
|
|
1190
1215
|
regular_files.append(rel_paths[i])
|
|
1191
1216
|
|
|
1192
1217
|
if regular_files:
|
|
1193
|
-
self.
|
|
1218
|
+
self._run_git_write(["restore", "--staged", "--worktree", "--", *regular_files])
|
|
1194
1219
|
logger.info("Successfully reverted %d files", len(regular_files))
|
|
1195
1220
|
else:
|
|
1196
1221
|
# For repositories with no commits, remove files to "revert" them
|
|
1197
1222
|
removed_count = 0
|
|
1198
1223
|
for file_path in file_paths:
|
|
1199
1224
|
if not self._is_submodule(file_path) and os.path.exists(file_path):
|
|
1200
|
-
|
|
1225
|
+
self._remove_file_as_runtime_user(file_path)
|
|
1201
1226
|
removed_count += 1
|
|
1202
1227
|
logger.info("Successfully removed %d files (no HEAD to revert to)", removed_count)
|
|
1203
1228
|
|
|
@@ -1214,7 +1239,7 @@ class GitManager:
|
|
|
1214
1239
|
|
|
1215
1240
|
try:
|
|
1216
1241
|
# Use git add . to stage everything - this is the most efficient way
|
|
1217
|
-
self.
|
|
1242
|
+
self._run_git_write(["add", "."])
|
|
1218
1243
|
logger.info("Successfully staged all changes using 'git add .'")
|
|
1219
1244
|
return True
|
|
1220
1245
|
|
|
@@ -1237,10 +1262,10 @@ class GitManager:
|
|
|
1237
1262
|
|
|
1238
1263
|
if has_head:
|
|
1239
1264
|
# Use git restore --staged . to unstage everything
|
|
1240
|
-
self.
|
|
1265
|
+
self._run_git_write(["restore", "--staged", "."])
|
|
1241
1266
|
else:
|
|
1242
1267
|
# For repositories with no commits, remove everything from index
|
|
1243
|
-
self.
|
|
1268
|
+
self._run_git_write(["rm", "--cached", "-r", "."])
|
|
1244
1269
|
|
|
1245
1270
|
logger.info("Successfully unstaged all changes")
|
|
1246
1271
|
return True
|
|
@@ -1264,7 +1289,7 @@ class GitManager:
|
|
|
1264
1289
|
|
|
1265
1290
|
if has_head:
|
|
1266
1291
|
# Use git restore . to revert all working directory changes
|
|
1267
|
-
self.
|
|
1292
|
+
self._run_git_write(["restore", "."])
|
|
1268
1293
|
logger.info("Successfully reverted all working directory changes")
|
|
1269
1294
|
else:
|
|
1270
1295
|
logger.warning("Cannot revert changes in repository with no commits")
|
|
@@ -1308,7 +1333,8 @@ class GitManager:
|
|
|
1308
1333
|
raise RuntimeError("No staged changes to commit")
|
|
1309
1334
|
|
|
1310
1335
|
# Perform the commit
|
|
1311
|
-
commit
|
|
1336
|
+
self._run_git_write(["commit", "-m", message.strip()])
|
|
1337
|
+
commit = self.repo.head.commit
|
|
1312
1338
|
logger.info("Successfully committed changes with hash: %s", commit.hexsha)
|
|
1313
1339
|
logger.info("Commit message: %s", message.strip())
|
|
1314
1340
|
|
|
@@ -74,6 +74,7 @@ from .handlers.project_aware_file_handlers import (
|
|
|
74
74
|
ProjectAwareFileCreateHandler,
|
|
75
75
|
ProjectAwareFolderCreateHandler,
|
|
76
76
|
)
|
|
77
|
+
from .handlers.file_transfer_handlers import FileUploadHandler, FileDownloadHandler
|
|
77
78
|
from .handlers.session import SessionManager
|
|
78
79
|
from .webmin_proxy_config import apply_turnkey_webmin_proxy_config
|
|
79
80
|
from portacode.tunneling.privileged import read_text, run, write_text
|
|
@@ -512,6 +513,8 @@ class TerminalManager:
|
|
|
512
513
|
self._command_registry.register(ProjectAwareFileCreateHandler) # Use project-aware version
|
|
513
514
|
self._command_registry.register(ProjectAwareFolderCreateHandler) # Use project-aware version
|
|
514
515
|
self._command_registry.register(FileRenameHandler)
|
|
516
|
+
self._command_registry.register(FileUploadHandler)
|
|
517
|
+
self._command_registry.register(FileDownloadHandler)
|
|
515
518
|
self._command_registry.register(FileSearchHandler)
|
|
516
519
|
self._command_registry.register(ContentRequestHandler)
|
|
517
520
|
self._command_registry.register(FileApplyDiffHandler)
|
|
@@ -310,6 +310,7 @@ portacode/connection/handlers/cloudflare_forwarding.py
|
|
|
310
310
|
portacode/connection/handlers/cloudflare_tunnel.py
|
|
311
311
|
portacode/connection/handlers/diff_handlers.py
|
|
312
312
|
portacode/connection/handlers/file_handlers.py
|
|
313
|
+
portacode/connection/handlers/file_transfer_handlers.py
|
|
313
314
|
portacode/connection/handlers/project_aware_file_handlers.py
|
|
314
315
|
portacode/connection/handlers/project_state_handlers.py
|
|
315
316
|
portacode/connection/handlers/proxmox_infra.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{portacode-1.5.6.dev1 → portacode-1.5.6.dev3}/docs/cloudflared-domain-connect-containers-audit.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|