Storage and meta files
blob layout, hashing, meta JSON, and compression
This page is implementation detail, beyond what normal use requires. You do not need any of it to run the four verbs.
This page builds a project with files of several sizes, then inspects the
metadata folder and the storage directory to show how dvs lays data out: a
content-addressed blob store, a .dvs meta file per tracked file, and per-file
compression.
🔗Setup
options(width = 1000)
library(dvs)
library(fs)
library(here)here() starts at /Users/elea/Documents/a2ai_github/dvs2-demo-repo🔗Helpers
source(here::here("R/mkdatasetfiles.R"))storage <- basename(tempfile(fileext = "_storage"))
new_project <- basename(tempfile(fileext = "_project"))
dir.create(here::here(storage))
dir.create(here::here(new_project))setwd(here::here(new_project))
mkdatasetfiles(n_files = 1, size_mb = 25, prefix = "large_", dir = "data/large", show_progress = !nzchar(Sys.getenv("QUARTO_DOCUMENT_PATH")))
mkdatasetfiles(n_files = 3, size_mb = 1, prefix = "small_", dir = "data/small", show_progress = !nzchar(Sys.getenv("QUARTO_DOCUMENT_PATH")))
mkdatasetfiles(n_files = 50, size_mb = 3, prefix = "individual_", dir = "data/individual", show_progress = !nzchar(Sys.getenv("QUARTO_DOCUMENT_PATH")))setwd(here::here(new_project))
dvs_init(here::here(storage), compression = "none")DVS Initializeddvs_add("data/large/large_1.csv", message = "add one large dataset")# A tibble: 1 × 5
path outcome hash size stored_size
<chr> <chr> <chr> <bytes> <bytes>
1 data/large/large_1.csv copied 3c77885f59933a6334a438d0a77d2adcd06873bed58a00fc9807fce3d13ed838 25.0 MB 25.0 MBdvs_add(paths = fs::dir_ls("data/small", type = "file"), message = "add small corpus datasets")# A tibble: 3 × 5
path outcome hash size stored_size
<chr> <chr> <chr> <bytes> <bytes>
1 data/small/small_1.csv copied e0fb0b7aac778f07ba37105d2e2a70d1cee429f50d77c3b0c9dd4ad4d2222937 1024.0 KB 1024.0 KB
2 data/small/small_2.csv copied 1574af6b3e5cfd7fdba90c4f819fbd2bd128cd573c304588623fc09d49ae6b04 1024.0 KB 1024.0 KB
3 data/small/small_3.csv copied 9d97b050e954474b51c5b3f06eafd07bc33366b9f3b09ea1211ac75c2704357a 1024.0 KB 1024.0 KBdvs_add(glob = "data/individual/individual_*.csv", message = "add individual datasets via glob")# A tibble: 50 × 5
path outcome hash size stored_size
<chr> <chr> <chr> <bytes> <bytes>
1 data/individual/individual_01.csv copied 57856e362f74d4319cdb81f0454e205a91e7ad8c83e3442aee7da4c676902d53 3.0 MB 3.0 MB
2 data/individual/individual_02.csv copied 85ee4a308973f2ef5cda8d4a1a6228a4ff69e0f72de5c2dfd1aa8f9a409e2b5c 3.0 MB 3.0 MB
3 data/individual/individual_03.csv copied cd648605e42fddc1c08fc761b3683021e0be3a4578b0ec9e02e84e9645db8d58 3.0 MB 3.0 MB
4 data/individual/individual_04.csv copied 388c35ea1e0f0f55cd73c6d6e84ad7659b3954f271103b51bcc868f9f07d1aee 3.0 MB 3.0 MB
5 data/individual/individual_05.csv copied 0dbb9776c7188194995a8ddc0dca67a9814ef7fa165cc035518386c6e51cbb92 3.0 MB 3.0 MB
6 data/individual/individual_06.csv copied e3d9340328668ac4a61180c62664fa53726de78410ac7b90679b9f81cee2b852 3.0 MB 3.0 MB
7 data/individual/individual_07.csv copied e755c66eba55a05f0cb10a6c068f29a373de0baaed2649f0b8828ff302c65d61 3.0 MB 3.0 MB
8 data/individual/individual_08.csv copied 93cb8aaac5d09feba55d44274f96b3b67f81fd66fce959e86e6b5af80b670d61 3.0 MB 3.0 MB
9 data/individual/individual_09.csv copied 26af472b0caf28693778231ceacf48504b4c09d2cc877dd9c4a7f1a21144d72f 3.0 MB 3.0 MB
10 data/individual/individual_10.csv copied 804e10256f674fbb79860959dc612b3f73171c96871a6707278eaea594f9d470 3.0 MB 3.0 MB
# ℹ 40 more rows🔗Internals of .dvs
.dvs is hidden, so fs:: helpers need all = TRUE.
setwd(here::here(new_project))
fs::dir_tree(".dvs", all = TRUE, regexp = "\\.git", invert = TRUE).dvs
├── .cache
│ └── dvs.db
└── data
├── individual
│ ├── individual_01.csv.dvs
│ ├── individual_02.csv.dvs
│ ├── individual_03.csv.dvs
│ ├── individual_04.csv.dvs
│ ├── individual_05.csv.dvs
│ ├── individual_06.csv.dvs
│ ├── individual_07.csv.dvs
│ ├── individual_08.csv.dvs
│ ├── individual_09.csv.dvs
│ ├── individual_10.csv.dvs
│ ├── individual_11.csv.dvs
│ ├── individual_12.csv.dvs
│ ├── individual_13.csv.dvs
│ ├── individual_14.csv.dvs
│ ├── individual_15.csv.dvs
│ ├── individual_16.csv.dvs
│ ├── individual_17.csv.dvs
│ ├── individual_18.csv.dvs
│ ├── individual_19.csv.dvs
│ ├── individual_20.csv.dvs
│ ├── individual_21.csv.dvs
│ ├── individual_22.csv.dvs
│ ├── individual_23.csv.dvs
│ ├── individual_24.csv.dvs
│ ├── individual_25.csv.dvs
│ ├── individual_26.csv.dvs
│ ├── individual_27.csv.dvs
│ ├── individual_28.csv.dvs
│ ├── individual_29.csv.dvs
│ ├── individual_30.csv.dvs
│ ├── individual_31.csv.dvs
│ ├── individual_32.csv.dvs
│ ├── individual_33.csv.dvs
│ ├── individual_34.csv.dvs
│ ├── individual_35.csv.dvs
│ ├── individual_36.csv.dvs
│ ├── individual_37.csv.dvs
│ ├── individual_38.csv.dvs
│ ├── individual_39.csv.dvs
│ ├── individual_40.csv.dvs
│ ├── individual_41.csv.dvs
│ ├── individual_42.csv.dvs
│ ├── individual_43.csv.dvs
│ ├── individual_44.csv.dvs
│ ├── individual_45.csv.dvs
│ ├── individual_46.csv.dvs
│ ├── individual_47.csv.dvs
│ ├── individual_48.csv.dvs
│ ├── individual_49.csv.dvs
│ └── individual_50.csv.dvs
├── large
│ └── large_1.csv.dvs
└── small
├── small_1.csv.dvs
├── small_2.csv.dvs
└── small_3.csv.dvssetwd(here::here(new_project))
fs::dir_info(".dvs", recurse = TRUE, all = TRUE, type = "file") |>
dplyr::filter(!grepl("\\.git", path)) |>
dplyr::select(size, path, type)# A tibble: 55 × 3
size path type
<fs::bytes> <fs::path> <fct>
1 20K .dvs/.cache/dvs.db file
2 264 .dvs/data/individual/individual_01.csv.dvs file
3 264 .dvs/data/individual/individual_02.csv.dvs file
4 263 .dvs/data/individual/individual_03.csv.dvs file
5 264 .dvs/data/individual/individual_04.csv.dvs file
6 263 .dvs/data/individual/individual_05.csv.dvs file
7 264 .dvs/data/individual/individual_06.csv.dvs file
8 264 .dvs/data/individual/individual_07.csv.dvs file
9 264 .dvs/data/individual/individual_08.csv.dvs file
10 264 .dvs/data/individual/individual_09.csv.dvs file
# ℹ 45 more rowssetwd(here::here(new_project))
fs::dir_info(".dvs", recurse = TRUE, all = TRUE, type = "file") |>
dplyr::filter(!grepl("\\.git", path)) |>
dplyr::mutate(subdir = path |> fs::path_dir() |> fs::path_rel(".dvs")) |>
dplyr::reframe(n_files = dplyr::n(), size = sum(size), .by = subdir)# A tibble: 4 × 3
subdir n_files size
<fs::path> <int> <fs::bytes>
1 .cache 1 20K
2 data/individual 50 12.9K
3 data/large 1 253
4 data/small 3 771🔗Meta files
Each tracked data file has a .dvs meta file under .dvs/, mirroring the data tree.
setwd(here::here(new_project))
meta_files <- fs::dir_ls(".dvs", recurse = TRUE, all = TRUE, glob = "*.dvs", type = "file")
meta_files <- meta_files[!grepl("\\.git", meta_files)]
meta_files.dvs/data/individual/individual_01.csv.dvs .dvs/data/individual/individual_02.csv.dvs .dvs/data/individual/individual_03.csv.dvs .dvs/data/individual/individual_04.csv.dvs .dvs/data/individual/individual_05.csv.dvs .dvs/data/individual/individual_06.csv.dvs .dvs/data/individual/individual_07.csv.dvs .dvs/data/individual/individual_08.csv.dvs .dvs/data/individual/individual_09.csv.dvs .dvs/data/individual/individual_10.csv.dvs .dvs/data/individual/individual_11.csv.dvs .dvs/data/individual/individual_12.csv.dvs .dvs/data/individual/individual_13.csv.dvs .dvs/data/individual/individual_14.csv.dvs .dvs/data/individual/individual_15.csv.dvs .dvs/data/individual/individual_16.csv.dvs .dvs/data/individual/individual_17.csv.dvs .dvs/data/individual/individual_18.csv.dvs .dvs/data/individual/individual_19.csv.dvs .dvs/data/individual/individual_20.csv.dvs .dvs/data/individual/individual_21.csv.dvs .dvs/data/individual/individual_22.csv.dvs .dvs/data/individual/individual_23.csv.dvs
.dvs/data/individual/individual_24.csv.dvs .dvs/data/individual/individual_25.csv.dvs .dvs/data/individual/individual_26.csv.dvs .dvs/data/individual/individual_27.csv.dvs .dvs/data/individual/individual_28.csv.dvs .dvs/data/individual/individual_29.csv.dvs .dvs/data/individual/individual_30.csv.dvs .dvs/data/individual/individual_31.csv.dvs .dvs/data/individual/individual_32.csv.dvs .dvs/data/individual/individual_33.csv.dvs .dvs/data/individual/individual_34.csv.dvs .dvs/data/individual/individual_35.csv.dvs .dvs/data/individual/individual_36.csv.dvs .dvs/data/individual/individual_37.csv.dvs .dvs/data/individual/individual_38.csv.dvs .dvs/data/individual/individual_39.csv.dvs .dvs/data/individual/individual_40.csv.dvs .dvs/data/individual/individual_41.csv.dvs .dvs/data/individual/individual_42.csv.dvs .dvs/data/individual/individual_43.csv.dvs .dvs/data/individual/individual_44.csv.dvs .dvs/data/individual/individual_45.csv.dvs .dvs/data/individual/individual_46.csv.dvs
.dvs/data/individual/individual_47.csv.dvs .dvs/data/individual/individual_48.csv.dvs .dvs/data/individual/individual_49.csv.dvs .dvs/data/individual/individual_50.csv.dvs .dvs/data/large/large_1.csv.dvs .dvs/data/small/small_1.csv.dvs .dvs/data/small/small_2.csv.dvs .dvs/data/small/small_3.csv.dvs
Contents of the meta file for data/large/large_1.csv:
setwd(here::here(new_project))
large_meta <- grep("large_1", meta_files, value = TRUE)
large_meta .dvs/data/large/large_1.csv.dvs
".dvs/data/large/large_1.csv.dvs" setwd(here::here(new_project))
cat("```json\n")
```r
cat(jsonlite::toJSON(jsonlite::fromJSON(large_meta, simplifyVector = FALSE), pretty = TRUE, auto_unbox = TRUE))
{ "hashes": { "blake3": "3c77885f59933a6334a438d0a77d2adcd06873bed58a00fc9807fce3d13ed838" }, "size": 26214390, "created_by": "elea", "add_time": "2026-06-16T17:06:53.00164Z", "compression": "none", "message": "add one large dataset" }
cat("\n```\n")# Storage directory
```r
fs::dir_tree(here::here(storage), all = TRUE, regexp = "\\.git", invert = TRUE)/Users/elea/Documents/a2ai_github/dvs2-demo-repo/file891962380109_storage
├── 0d
│ └── bb9776c7188194995a8ddc0dca67a9814ef7fa165cc035518386c6e51cbb92
├── 15
│ └── 74af6b3e5cfd7fdba90c4f819fbd2bd128cd573c304588623fc09d49ae6b04
├── 1d
│ └── 884347c3d0433a2833ef586c83afebb2bc30cdea12d323e80f25526aacaae4
├── 1f
│ └── e13d85d36ee596cf9bc781919808458b2cd00b49bcb342e8c5db5cce915c62
├── 26
│ ├── af472b0caf28693778231ceacf48504b4c09d2cc877dd9c4a7f1a21144d72f
│ └── bfcc219ab65cd79ce696d013ae6148055d01c187e2c31570452315e441819f
├── 2a
│ └── ecd8dc9adb04d3777e23ac721bbc2828e599be8ad35af4b87400cd41148671
├── 2f
│ └── 05406da9b7905880f2f6230ca5883637820d1abecbdd12190696242e4a3077
├── 31
│ └── 758fcb8655fd233cf99e0ab466f4a7d997b85a51ecfc804965aad4d3125d18
├── 34
│ └── fd92ee0ed3122e814c275ba2d4bcf83e749ea0a4fda462d56afbd0f62fea8a
├── 38
│ └── 8c35ea1e0f0f55cd73c6d6e84ad7659b3954f271103b51bcc868f9f07d1aee
├── 3c
│ └── 77885f59933a6334a438d0a77d2adcd06873bed58a00fc9807fce3d13ed838
├── 3e
│ └── 5fb7f5dab7515086635a93328785b2b703922b6b7499cf3de2d6f4e954e98c
├── 44
│ └── 3b0aad3af092b510e3624d737d71f60cf771b5bf387c1f7126e0cd712cc8cf
├── 45
│ └── 6eaf1e596ccf2e8cc982c9ca3192f996efa0638d9dbd96a03f90fc35a34c51
├── 48
│ └── dff588f909e9720dff2a675afef20a44add218cb55e7883736326938917b73
├── 49
│ └── d367f13b24c611561d1dae7d9860390b8239689a7a7ffac393b3eaf8907be7
├── 4b
│ └── bae46269b915721b8a461f9138afaa04dbe69c2a6be89ccbd3d26abc09f869
├── 57
│ ├── 216386358ca115c810f01903cce60423037feee2faf2d3a26032627ed7ca9d
│ └── 856e362f74d4319cdb81f0454e205a91e7ad8c83e3442aee7da4c676902d53
├── 5b
│ └── 8ed16fac2af119cd417960ca8ef817507f2a74352cd10b4809fe77ad0f9759
├── 62
│ └── 058b6bf8fb1c380f4fded49604df6fa144c84e49775dd879f084124d6ea8a1
├── 71
│ └── f792a1264e4704e7f53e99f741d4baa46f0fa3ef864a83ada590a954da34e9
├── 77
│ └── d27c2060525b39adcfd943235b96f0c0158e2c6eda8ef3d007f23b0a9b29b0
├── 78
│ └── ffc0ed3e6b077436ef61504935dd65137caa45893173527f53f14dd54073c9
├── 7c
│ └── f60960fa5161e67262be59e546dc42cada90c99a6d9c767cc9eda8530a282d
├── 7d
│ └── 62b45f3c50dcaf1f3143a9c67d5a1606b58660359405f533483713157d3ce2
├── 80
│ └── 4e10256f674fbb79860959dc612b3f73171c96871a6707278eaea594f9d470
├── 81
│ └── 9f86f6a3bdc6ce6d08f3529690c674e01d89dbfcd6e5491630db4ea2add30a
├── 85
│ └── ee4a308973f2ef5cda8d4a1a6228a4ff69e0f72de5c2dfd1aa8f9a409e2b5c
├── 88
│ └── ba43b3a95a505c9605335a03f0a07d89dbb0b0fd1824d2e50f109ec8267468
├── 8d
│ └── 0524a0aaca6787bebacce86072df4b16930660998654c202a0235888512d3e
├── 93
│ ├── ca349f3eb8b7bae487fc3c871b38b702ca8774e1e47e291dbf4deef768188f
│ └── cb8aaac5d09feba55d44274f96b3b67f81fd66fce959e86e6b5af80b670d61
├── 96
│ └── 49f8ae18c09b20768f4f017ab983c75b90b3e4e5935d1308e935f2ac4e9b4b
├── 9d
│ ├── 97b050e954474b51c5b3f06eafd07bc33366b9f3b09ea1211ac75c2704357a
│ └── ec1c7c19612c726f715faef5d6057b9e4dde7d5c20d70b056cbe6f2bd7c91c
├── a0
│ └── 23d54af885922c1f2e65efa78cd32d6cef07a3a31a2edb7cbe67e862964ac7
├── ad
│ └── ebf3682c67ecf60ed348fa6eb031c786496275e9b8a47082e4839cf0d02a4d
├── audit.log.jsonl
├── b0
│ └── 5327be23b5f7172df2b5c2a19ba2a214b6d8c01d87f6231563a2b2dd9f464b
├── bc
│ └── 2c089b5bfd013e062b7cea8e22907983fb40e7824b8d309ec0dc7c46fdc6e4
├── bd
│ └── d2150b27e4b6b90cba72e1a5e9e7fa0fd38e90702c0169393c86e2dc85691a
├── c2
│ └── 332280ea27acd678ed478ae719549e643820c193e35a4362ffc57d02a211a8
├── cd
│ └── 648605e42fddc1c08fc761b3683021e0be3a4578b0ec9e02e84e9645db8d58
├── d3
│ └── 25a9ede2e5b2509fd4893dfdb350e4fd653e9a9e4fb6b2605f72ae315659c8
├── d8
│ └── 55539255e6bcef2bdb7b3be9c727312db4c8eb6229851bb2ddd71667bde6e3
├── df
│ └── 09093a115feea9827440955103488d2c73bcbaf8a56f7ff79842b19348645f
├── e0
│ └── fb0b7aac778f07ba37105d2e2a70d1cee429f50d77c3b0c9dd4ad4d2222937
├── e3
│ ├── 9164399b7147c57fc78e073fff926a23d1165b4436a5c71f70941d8acb4a58
│ └── d9340328668ac4a61180c62664fa53726de78410ac7b90679b9f81cee2b852
├── e4
│ └── 7dda9fc7f57f5acaf284aed70e127bbc78ed1a67195936cbbcf4e6d1c321b2
├── e7
│ └── 55c66eba55a05f0cb10a6c068f29a373de0baaed2649f0b8828ff302c65d61
├── ec
│ └── 1caea68524d4fb96a4ec8e9127229bc3c2e23d669be92f5add767c59889ab8
└── f3
└── cd94c8247890360ef1b61bb7cdc49f6463c39c08b7f0e0c62ea9dec575b0fafs::dir_info(here::here(storage), recurse = TRUE, all = TRUE, type = "file") |>
dplyr::filter(!grepl("\\.git", path)) |>
dplyr::mutate(subdir = path |> fs::path_dir() |> fs::path_rel(here::here(storage))) |>
dplyr::reframe(n_files = dplyr::n(), size = sum(size), .by = subdir)# A tibble: 50 × 3
subdir n_files size
<fs::path> <int> <fs::bytes>
1 0d 1 3M
2 15 1 1024K
3 1d 1 3M
4 1f 1 3M
5 26 2 6M
6 2a 1 3M
7 2f 1 3M
8 31 1 3M
9 34 1 3M
10 38 1 3M
# ℹ 40 more rows🔗Hashed blob is plain text
Pick up the blake3 hash from the meta file.
setwd(here::here(new_project))
meta <- jsonlite::fromJSON(large_meta)
meta$hashes
$hashes$blake3
[1] "3c77885f59933a6334a438d0a77d2adcd06873bed58a00fc9807fce3d13ed838"
$size
[1] 26214390
$created_by
[1] "elea"
$add_time
[1] "2026-06-16T17:06:53.00164Z"
$compression
[1] "none"
$message
[1] "add one large dataset"hash <- meta$hashes$blake3
hash[1] "3c77885f59933a6334a438d0a77d2adcd06873bed58a00fc9807fce3d13ed838"
Blobs are split into <first-2>/<rest>:
large_blob <- here::here(storage, substr(hash, 1, 2), substr(hash, 3, nchar(hash)))
large_blob[1] "/Users/elea/Documents/a2ai_github/dvs2-demo-repo/file891962380109_storage/3c/77885f59933a6334a438d0a77d2adcd06873bed58a00fc9807fce3d13ed838"fs::file_exists(large_blob)/Users/elea/Documents/a2ai_github/dvs2-demo-repo/file891962380109_storage/3c/77885f59933a6334a438d0a77d2adcd06873bed58a00fc9807fce3d13ed838
TRUE
Initialized with compression = "none", the stored object is the original CSV, addressable by hash. Readable as-is.
readLines(large_blob, n = 5)[1] "weight,Time,Chick,Diet,rand1,rand2,rand3,rand4,rand5,rand6,rand7,rand8,rand9,rand10" "42,0,1,1,835,744,435,780,819,845,933,348,470,634" "51,2,1,1,678,501,383,179,313,256,607,120,393,638" "59,4,1,1,128,687,923,696,798,190,506,122,254,584" "64,6,1,1,929,315,597,366,830,800,287,457,774,403" readLines(
n = 5, here::here(new_project, "data", "large", "large_1.csv")
)[1] "weight,Time,Chick,Diet,rand1,rand2,rand3,rand4,rand5,rand6,rand7,rand8,rand9,rand10" "42,0,1,1,835,744,435,780,819,845,933,348,470,634" "51,2,1,1,678,501,383,179,313,256,607,120,393,638" "59,4,1,1,128,687,923,696,798,190,506,122,254,584" "64,6,1,1,929,315,597,366,830,800,287,457,774,403" 🔗.dvs/ mirrors data/
Meta files live under .dvs/ at the same relative paths as the data files they track.
setwd(here::here(new_project))
fs::dir_tree("data", regexp = "\\.git", invert = TRUE)data
├── individual
│ ├── individual_01.csv
│ ├── individual_02.csv
│ ├── individual_03.csv
│ ├── individual_04.csv
│ ├── individual_05.csv
│ ├── individual_06.csv
│ ├── individual_07.csv
│ ├── individual_08.csv
│ ├── individual_09.csv
│ ├── individual_10.csv
│ ├── individual_11.csv
│ ├── individual_12.csv
│ ├── individual_13.csv
│ ├── individual_14.csv
│ ├── individual_15.csv
│ ├── individual_16.csv
│ ├── individual_17.csv
│ ├── individual_18.csv
│ ├── individual_19.csv
│ ├── individual_20.csv
│ ├── individual_21.csv
│ ├── individual_22.csv
│ ├── individual_23.csv
│ ├── individual_24.csv
│ ├── individual_25.csv
│ ├── individual_26.csv
│ ├── individual_27.csv
│ ├── individual_28.csv
│ ├── individual_29.csv
│ ├── individual_30.csv
│ ├── individual_31.csv
│ ├── individual_32.csv
│ ├── individual_33.csv
│ ├── individual_34.csv
│ ├── individual_35.csv
│ ├── individual_36.csv
│ ├── individual_37.csv
│ ├── individual_38.csv
│ ├── individual_39.csv
│ ├── individual_40.csv
│ ├── individual_41.csv
│ ├── individual_42.csv
│ ├── individual_43.csv
│ ├── individual_44.csv
│ ├── individual_45.csv
│ ├── individual_46.csv
│ ├── individual_47.csv
│ ├── individual_48.csv
│ ├── individual_49.csv
│ └── individual_50.csv
├── large
│ └── large_1.csv
└── small
├── small_1.csv
├── small_2.csv
└── small_3.csvsetwd(here::here(new_project))
fs::dir_tree(".dvs", all = TRUE, regexp = "\\.git", invert = TRUE).dvs
├── .cache
│ └── dvs.db
└── data
├── individual
│ ├── individual_01.csv.dvs
│ ├── individual_02.csv.dvs
│ ├── individual_03.csv.dvs
│ ├── individual_04.csv.dvs
│ ├── individual_05.csv.dvs
│ ├── individual_06.csv.dvs
│ ├── individual_07.csv.dvs
│ ├── individual_08.csv.dvs
│ ├── individual_09.csv.dvs
│ ├── individual_10.csv.dvs
│ ├── individual_11.csv.dvs
│ ├── individual_12.csv.dvs
│ ├── individual_13.csv.dvs
│ ├── individual_14.csv.dvs
│ ├── individual_15.csv.dvs
│ ├── individual_16.csv.dvs
│ ├── individual_17.csv.dvs
│ ├── individual_18.csv.dvs
│ ├── individual_19.csv.dvs
│ ├── individual_20.csv.dvs
│ ├── individual_21.csv.dvs
│ ├── individual_22.csv.dvs
│ ├── individual_23.csv.dvs
│ ├── individual_24.csv.dvs
│ ├── individual_25.csv.dvs
│ ├── individual_26.csv.dvs
│ ├── individual_27.csv.dvs
│ ├── individual_28.csv.dvs
│ ├── individual_29.csv.dvs
│ ├── individual_30.csv.dvs
│ ├── individual_31.csv.dvs
│ ├── individual_32.csv.dvs
│ ├── individual_33.csv.dvs
│ ├── individual_34.csv.dvs
│ ├── individual_35.csv.dvs
│ ├── individual_36.csv.dvs
│ ├── individual_37.csv.dvs
│ ├── individual_38.csv.dvs
│ ├── individual_39.csv.dvs
│ ├── individual_40.csv.dvs
│ ├── individual_41.csv.dvs
│ ├── individual_42.csv.dvs
│ ├── individual_43.csv.dvs
│ ├── individual_44.csv.dvs
│ ├── individual_45.csv.dvs
│ ├── individual_46.csv.dvs
│ ├── individual_47.csv.dvs
│ ├── individual_48.csv.dvs
│ ├── individual_49.csv.dvs
│ └── individual_50.csv.dvs
├── large
│ └── large_1.csv.dvs
└── small
├── small_1.csv.dvs
├── small_2.csv.dvs
└── small_3.csv.dvs🔗Git integration
When the project is inside a Git repository, dvs_add() appends each added file
to a .gitignore in that file's parent directory, as /<filename>. The file
contents stay out of Git; what you commit is the .dvs meta file, which travels
with your code and records the hash needed to retrieve the data.
# .gitignore entry written for data/large/large_1.csv
/large_1.csv
If there is no .git, this step is skipped. A failure to write .gitignore is
a warning, not an error.
🔗Untracking a file
dvs tracks a file through its meta file. Remove the meta file and dvs no longer tracks the file. The stored blob is left in place, so other meta files that reference the same content still resolve.
setwd(here::here(new_project))
dvs_status("data/large/large_1.csv")[, c("path", "status")]# A tibble: 1 × 2
path status
<chr> <chr>
1 data/large/large_1.csv currentsetwd(here::here(new_project))
file.remove(large_meta)[1] TRUEdvs_status("data/large/large_1.csv")# A tibble: 0 × 0🔗Cleanup
unlink(here::here(new_project), recursive = TRUE)
unlink(here::here(storage), recursive = TRUE)🔗See also
- The dvs.toml project file: the project configuration.
- The audit log: the append-only record of every add.
- The command references: dvs_add() / dvs add.