Skip to content

new architecture #8453

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 276 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
276 commits
Select commit Hold shift + click to select a range
f3e4043
support EventIterator overflow options (like node fs watch); add abil…
williamstein Jul 19, 2025
0c48df6
more fs.watch unit tests
williamstein Jul 19, 2025
41c3cd4
add fs watch core
williamstein Jul 19, 2025
dd29234
conat rpc fs.watch implemented and working here
williamstein Jul 19, 2025
99656fd
broken work in progress creating a more generic and unit testable syn…
williamstein Jul 19, 2025
346b9ef
sync-doc: integrating with conat
williamstein Jul 19, 2025
ec86176
sync-doc conat: minor refactoring
williamstein Jul 19, 2025
366ca14
make SyncString available from conat core client
williamstein Jul 19, 2025
205f14d
conat sync/fileserver: integrate with hub
williamstein Jul 19, 2025
67a3d1d
conat sync-doc: make sync.string not async to match existing api usage
williamstein Jul 19, 2025
088dbab
syncdb: implement similar to syncstring
williamstein Jul 20, 2025
1304de4
syncdb: implement similar to syncstring
williamstein Jul 20, 2025
65208e2
Merge branch 'fs2' of github.com:sagemathinc/cocalc into fs2
williamstein Jul 20, 2025
592915f
fix some depcheck issues
williamstein Jul 20, 2025
f188580
fix circular ref
williamstein Jul 20, 2025
2476674
fix a test now that I made EventIterator work much better
williamstein Jul 20, 2025
3eaf091
writing some sync-doc tests
williamstein Jul 20, 2025
ad13e3b
write some merge conflict related tests
williamstein Jul 20, 2025
0ce82c7
sync-doc: tests using noAutosave
williamstein Jul 20, 2025
69ea3a1
improve runoo
williamstein Jul 20, 2025
c17234b
syncdoc: unit test involving merging many heads
williamstein Jul 20, 2025
8da8ef5
sync-doc: make the "read from disk" command "readFile" and be public;…
williamstein Jul 20, 2025
681e2a2
sync-doc: first steps toward client-only fs listener
williamstein Jul 20, 2025
f804b01
sync-doc: working on multiple clients efficiently watching for fs cha…
williamstein Jul 20, 2025
e64eee3
sync-doc: implement a pretty nice approach to filesystem watching for…
williamstein Jul 20, 2025
c4c9632
syncdoc: working but hacky approach to saving to disk without causing…
williamstein Jul 21, 2025
6b52a5a
file watch ignore when saving -- more ts friendly implementation
williamstein Jul 21, 2025
e39cd45
...
williamstein Jul 21, 2025
87fb723
sync-doc: implement extremely simple version of "has unsaved changes"…
williamstein Jul 21, 2025
5bfffcb
Merge branch 'master' into fs2
williamstein Jul 21, 2025
d79705e
Merge branch 'master' into fs2
williamstein Jul 21, 2025
611ee19
rewrite code formatting to not use backend state or service -- just a…
williamstein Jul 21, 2025
dd94501
delete all the syncstring-based formatter code (just format strings);…
williamstein Jul 22, 2025
fee5a14
surpress an antd react19 warning
williamstein Jul 22, 2025
5814146
remove old formatter; implement file delete
williamstein Jul 22, 2025
476e9c3
fix building latex on save
williamstein Jul 22, 2025
dffe85e
sync: eliminate non-conate syncdb and syncstring usage in the frontend
williamstein Jul 22, 2025
91b79d3
sync-doc: add unit test of file deletion
williamstein Jul 22, 2025
eac0e2f
fix broken test and some ts
williamstein Jul 22, 2025
0120c3e
sync-doc: improving behavior based on unit testing
williamstein Jul 22, 2025
156bef6
syncdoc: a little bit of org and opt; frontend -- delay spinners and …
williamstein Jul 22, 2025
c78bc62
preload background file tabs
williamstein Jul 22, 2025
687f713
syncdoc -- delete the old approach and embrace this.fs
williamstein Jul 22, 2025
1dc407e
add find command to fs api
williamstein Jul 22, 2025
c438282
use reuseInFlight instead of 1000's of once listeners at once.
williamstein Jul 22, 2025
80224e9
fs sandbox: support for readonly and unsafe; ability to find files ma…
williamstein Jul 23, 2025
06ddce7
update file-server to not use fs.ls
williamstein Jul 23, 2025
c32f469
fix the packages/sync tests
williamstein Jul 23, 2025
17077cf
implement core of new listings
williamstein Jul 23, 2025
7fbde56
timetravel -- implement opening timetravel doc in a much more straigh…
williamstein Jul 23, 2025
a5e6784
Merge branch 'master' into fs2
williamstein Jul 23, 2025
b011fdf
file opening in frontend -- fix leak I had just caused by opening bac…
williamstein Jul 23, 2025
3bd88b8
github ci: fix test failing due to missing yapf
williamstein Jul 23, 2025
cabf024
create a new frontend integration test package and one tiny little te…
williamstein Jul 23, 2025
8a22639
test: actually unit testing the useFiles hook
williamstein Jul 23, 2025
db04858
add basic test of use-listing
williamstein Jul 23, 2025
73b7080
unit tests of use-listing that involve sorting
williamstein Jul 23, 2025
7b3c4dd
frontend listings: first pass at using the new fs interface and hooks…
williamstein Jul 23, 2025
5bdfca9
remove some not-necessary default styling; increase react virtuoso de…
williamstein Jul 23, 2025
247a6a0
show file creation buttons even if you don't search (hsy suggested th…
williamstein Jul 23, 2025
64a569d
Merge branch 'master' into fs2
williamstein Jul 23, 2025
4c41caa
fix package.json issue
williamstein Jul 23, 2025
95c7054
fix depcheck issue with new test package
williamstein Jul 23, 2025
d332bb6
refactor code for filtering the listing
williamstein Jul 24, 2025
a7987bd
ripping out the old listings related code and rewriting/replacing it …
williamstein Jul 24, 2025
bf6f182
trivial
williamstein Jul 24, 2025
fcfe0b6
Merge branch 'master' into fs2
williamstein Jul 26, 2025
e3a31bd
conat fs.readdir -- implement options
williamstein Jul 26, 2025
f039e0d
add test of non-utf8 Buffer readdir
williamstein Jul 26, 2025
e6b1f6b
change mtime for listings, etc., to be in ms
williamstein Jul 26, 2025
256affd
filesystem rewrite frontend integration progress
williamstein Jul 26, 2025
c52224b
rewrite flyout panel directory listing to use new fs api.
williamstein Jul 26, 2025
6812a26
update guide and fix some major bugs/issues
williamstein Jul 26, 2025
4b36fa9
switch terminal to be ephemeral by default
williamstein Jul 26, 2025
39ed974
no need to alert about opening the target of a symlink
williamstein Jul 26, 2025
d36bb97
fix a case where I guess trying to edit a readonly sagews would crash…
williamstein Jul 26, 2025
3ec160a
jupyter: first steps on getting notebooks to start running just using…
williamstein Jul 27, 2025
986f664
wire up proof of concept to show we can do code evaluation in the pin…
williamstein Jul 27, 2025
80e70f4
sometimes err is a string so we can't do err.message in that case
williamstein Jul 27, 2025
bef4fff
add better typing to the jupyter output handler
williamstein Jul 27, 2025
1ccb099
jupyter: faster execution proof of concept
williamstein Jul 27, 2025
979b272
conat: basic framework for running jupyter code
williamstein Jul 27, 2025
4f6bb41
conat jupyter code runner: streaming output now working for one cell
williamstein Jul 27, 2025
16b7994
depcheck fix
williamstein Jul 27, 2025
e02db38
ts
williamstein Jul 27, 2025
a43db52
jupyter eval: organizing code; removing flicker
williamstein Jul 27, 2025
55d012b
jupyter: evaluation when client vanishes (with one cell) is working
williamstein Jul 27, 2025
61a82f1
jupyter run: add unit test for "client closes connection"
williamstein Jul 27, 2025
235d983
jupyter cell runner: handle multiple input cells
williamstein Jul 27, 2025
8a5911b
ensure cells run in order
williamstein Jul 27, 2025
e6fc717
jupyter eval: support noHalt
williamstein Jul 27, 2025
3ca8aa9
jupyter runner: include the kernel
williamstein Jul 27, 2025
198f0e2
jupyter run: record last evaluation time
williamstein Jul 27, 2025
d908e26
jupyter run: queuing up cells to run
williamstein Jul 28, 2025
a95ed82
delete jupyter exec_state sync, since it's no longer possible
williamstein Jul 28, 2025
65ffcb0
jupyter: fix opening timetravel
williamstein Jul 28, 2025
0afbd27
disabling/deleting a lot of jupyter backend code that will no longer …
williamstein Jul 28, 2025
9924e93
ts
williamstein Jul 28, 2025
b4f0605
jupyter run: run all cells and also deleting old code
williamstein Jul 28, 2025
858f519
jupyter run -- starting to work on processing output
williamstein Jul 28, 2025
5c3c56d
starting to work on handling case when project is restarted
williamstein Jul 28, 2025
938c4a9
Merge branch 'master' into fs2
williamstein Jul 28, 2025
8772f9f
reimplement cursor navigation of explorer listing
williamstein Jul 28, 2025
65b372a
add non-hidden first subdir caching
williamstein Jul 28, 2025
5532460
directory caching -- take 2
williamstein Jul 28, 2025
d2acbe1
work in progress converting the explorer component to a functional co…
williamstein Jul 29, 2025
397dde1
move explorer keyboard handling to the explorer itself
williamstein Jul 29, 2025
ecc14de
explorer: support [*]-up arrow to move to parent directory
williamstein Jul 29, 2025
145ce9a
rewrite file explorer to be a functional component
williamstein Jul 29, 2025
489eaf1
fix bugs in new file listings
williamstein Jul 29, 2025
adf444f
files: select a range of files
williamstein Jul 29, 2025
57934c7
refactor explorer listings so that action bar works again
williamstein Jul 29, 2025
df6f9db
fix crash in socket reconnect after close
williamstein Jul 29, 2025
ecc2f49
action bar -- show even if project is not running
williamstein Jul 29, 2025
b297394
ts
williamstein Jul 29, 2025
cc5f65c
typo
williamstein Jul 30, 2025
62ab5b0
Merge branch 'master' into fs2
williamstein Jul 30, 2025
47699d8
sync: fix hash_of_saved_version
williamstein Jul 30, 2025
8752002
sync: missing save-to-disk event
williamstein Jul 30, 2025
b8eb20c
sync: reimplement read-write versus read-only handling
williamstein Jul 30, 2025
3520607
copy between projects -- hide activity indicator when done
williamstein Jul 30, 2025
52e796c
Merge branch 'master' into fs2
williamstein Jul 30, 2025
78ed491
state issue with listing
williamstein Jul 30, 2025
a12ea7c
focus explorer filter on directory change
williamstein Jul 30, 2025
850ce5d
masked files -- make that work again
williamstein Jul 30, 2025
631502c
fix little bug I just introduced in SearchInput
williamstein Jul 30, 2025
ecdf992
get rid of file mask toggle button for full page file explorer since …
williamstein Jul 30, 2025
0e420a5
isdir --> isDir; isopen --> isOpen, etc. -- consistent naming. Also…
williamstein Jul 30, 2025
322fad2
mainly fixing publish state view and editing
williamstein Jul 30, 2025
1f04e77
fix isActive and isOpen for file listings to get updated; also make i…
williamstein Jul 31, 2025
da8971f
fix a test
williamstein Jul 31, 2025
0e23bab
change tests for how we changed hash of saved version and is read only
williamstein Jul 31, 2025
102cae0
remove the entire open-files implementation, front to back
williamstein Jul 31, 2025
192627a
jupyter: when evaluating a cell don't have the input get reset as new…
williamstein Jul 31, 2025
22c35e3
surprise subtle improvement to EventIterator
williamstein Jul 31, 2025
c22f8d4
jupyter run -- handle tcp buffer issue
williamstein Jul 31, 2025
14fc7f8
jupyter run -- buffer the jupyter output messages
williamstein Jul 31, 2025
af4137f
Merge branch 'master' into fs2
williamstein Jul 31, 2025
f18e917
mainly fix using File --> Duplicate, etc.; did this by being more car…
williamstein Aug 1, 2025
feab900
starting work on new jupyter save approach
williamstein Aug 1, 2025
f69640b
sync-doc -- bigger ignore on save interval
williamstein Aug 1, 2025
9e779c0
jupyter: starting moving things more to the frontend -- this mainly d…
williamstein Aug 1, 2025
84077c3
delete the old project actions entirely -- starting from scratch with…
williamstein Aug 1, 2025
7cca2c1
refactor: move the jupyter functionality from project api.editor to n…
williamstein Aug 1, 2025
d3c1d2d
jupyter: rewriting to move more control/state to frontend
williamstein Aug 1, 2025
9dc1899
frontend terminal -- noticed some cases where it might try to do some…
williamstein Aug 2, 2025
73a9e31
jupyter: fix situation where errors during execution not properly rep…
williamstein Aug 2, 2025
3f02995
jupyter: tab completion
williamstein Aug 2, 2025
9e7e214
add jupyter api getConnectionFile and use that instead of redux/sync
williamstein Aug 2, 2025
ca84275
jupyter: ensure positions are unique
williamstein Aug 2, 2025
ccc1c25
file explorer -- fix bug when hitting enter in action box
williamstein Aug 2, 2025
bcc4925
remove debug messages
williamstein Aug 2, 2025
2f8f7f0
add ripgrep support to the fs module (not used by frontend yet)
williamstein Aug 2, 2025
ec056d8
ripgrep: automate installing it properly (not using the vscode version)
williamstein Aug 2, 2025
bbd52a0
update better-sqlite3 and zstd-napi
williamstein Aug 2, 2025
144f647
ripgrep: whitelist searching binary files
williamstein Aug 2, 2025
79dcc3c
files sandbox: create generic exec command for running command with v…
williamstein Aug 2, 2025
284f91d
automate install of fd and ripgrep in a more robust way
williamstein Aug 3, 2025
348f005
refactor search action function -- first step before rewriting it to …
williamstein Aug 3, 2025
5cbff75
add dust -- still need to add whitelisted commands...
williamstein Aug 3, 2025
7283c13
add dust whitelist and test
williamstein Aug 3, 2025
17fa2ca
no longer using vscode/ripgrep
williamstein Aug 3, 2025
61eda29
update find unit test
williamstein Aug 3, 2025
e1fc9f9
unsafe proof of concept rustic integration
williamstein Aug 3, 2025
b237f85
working on rustic whitelist options
williamstein Aug 4, 2025
e99b4fb
finished rustic whitelisting
williamstein Aug 4, 2025
dde1d5c
add a test of rustic
williamstein Aug 4, 2025
a999dcf
search -- switch to using fs ripgrep, first version
williamstein Aug 4, 2025
c60a511
search: make consistent with flyout; use virtuoso so displaying a lar…
williamstein Aug 4, 2025
96c1ad4
add archiver to sandbox for easily making zip/tar files.
williamstein Aug 5, 2025
4f788e4
ouch -- rust based compression
williamstein Aug 5, 2025
606a597
remove archiver integration completely -- it's just not fast enough t…
williamstein Aug 5, 2025
31b040a
ability to compress directory using new fs api
williamstein Aug 5, 2025
7eafe94
ouch: add some missing options
williamstein Aug 5, 2025
2036af7
compress -- allow user to select format
williamstein Aug 5, 2025
21cdb2f
switch to ouch for multi-file download
williamstein Aug 5, 2025
4f67be8
add nsjail support to sandbox exec
williamstein Aug 5, 2025
9e200b2
automate installation of nsjail
williamstein Aug 5, 2025
e7ac861
add proof-of-concept nsjail support to terminal
williamstein Aug 6, 2025
0b8e77d
fix issue with nsjail terminal proof of concept
williamstein Aug 6, 2025
fe703c2
make nsjail terminal POC work on aarch64
williamstein Aug 6, 2025
e37aec1
proof of concept using nsjail for projects in single user mode
williamstein Aug 6, 2025
5c5f6a6
no longer using archiver -- it's faster to shell and use "ouch"
williamstein Aug 6, 2025
78cd60c
add basic project control server skeleton
williamstein Aug 6, 2025
b37e73e
work in progress on new approach to running projects
williamstein Aug 6, 2025
ee2d8be
implement a load balancer that is in front of the project runner
williamstein Aug 6, 2025
6226ca2
project runner: implement shared state and basic load balancing
williamstein Aug 7, 2025
059e357
runner -- same one only if not opened
williamstein Aug 7, 2025
da494da
working on project run server code
williamstein Aug 7, 2025
fe3877a
starting to clean up the proof of concept nsjail launcher code for pr…
williamstein Aug 7, 2025
423da5f
HOME=/home/user in general
williamstein Aug 7, 2025
fb4080c
update project state when switching to the tab
williamstein Aug 7, 2025
1b46f52
project runner -- more unit tests; add ability to run project in admi…
williamstein Aug 7, 2025
5c95f54
ts in new tests
williamstein Aug 7, 2025
126a45f
use proper path to pnpm
williamstein Aug 7, 2025
56efcdb
delete the old project start/stop code
williamstein Aug 7, 2025
20c199f
log the project's output -- may be way too much; we'll see
williamstein Aug 7, 2025
f457275
project runner -- adapting to multiuser setup
williamstein Aug 7, 2025
8d52311
make it possible to build/install nsjail (part of cocalc) without sudo
williamstein Aug 7, 2025
f3561f0
project runner -- fully running with jails *inside* a jail! this wor…
williamstein Aug 7, 2025
a132d1e
no longer need 'which'
williamstein Aug 8, 2025
1388d14
project runner -- add limits
williamstein Aug 8, 2025
526c61f
project runner -- tweaking params
williamstein Aug 8, 2025
4bdf294
attempt a completely different approach to admin user
williamstein Aug 8, 2025
793d12a
put in some default limits at least using rlimit unit we figure out c…
williamstein Aug 8, 2025
23aabb6
project runner -- new attempt to make an admin mode
williamstein Aug 8, 2025
eaf1968
fix depcheck issue
williamstein Aug 8, 2025
b91864f
Merge branch 'master' into fs2
williamstein Aug 8, 2025
9ec1495
revert to "stupid" complete terminal reset
williamstein Aug 8, 2025
a42038e
include node path when launching project
williamstein Aug 8, 2025
9805077
make build failure of nsjail non-fatal (since it isn't needed for uni…
williamstein Aug 8, 2025
3cc7553
fix handling of "no such directory" for file explorer
williamstein Aug 8, 2025
e0359be
comment out the test reporting from github actions
williamstein Aug 8, 2025
fc8c4f5
better handle opening a project you are not a collab on
williamstein Aug 8, 2025
2735f56
make runner work on more configurations
williamstein Aug 8, 2025
210f755
Merge branch 'fs2' of github.com:sagemathinc/cocalc into fs2
williamstein Aug 8, 2025
f66e857
jupyter; when changing kernel, restart it
williamstein Aug 8, 2025
e446b23
minimally usable reimplementation of jupyter raw input with new archi…
williamstein Aug 8, 2025
1f79a32
make stdin optional
williamstein Aug 9, 2025
57997ff
finished undoing something
williamstein Aug 9, 2025
30cc19a
juptyer raw input: fix interaction with keyboard handler
williamstein Aug 9, 2025
cbd7fe3
jupyter: interrupt -- make it clear run state *and* also interrupt on…
williamstein Aug 9, 2025
78e2480
jupyter: process output to remove large data (so not stored in syncdb…
williamstein Aug 9, 2025
e43e0f5
jupyter: reimplement handling processing of images/large data
williamstein Aug 9, 2025
a63c7cb
fix some keyboard handling issues with flyout versus explorer
williamstein Aug 9, 2025
aa4fe03
don't suggest to create directory if the error is something else
williamstein Aug 9, 2025
6f3a52f
error if uploading blob fails
williamstein Aug 9, 2025
4277352
project search -- explicit regexp toggle
williamstein Aug 9, 2025
41bed2f
turn off markdown for ripgrep error
williamstein Aug 9, 2025
9bfeb16
fix issue with jupyter import that broke next build
williamstein Aug 9, 2025
6c6d7f3
starting to create conat-service to use btrfs code
williamstein Aug 10, 2025
76ee046
dev mode using new btrfs fileserver
williamstein Aug 10, 2025
d010f83
add quota to fileserver api; rewrite delete file to use sandbox fs
williamstein Aug 10, 2025
b9b40ae
revert horrible use of resize observer to do something that only shou…
williamstein Aug 10, 2025
8b80e8c
add move from fs-extra and use it to implement frontend move using th…
williamstein Aug 10, 2025
732591c
rewrite frontend copy (not tested much yet)
williamstein Aug 10, 2025
15a7d1b
actually use reflink with cp exec
williamstein Aug 10, 2025
7a6754a
add more logging to project status request
williamstein Aug 10, 2025
6e28c6e
implement file-server cp for copying *between* projects very efficiently
williamstein Aug 10, 2025
72240ac
broken work in progress rewriting copy path between projects for fron…
williamstein Aug 10, 2025
f29fff3
Merge branch 'master' into fs2
williamstein Aug 10, 2025
0abd3ac
copy projects between paths -- all the backend stuff may work (need t…
williamstein Aug 10, 2025
c24596d
rewrite all non-course use of copying files between projects
williamstein Aug 10, 2025
7da179a
update course functionality to use new copy-between-projects
williamstein Aug 10, 2025
a74bda0
fix project entry made for copying files
williamstein Aug 10, 2025
fed5451
rewrite how excluding files works for courses
williamstein Aug 10, 2025
e3426d6
add clone function to file server
williamstein Aug 10, 2025
18d0b42
api support for cloning a project
williamstein Aug 10, 2025
5b9122c
add fork button
williamstein Aug 10, 2025
e0ac383
file-server -- start adding rustic support
williamstein Aug 11, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
54 changes: 25 additions & 29 deletions .github/workflows/make-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
detached: true
- uses: actions/checkout@v4
- name: Install python3 requests
run: sudo apt-get install python3-requests
run: sudo apt-get install python3-requests python3-yapf
- name: Check doc links
run: cd src/scripts && python3 check_doc_urls.py || sleep 5 || python3 check_doc_urls.py

Expand Down Expand Up @@ -91,19 +91,15 @@ jobs:
# cache: "pnpm"
# cache-dependency-path: "src/packages/pnpm-lock.yaml"

- name: Download and install Valkey
run: |
VALKEY_VERSION=8.1.2
curl -LOq https://download.valkey.io/releases/valkey-${VALKEY_VERSION}-jammy-x86_64.tar.gz
tar -xzf valkey-${VALKEY_VERSION}-jammy-x86_64.tar.gz
sudo cp valkey-${VALKEY_VERSION}-jammy-x86_64/bin/valkey-server /usr/local/bin/
- name: Install btrfs-progs and bup for @cocalc/file-server
run: sudo apt-get update && sudo apt-get install -y btrfs-progs bup

- name: Set up Python venv and Jupyter kernel
run: |
python3 -m pip install --upgrade pip virtualenv
python3 -m virtualenv venv
source venv/bin/activate
pip install ipykernel
pip install ipykernel yapf
python -m ipykernel install --prefix=./jupyter-local --name python3-local --display-name "Python 3 (Local)"


Expand All @@ -128,30 +124,30 @@ jobs:
name: "test-results-node-${{ matrix.node-version }}-pg-${{ matrix.pg-version }}"
path: 'src/packages/*/junit.xml'

report:
runs-on: ubuntu-latest
# report:
# runs-on: ubuntu-latest

needs: [test]
# needs: [test]

if: ${{ !cancelled() }}
# if: ${{ !cancelled() }}

steps:
- name: Checkout code
uses: actions/checkout@v4
# steps:
# - name: Checkout code
# uses: actions/checkout@v4

- name: Download all test artifacts
uses: actions/download-artifact@v4
with:
pattern: "test-results-*"
merge-multiple: true
path: test-results/
# - name: Download all test artifacts
# uses: actions/download-artifact@v4
# with:
# pattern: "test-results-*"
# merge-multiple: true
# path: test-results/

- name: Test Report
uses: dorny/test-reporter@v2
with:
name: CoCalc Jest Tests
path: 'test-results/**/junit.xml'
reporter: jest-junit
use-actions-summary: 'true'
fail-on-error: false
# - name: Test Report
# uses: dorny/test-reporter@v2
# with:
# name: CoCalc Jest Tests
# path: 'test-results/**/junit.xml'
# reporter: jest-junit
# use-actions-summary: 'true'
# fail-on-error: false

2 changes: 1 addition & 1 deletion src/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"version-check": "pip3 install typing_extensions mypy || pip3 install --break-system-packages typing_extensions mypy && ./workspaces.py version-check && mypy scripts/check_npm_packages.py",
"test-parallel": "unset DEBUG && pnpm run version-check && cd packages && pnpm run -r --parallel test",
"test": "unset DEBUG && pnpm run depcheck && pnpm run version-check && ./workspaces.py test",
"test-github-ci": "unset DEBUG && pnpm run depcheck && pnpm run version-check && ./workspaces.py test --exclude=jupyter,file-server --retries=1",
"test-github-ci": "unset DEBUG && pnpm run depcheck && pnpm run version-check && ./workspaces.py test --test-github-ci --exclude=jupyter --retries=1",
"depcheck": "cd packages && pnpm run -r --parallel depcheck",
"prettier-all": "cd packages/",
"local-ci": "./scripts/ci.sh",
Expand Down
59 changes: 59 additions & 0 deletions src/packages/backend/conat/files/local-path.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { fsServer, DEFAULT_FILE_SERVICE } from "@cocalc/conat/files/fs";
import { SandboxedFilesystem } from "@cocalc/backend/sandbox";
import { isValidUUID } from "@cocalc/util/misc";
import { type Client } from "@cocalc/conat/core/client";
import { conat } from "@cocalc/backend/conat/conat";
import { client as createFileClient } from "@cocalc/conat/files/file-server";

export async function localPathFileserver({
path,
service = DEFAULT_FILE_SERVICE,
client,
project_id,
unsafeMode,
}: {
service?: string;
client?: Client;
// if project_id is specified, use single project mode.
project_id?: string;
// only used in single project mode
path?: string;
unsafeMode?: boolean;
} = {}) {
client ??= conat();

const server = await fsServer({
service,
client,
project_id,
fs: async (subject: string) => {
if (project_id) {
if (path == null) {
throw Error("path must be specified");
}
return new SandboxedFilesystem(path, { unsafeMode });
} else {
const project_id = getProjectId(subject);
const fsclient = createFileClient({ client });
const { path } = await fsclient.mount({ project_id });
return new SandboxedFilesystem(path, { unsafeMode, host: project_id });
}
},
});
return { server, client, path, service, close: () => server.close() };
}

function getProjectId(subject: string) {
const v = subject.split(".");
if (v.length != 2) {
throw Error("subject must have 2 segments");
}
if (!v[1].startsWith("project-")) {
throw Error("second segment of subject must start with 'project-'");
}
const project_id = v[1].slice("project-".length);
if (!isValidUUID(project_id)) {
throw Error("not a valid project id");
}
return project_id;
}
93 changes: 93 additions & 0 deletions src/packages/backend/conat/files/test/listing.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { SandboxedFilesystem } from "@cocalc/backend/sandbox";
import { mkdtemp, rm } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "path";
import { randomId } from "@cocalc/conat/names";
import listing from "@cocalc/conat/files/listing";

let tmp;
beforeAll(async () => {
tmp = await mkdtemp(join(tmpdir(), `cocalc-${randomId()}0`));
});

afterAll(async () => {
try {
await rm(tmp, { force: true, recursive: true });
} catch {}
});

describe("creating a listing monitor starting with an empty directory", () => {
let fs, dir;
it("creates sandboxed filesystem", async () => {
fs = new SandboxedFilesystem(tmp);
dir = await listing({ path: "", fs });
});

it("initial listing is empty", () => {
expect(Object.keys(dir.files)).toEqual([]);
});

let iter;
it("create a file and get an update", async () => {
iter = dir.iter();
await fs.writeFile("a.txt", "hello");
let { value } = await iter.next();
expect(value).toEqual({
mtime: value.mtime,
name: "a.txt",
size: value.size,
});
// it's possible that the file isn't written completely above.
if (value.size != 5) {
({ value } = await iter.next());
}
const stat = await fs.stat("a.txt");
expect(stat.mtimeMs).toEqual(value.mtime);
expect(dir.files["a.txt"]).toEqual({ mtime: value.mtime, size: 5 });
});

it("modify the file and get two updates -- one when it starts and another when done", async () => {
await fs.appendFile("a.txt", " there");
const { value } = await iter.next();
expect(value).toEqual({ mtime: value.mtime, name: "a.txt", size: 5 });
const { value: value2 } = await iter.next();
expect(value2).toEqual({ mtime: value2.mtime, name: "a.txt", size: 11 });
const stat = await fs.stat("a.txt");
expect(stat.mtimeMs).toEqual(value2.mtime);
expect(dir.files["a.txt"]).toEqual({ mtime: value2.mtime, size: 11 });
});

it("create another monitor starting with the now nonempty directory", async () => {
const dir2 = await listing({ path: "", fs });
expect(Object.keys(dir2.files!)).toEqual(["a.txt"]);
expect(dir.files["a.txt"].mtime).toBeCloseTo(dir2.files!["a.txt"].mtime);
dir2.close();
});

const count = 500;
it(`creates ${count} files and see they are found`, async () => {
const n = Object.keys(dir.files).length;

for (let i = 0; i < count; i++) {
await fs.writeFile(`${i}`, "");
}
const values: string[] = [];
while (true) {
const { value } = await iter.next();
if (value == "a.txt") {
continue;
}
values.push(value);
if (value.name == `${count - 1}`) {
break;
}
}
expect(new Set(values).size).toEqual(count);

expect(Object.keys(dir.files).length).toEqual(n + count);
});

it("cleans up", () => {
dir.close();
});
});
Loading
Loading