devobs 0.1.0__tar.gz → 0.2.0__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.
- {devobs-0.1.0 → devobs-0.2.0}/.devcontainer/devcontainer.json +1 -1
- {devobs-0.1.0 → devobs-0.2.0}/.devcontainer/postAttachCommand.sh +1 -1
- {devobs-0.1.0 → devobs-0.2.0}/.github/workflows/ci.yaml +2 -2
- {devobs-0.1.0 → devobs-0.2.0}/.github/workflows/release.yaml +4 -4
- {devobs-0.1.0 → devobs-0.2.0}/.pre-commit-config.yaml +14 -0
- {devobs-0.1.0 → devobs-0.2.0}/Cargo.lock +61 -87
- {devobs-0.1.0 → devobs-0.2.0}/Cargo.toml +6 -5
- {devobs-0.1.0 → devobs-0.2.0}/Makefile +2 -2
- {devobs-0.1.0 → devobs-0.2.0}/PKG-INFO +3 -3
- devobs-0.2.0/README.md +7 -0
- devobs-0.2.0/src/commands/assert_diff.rs +158 -0
- {devobs-0.1.0 → devobs-0.2.0}/src/commands/check_file_pair.rs +2 -1
- {devobs-0.1.0 → devobs-0.2.0}/src/commands.rs +1 -0
- {devobs-0.1.0 → devobs-0.2.0}/src/main.rs +5 -3
- {devobs-0.1.0 → devobs-0.2.0}/src/utils/fs.rs +19 -4
- {devobs-0.1.0 → devobs-0.2.0}/tests/commands/mod.rs +1 -0
- devobs-0.2.0/tests/commands/snapshots/integration_test__commands__test_assert_diff__changes_create-2.snap +5 -0
- devobs-0.2.0/tests/commands/snapshots/integration_test__commands__test_assert_diff__changes_create.snap +7 -0
- devobs-0.2.0/tests/commands/snapshots/integration_test__commands__test_assert_diff__changes_delete-2.snap +5 -0
- devobs-0.2.0/tests/commands/snapshots/integration_test__commands__test_assert_diff__changes_delete.snap +7 -0
- devobs-0.2.0/tests/commands/snapshots/integration_test__commands__test_assert_diff__changes_modify-2.snap +5 -0
- devobs-0.2.0/tests/commands/snapshots/integration_test__commands__test_assert_diff__changes_modify.snap +7 -0
- devobs-0.2.0/tests/commands/snapshots/integration_test__commands__test_assert_diff__empty_directory.snap +9 -0
- devobs-0.2.0/tests/commands/snapshots/integration_test__commands__test_assert_diff__no_changes.snap +9 -0
- devobs-0.2.0/tests/commands/snapshots/integration_test__commands__test_assert_diff__no_command_to_run.snap +5 -0
- devobs-0.2.0/tests/commands/snapshots/integration_test__commands__test_assert_diff__nonexistent_directory.snap +5 -0
- devobs-0.2.0/tests/commands/snapshots/integration_test__commands__test_assert_diff__on_command_error_ignore.snap +9 -0
- devobs-0.2.0/tests/commands/snapshots/integration_test__commands__test_assert_diff__on_command_error_propagate.snap +7 -0
- devobs-0.2.0/tests/commands/test_assert_diff.rs +334 -0
- {devobs-0.1.0 → devobs-0.2.0}/tests/commands/test_check_file_pair.rs +43 -38
- {devobs-0.1.0 → devobs-0.2.0}/tests/helpers.rs +19 -8
- devobs-0.1.0/README.md +0 -7
- {devobs-0.1.0 → devobs-0.2.0}/.config/nextest.toml +0 -0
- {devobs-0.1.0 → devobs-0.2.0}/.devcontainer/onCreateCommand.sh +0 -0
- {devobs-0.1.0 → devobs-0.2.0}/.editorconfig +0 -0
- {devobs-0.1.0 → devobs-0.2.0}/.gitattributes +0 -0
- {devobs-0.1.0 → devobs-0.2.0}/.github/dependabot.yaml +0 -0
- {devobs-0.1.0 → devobs-0.2.0}/.gitignore +0 -0
- {devobs-0.1.0 → devobs-0.2.0}/.pre-commit-hooks.yaml +0 -0
- {devobs-0.1.0 → devobs-0.2.0}/.rustfmt.toml +0 -0
- {devobs-0.1.0 → devobs-0.2.0}/.vscode/extensions.json +0 -0
- {devobs-0.1.0 → devobs-0.2.0}/.vscode/launch.json +0 -0
- {devobs-0.1.0 → devobs-0.2.0}/.vscode/settings.json +0 -0
- {devobs-0.1.0 → devobs-0.2.0}/LICENSE +0 -0
- {devobs-0.1.0 → devobs-0.2.0}/pyproject.toml +0 -0
- {devobs-0.1.0 → devobs-0.2.0}/rust-toolchain.toml +0 -0
- {devobs-0.1.0 → devobs-0.2.0}/src/utils.rs +0 -0
- {devobs-0.1.0 → devobs-0.2.0}/tests/commands/snapshots/integration_test__commands__test_check_file_pair__backward_matching.snap +0 -0
- {devobs-0.1.0 → devobs-0.2.0}/tests/commands/snapshots/integration_test__commands__test_check_file_pair__create_if_not_exists.snap +0 -0
- {devobs-0.1.0 → devobs-0.2.0}/tests/commands/snapshots/integration_test__commands__test_check_file_pair__create_if_not_exists_dry_run.snap +0 -0
- {devobs-0.1.0 → devobs-0.2.0}/tests/commands/snapshots/integration_test__commands__test_check_file_pair__empty_directory_no_error_no_output.snap +0 -0
- {devobs-0.1.0 → devobs-0.2.0}/tests/commands/snapshots/integration_test__commands__test_check_file_pair__forward_matching.snap +0 -0
- {devobs-0.1.0 → devobs-0.2.0}/tests/commands/snapshots/integration_test__commands__test_check_file_pair__on_fully_populated_directory.snap +0 -0
- {devobs-0.1.0 → devobs-0.2.0}/tests/integration_test.rs +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "lasuillard/devobs",
|
|
3
3
|
"image": "mcr.microsoft.com/devcontainers/rust:1-bookworm",
|
|
4
4
|
"features": {
|
|
5
|
-
"ghcr.io/devcontainers-
|
|
5
|
+
"ghcr.io/devcontainers-extra/features/pre-commit:2": {}
|
|
6
6
|
},
|
|
7
7
|
"onCreateCommand": "./.devcontainer/onCreateCommand.sh",
|
|
8
8
|
"postAttachCommand": "./.devcontainer/postAttachCommand.sh",
|
|
@@ -15,7 +15,7 @@ jobs:
|
|
|
15
15
|
timeout-minutes: 10
|
|
16
16
|
steps:
|
|
17
17
|
- name: Checkout
|
|
18
|
-
uses: actions/checkout@
|
|
18
|
+
uses: actions/checkout@v5
|
|
19
19
|
|
|
20
20
|
- name: Set up Rust
|
|
21
21
|
run: rustup show
|
|
@@ -38,7 +38,7 @@ jobs:
|
|
|
38
38
|
id-token: write
|
|
39
39
|
steps:
|
|
40
40
|
- name: Checkout
|
|
41
|
-
uses: actions/checkout@
|
|
41
|
+
uses: actions/checkout@v5
|
|
42
42
|
|
|
43
43
|
- name: Set up Rust
|
|
44
44
|
run: rustup show
|
|
@@ -23,7 +23,7 @@ jobs:
|
|
|
23
23
|
timeout-minutes: 15
|
|
24
24
|
steps:
|
|
25
25
|
- name: Checkout
|
|
26
|
-
uses: actions/checkout@
|
|
26
|
+
uses: actions/checkout@v5
|
|
27
27
|
|
|
28
28
|
- name: Build wheels
|
|
29
29
|
uses: PyO3/maturin-action@v1
|
|
@@ -42,7 +42,7 @@ jobs:
|
|
|
42
42
|
timeout-minutes: 15
|
|
43
43
|
steps:
|
|
44
44
|
- name: Checkout
|
|
45
|
-
uses: actions/checkout@
|
|
45
|
+
uses: actions/checkout@v5
|
|
46
46
|
|
|
47
47
|
- name: Build sdist
|
|
48
48
|
uses: PyO3/maturin-action@v1
|
|
@@ -68,7 +68,7 @@ jobs:
|
|
|
68
68
|
contents: write
|
|
69
69
|
steps:
|
|
70
70
|
- name: Download binary artifacts
|
|
71
|
-
uses: actions/download-artifact@
|
|
71
|
+
uses: actions/download-artifact@v5
|
|
72
72
|
with:
|
|
73
73
|
path: dist
|
|
74
74
|
|
|
@@ -91,7 +91,7 @@ jobs:
|
|
|
91
91
|
id-token: write
|
|
92
92
|
steps:
|
|
93
93
|
- name: Download binary artifacts
|
|
94
|
-
uses: actions/download-artifact@
|
|
94
|
+
uses: actions/download-artifact@v5
|
|
95
95
|
with:
|
|
96
96
|
path: dist
|
|
97
97
|
merge-multiple: true
|
|
@@ -11,6 +11,20 @@ repos:
|
|
|
11
11
|
- id: trailing-whitespace
|
|
12
12
|
- id: end-of-file-fixer
|
|
13
13
|
|
|
14
|
+
# TODO(lasuillard): For testing. Later need to be improved with config file support.
|
|
15
|
+
- repo: https://github.com/lasuillard/devobs
|
|
16
|
+
rev: v0.1.0
|
|
17
|
+
hooks:
|
|
18
|
+
# Require each commands to have a matching integration tests.
|
|
19
|
+
- id: devobs
|
|
20
|
+
pass_filenames: false
|
|
21
|
+
args:
|
|
22
|
+
- check-file-pair
|
|
23
|
+
- --from=src/commands
|
|
24
|
+
- --to=tests/commands
|
|
25
|
+
- --include='*.rs'
|
|
26
|
+
- --expect='{to}/{relative_from}/test_{filename}'
|
|
27
|
+
|
|
14
28
|
- repo: local
|
|
15
29
|
hooks:
|
|
16
30
|
- id: cargo-fmt
|
|
@@ -2,21 +2,6 @@
|
|
|
2
2
|
# It is not intended for manual editing.
|
|
3
3
|
version = 4
|
|
4
4
|
|
|
5
|
-
[[package]]
|
|
6
|
-
name = "addr2line"
|
|
7
|
-
version = "0.24.2"
|
|
8
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
9
|
-
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
|
|
10
|
-
dependencies = [
|
|
11
|
-
"gimli",
|
|
12
|
-
]
|
|
13
|
-
|
|
14
|
-
[[package]]
|
|
15
|
-
name = "adler2"
|
|
16
|
-
version = "2.0.0"
|
|
17
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
18
|
-
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
|
19
|
-
|
|
20
5
|
[[package]]
|
|
21
6
|
name = "aho-corasick"
|
|
22
7
|
version = "1.1.3"
|
|
@@ -110,21 +95,6 @@ version = "1.4.0"
|
|
|
110
95
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
111
96
|
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
|
112
97
|
|
|
113
|
-
[[package]]
|
|
114
|
-
name = "backtrace"
|
|
115
|
-
version = "0.3.75"
|
|
116
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
117
|
-
checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002"
|
|
118
|
-
dependencies = [
|
|
119
|
-
"addr2line",
|
|
120
|
-
"cfg-if",
|
|
121
|
-
"libc",
|
|
122
|
-
"miniz_oxide",
|
|
123
|
-
"object",
|
|
124
|
-
"rustc-demangle",
|
|
125
|
-
"windows-targets 0.52.6",
|
|
126
|
-
]
|
|
127
|
-
|
|
128
98
|
[[package]]
|
|
129
99
|
name = "base64"
|
|
130
100
|
version = "0.22.1"
|
|
@@ -260,7 +230,7 @@ dependencies = [
|
|
|
260
230
|
|
|
261
231
|
[[package]]
|
|
262
232
|
name = "devobs"
|
|
263
|
-
version = "0.
|
|
233
|
+
version = "0.2.0"
|
|
264
234
|
dependencies = [
|
|
265
235
|
"anyhow",
|
|
266
236
|
"assert_cmd",
|
|
@@ -272,6 +242,7 @@ dependencies = [
|
|
|
272
242
|
"regex",
|
|
273
243
|
"reqwest",
|
|
274
244
|
"rstest",
|
|
245
|
+
"serde",
|
|
275
246
|
"simplelog",
|
|
276
247
|
"strfmt",
|
|
277
248
|
"sugars",
|
|
@@ -462,12 +433,6 @@ dependencies = [
|
|
|
462
433
|
"wasi 0.14.2+wasi-0.2.4",
|
|
463
434
|
]
|
|
464
435
|
|
|
465
|
-
[[package]]
|
|
466
|
-
name = "gimli"
|
|
467
|
-
version = "0.31.1"
|
|
468
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
469
|
-
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
|
470
|
-
|
|
471
436
|
[[package]]
|
|
472
437
|
name = "glob"
|
|
473
438
|
version = "0.3.2"
|
|
@@ -611,7 +576,7 @@ dependencies = [
|
|
|
611
576
|
"hyper",
|
|
612
577
|
"libc",
|
|
613
578
|
"pin-project-lite",
|
|
614
|
-
"socket2",
|
|
579
|
+
"socket2 0.5.9",
|
|
615
580
|
"tokio",
|
|
616
581
|
"tower-service",
|
|
617
582
|
"tracing",
|
|
@@ -819,15 +784,6 @@ version = "0.3.17"
|
|
|
819
784
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
820
785
|
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
|
821
786
|
|
|
822
|
-
[[package]]
|
|
823
|
-
name = "miniz_oxide"
|
|
824
|
-
version = "0.8.8"
|
|
825
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
826
|
-
checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
|
|
827
|
-
dependencies = [
|
|
828
|
-
"adler2",
|
|
829
|
-
]
|
|
830
|
-
|
|
831
787
|
[[package]]
|
|
832
788
|
name = "mio"
|
|
833
789
|
version = "1.0.4"
|
|
@@ -897,15 +853,6 @@ dependencies = [
|
|
|
897
853
|
"libc",
|
|
898
854
|
]
|
|
899
855
|
|
|
900
|
-
[[package]]
|
|
901
|
-
name = "object"
|
|
902
|
-
version = "0.36.7"
|
|
903
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
904
|
-
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
|
|
905
|
-
dependencies = [
|
|
906
|
-
"memchr",
|
|
907
|
-
]
|
|
908
|
-
|
|
909
856
|
[[package]]
|
|
910
857
|
name = "once_cell"
|
|
911
858
|
version = "1.21.3"
|
|
@@ -1095,9 +1042,9 @@ dependencies = [
|
|
|
1095
1042
|
|
|
1096
1043
|
[[package]]
|
|
1097
1044
|
name = "regex"
|
|
1098
|
-
version = "1.
|
|
1045
|
+
version = "1.12.2"
|
|
1099
1046
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1100
|
-
checksum = "
|
|
1047
|
+
checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4"
|
|
1101
1048
|
dependencies = [
|
|
1102
1049
|
"aho-corasick",
|
|
1103
1050
|
"memchr",
|
|
@@ -1107,9 +1054,9 @@ dependencies = [
|
|
|
1107
1054
|
|
|
1108
1055
|
[[package]]
|
|
1109
1056
|
name = "regex-automata"
|
|
1110
|
-
version = "0.4.
|
|
1057
|
+
version = "0.4.13"
|
|
1111
1058
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1112
|
-
checksum = "
|
|
1059
|
+
checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c"
|
|
1113
1060
|
dependencies = [
|
|
1114
1061
|
"aho-corasick",
|
|
1115
1062
|
"memchr",
|
|
@@ -1188,21 +1135,20 @@ dependencies = [
|
|
|
1188
1135
|
|
|
1189
1136
|
[[package]]
|
|
1190
1137
|
name = "rstest"
|
|
1191
|
-
version = "0.
|
|
1138
|
+
version = "0.26.1"
|
|
1192
1139
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1193
|
-
checksum = "
|
|
1140
|
+
checksum = "f5a3193c063baaa2a95a33f03035c8a72b83d97a54916055ba22d35ed3839d49"
|
|
1194
1141
|
dependencies = [
|
|
1195
1142
|
"futures-timer",
|
|
1196
1143
|
"futures-util",
|
|
1197
1144
|
"rstest_macros",
|
|
1198
|
-
"rustc_version",
|
|
1199
1145
|
]
|
|
1200
1146
|
|
|
1201
1147
|
[[package]]
|
|
1202
1148
|
name = "rstest_macros"
|
|
1203
|
-
version = "0.
|
|
1149
|
+
version = "0.26.1"
|
|
1204
1150
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1205
|
-
checksum = "
|
|
1151
|
+
checksum = "9c845311f0ff7951c5506121a9ad75aec44d083c31583b2ea5a30bcb0b0abba0"
|
|
1206
1152
|
dependencies = [
|
|
1207
1153
|
"cfg-if",
|
|
1208
1154
|
"glob",
|
|
@@ -1216,12 +1162,6 @@ dependencies = [
|
|
|
1216
1162
|
"unicode-ident",
|
|
1217
1163
|
]
|
|
1218
1164
|
|
|
1219
|
-
[[package]]
|
|
1220
|
-
name = "rustc-demangle"
|
|
1221
|
-
version = "0.1.24"
|
|
1222
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1223
|
-
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
|
1224
|
-
|
|
1225
1165
|
[[package]]
|
|
1226
1166
|
name = "rustc_version"
|
|
1227
1167
|
version = "0.4.1"
|
|
@@ -1344,18 +1284,28 @@ checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
|
|
|
1344
1284
|
|
|
1345
1285
|
[[package]]
|
|
1346
1286
|
name = "serde"
|
|
1347
|
-
version = "1.0.
|
|
1287
|
+
version = "1.0.228"
|
|
1348
1288
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1349
|
-
checksum = "
|
|
1289
|
+
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
|
1290
|
+
dependencies = [
|
|
1291
|
+
"serde_core",
|
|
1292
|
+
"serde_derive",
|
|
1293
|
+
]
|
|
1294
|
+
|
|
1295
|
+
[[package]]
|
|
1296
|
+
name = "serde_core"
|
|
1297
|
+
version = "1.0.228"
|
|
1298
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1299
|
+
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
|
1350
1300
|
dependencies = [
|
|
1351
1301
|
"serde_derive",
|
|
1352
1302
|
]
|
|
1353
1303
|
|
|
1354
1304
|
[[package]]
|
|
1355
1305
|
name = "serde_derive"
|
|
1356
|
-
version = "1.0.
|
|
1306
|
+
version = "1.0.228"
|
|
1357
1307
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1358
|
-
checksum = "
|
|
1308
|
+
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
|
1359
1309
|
dependencies = [
|
|
1360
1310
|
"proc-macro2",
|
|
1361
1311
|
"quote",
|
|
@@ -1443,6 +1393,16 @@ dependencies = [
|
|
|
1443
1393
|
"windows-sys 0.52.0",
|
|
1444
1394
|
]
|
|
1445
1395
|
|
|
1396
|
+
[[package]]
|
|
1397
|
+
name = "socket2"
|
|
1398
|
+
version = "0.6.0"
|
|
1399
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1400
|
+
checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807"
|
|
1401
|
+
dependencies = [
|
|
1402
|
+
"libc",
|
|
1403
|
+
"windows-sys 0.59.0",
|
|
1404
|
+
]
|
|
1405
|
+
|
|
1446
1406
|
[[package]]
|
|
1447
1407
|
name = "stable_deref_trait"
|
|
1448
1408
|
version = "1.2.0"
|
|
@@ -1527,15 +1487,15 @@ dependencies = [
|
|
|
1527
1487
|
|
|
1528
1488
|
[[package]]
|
|
1529
1489
|
name = "tempfile"
|
|
1530
|
-
version = "3.
|
|
1490
|
+
version = "3.23.0"
|
|
1531
1491
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1532
|
-
checksum = "
|
|
1492
|
+
checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16"
|
|
1533
1493
|
dependencies = [
|
|
1534
1494
|
"fastrand",
|
|
1535
1495
|
"getrandom 0.3.3",
|
|
1536
1496
|
"once_cell",
|
|
1537
1497
|
"rustix",
|
|
1538
|
-
"windows-sys 0.
|
|
1498
|
+
"windows-sys 0.61.2",
|
|
1539
1499
|
]
|
|
1540
1500
|
|
|
1541
1501
|
[[package]]
|
|
@@ -1598,27 +1558,26 @@ dependencies = [
|
|
|
1598
1558
|
|
|
1599
1559
|
[[package]]
|
|
1600
1560
|
name = "tokio"
|
|
1601
|
-
version = "1.
|
|
1561
|
+
version = "1.48.0"
|
|
1602
1562
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1603
|
-
checksum = "
|
|
1563
|
+
checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408"
|
|
1604
1564
|
dependencies = [
|
|
1605
|
-
"backtrace",
|
|
1606
1565
|
"bytes",
|
|
1607
1566
|
"libc",
|
|
1608
1567
|
"mio",
|
|
1609
1568
|
"parking_lot",
|
|
1610
1569
|
"pin-project-lite",
|
|
1611
1570
|
"signal-hook-registry",
|
|
1612
|
-
"socket2",
|
|
1571
|
+
"socket2 0.6.0",
|
|
1613
1572
|
"tokio-macros",
|
|
1614
|
-
"windows-sys 0.
|
|
1573
|
+
"windows-sys 0.61.2",
|
|
1615
1574
|
]
|
|
1616
1575
|
|
|
1617
1576
|
[[package]]
|
|
1618
1577
|
name = "tokio-macros"
|
|
1619
|
-
version = "2.
|
|
1578
|
+
version = "2.6.0"
|
|
1620
1579
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1621
|
-
checksum = "
|
|
1580
|
+
checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5"
|
|
1622
1581
|
dependencies = [
|
|
1623
1582
|
"proc-macro2",
|
|
1624
1583
|
"quote",
|
|
@@ -1897,6 +1856,12 @@ version = "0.1.1"
|
|
|
1897
1856
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1898
1857
|
checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
|
|
1899
1858
|
|
|
1859
|
+
[[package]]
|
|
1860
|
+
name = "windows-link"
|
|
1861
|
+
version = "0.2.1"
|
|
1862
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1863
|
+
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
|
1864
|
+
|
|
1900
1865
|
[[package]]
|
|
1901
1866
|
name = "windows-registry"
|
|
1902
1867
|
version = "0.4.0"
|
|
@@ -1914,7 +1879,7 @@ version = "0.3.4"
|
|
|
1914
1879
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1915
1880
|
checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
|
|
1916
1881
|
dependencies = [
|
|
1917
|
-
"windows-link",
|
|
1882
|
+
"windows-link 0.1.1",
|
|
1918
1883
|
]
|
|
1919
1884
|
|
|
1920
1885
|
[[package]]
|
|
@@ -1923,7 +1888,7 @@ version = "0.3.1"
|
|
|
1923
1888
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1924
1889
|
checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319"
|
|
1925
1890
|
dependencies = [
|
|
1926
|
-
"windows-link",
|
|
1891
|
+
"windows-link 0.1.1",
|
|
1927
1892
|
]
|
|
1928
1893
|
|
|
1929
1894
|
[[package]]
|
|
@@ -1944,6 +1909,15 @@ dependencies = [
|
|
|
1944
1909
|
"windows-targets 0.52.6",
|
|
1945
1910
|
]
|
|
1946
1911
|
|
|
1912
|
+
[[package]]
|
|
1913
|
+
name = "windows-sys"
|
|
1914
|
+
version = "0.61.2"
|
|
1915
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1916
|
+
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
|
1917
|
+
dependencies = [
|
|
1918
|
+
"windows-link 0.2.1",
|
|
1919
|
+
]
|
|
1920
|
+
|
|
1947
1921
|
[[package]]
|
|
1948
1922
|
name = "windows-targets"
|
|
1949
1923
|
version = "0.52.6"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "devobs"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.2.0"
|
|
4
4
|
edition = "2024"
|
|
5
5
|
description = "CLI for obsessed developers."
|
|
6
6
|
readme = "README.md"
|
|
@@ -12,17 +12,18 @@ license = "MIT"
|
|
|
12
12
|
clap = { version = "4.5.38", features = ["derive"] }
|
|
13
13
|
glob = "0.3.2"
|
|
14
14
|
log = "0.4.27"
|
|
15
|
-
regex = "1.
|
|
15
|
+
regex = "1.12.2"
|
|
16
16
|
simplelog = "0.12.2"
|
|
17
17
|
strfmt = "0.2.4"
|
|
18
|
-
tokio = { version = "1.
|
|
18
|
+
tokio = { version = "1.48.0", features = ["full"] }
|
|
19
19
|
anyhow = "1.0.86"
|
|
20
20
|
sugars = "3.0.1"
|
|
21
|
+
serde = { version = "1.0.228", features = ["derive"] }
|
|
21
22
|
|
|
22
23
|
[dev-dependencies]
|
|
23
24
|
assert_cmd = "2.0.17"
|
|
24
25
|
insta = "1.43.1"
|
|
25
26
|
mockall = "0.13.0"
|
|
26
27
|
reqwest = "0.12.5"
|
|
27
|
-
rstest = "0.
|
|
28
|
-
tempfile = "3.
|
|
28
|
+
rstest = "0.26.1"
|
|
29
|
+
tempfile = "3.23.0"
|
|
@@ -28,7 +28,8 @@ update: ## Update deps and tools
|
|
|
28
28
|
.PHONY: update
|
|
29
29
|
|
|
30
30
|
run: ## Run development application
|
|
31
|
-
|
|
31
|
+
read -p "Enter command line arguments: " args
|
|
32
|
+
cargo watch --exec "run -- --log-level debug $$args"
|
|
32
33
|
.PHONY: run
|
|
33
34
|
|
|
34
35
|
|
|
@@ -51,6 +52,5 @@ lint: ## Run linters
|
|
|
51
52
|
test: ## Run tests
|
|
52
53
|
cargo llvm-cov nextest --workspace --lcov --output-path lcov.info \
|
|
53
54
|
&& cargo llvm-cov report --summary-only
|
|
54
|
-
|
|
55
55
|
cargo insta accept
|
|
56
56
|
.PHONY: test
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: devobs
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: CLI for obsessed developers.
|
|
5
5
|
Home-Page: https://github.com/lasuillard/devobs
|
|
6
6
|
Author: Yuchan Lee <lasuillard@gmail.com>
|
|
@@ -11,8 +11,8 @@ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
|
11
11
|
# devobs
|
|
12
12
|
|
|
13
13
|
[](https://opensource.org/licenses/MIT)
|
|
14
|
-
[](https://codecov.io/gh/lasuillard-s/devobs)
|
|
15
|
+
[](https://pypi.org/project/devobs/)
|
|
16
16
|
|
|
17
17
|
CLI for obsessed developers.
|
|
18
18
|
|
devobs-0.2.0/README.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# devobs
|
|
2
|
+
|
|
3
|
+
[](https://opensource.org/licenses/MIT)
|
|
4
|
+
[](https://codecov.io/gh/lasuillard-s/devobs)
|
|
5
|
+
[](https://pypi.org/project/devobs/)
|
|
6
|
+
|
|
7
|
+
CLI for obsessed developers.
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
use std::{fs::File,
|
|
2
|
+
hash::{DefaultHasher, Hash, Hasher},
|
|
3
|
+
io::Read,
|
|
4
|
+
path::{PathBuf, absolute}};
|
|
5
|
+
|
|
6
|
+
use anyhow::{Result, bail};
|
|
7
|
+
use clap::{Args, ValueEnum};
|
|
8
|
+
use serde::Serialize;
|
|
9
|
+
|
|
10
|
+
use crate::{GlobalOpts, utils::fs::list_files};
|
|
11
|
+
|
|
12
|
+
const BUFFER_SIZE: usize = 8192;
|
|
13
|
+
|
|
14
|
+
#[derive(ValueEnum, Clone, Debug, Serialize, Default)]
|
|
15
|
+
#[serde(rename_all = "kebab-case")]
|
|
16
|
+
enum OnCommandError {
|
|
17
|
+
/// Exit the program with the original error
|
|
18
|
+
#[default]
|
|
19
|
+
Propagate,
|
|
20
|
+
|
|
21
|
+
/// Ignore the error and continue
|
|
22
|
+
Ignore,
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// NOTE: This command does not support dry-run mode, as there is no state change involved (except hash file).
|
|
26
|
+
/// Detects changes in the target directory by comparing file hashes before and after running a command.
|
|
27
|
+
/// Raises an error if any changes are detected.
|
|
28
|
+
#[derive(Args, Debug, Clone)]
|
|
29
|
+
pub(crate) struct CommandArgs {
|
|
30
|
+
/// Target directory to watch for changes.
|
|
31
|
+
#[arg(long)]
|
|
32
|
+
target: String,
|
|
33
|
+
|
|
34
|
+
/// List of glob patterns to include files from the `target` directory.
|
|
35
|
+
///
|
|
36
|
+
/// This option can be specified multiple times or as a comma-separated list.
|
|
37
|
+
#[arg(long, num_args = 1.., value_delimiter = ',', default_value = "**/*")]
|
|
38
|
+
include: Vec<String>,
|
|
39
|
+
|
|
40
|
+
/// List of glob patterns to exclude files from the `target` directory.
|
|
41
|
+
///
|
|
42
|
+
/// This option can be specified multiple times or as a comma-separated list.
|
|
43
|
+
#[arg(long, num_args = 1.., value_delimiter = ',')]
|
|
44
|
+
exclude: Vec<String>,
|
|
45
|
+
|
|
46
|
+
/// Error handling strategy for the command.
|
|
47
|
+
#[arg(long, default_value_t, value_enum)]
|
|
48
|
+
on_command_error: OnCommandError,
|
|
49
|
+
|
|
50
|
+
/// Command to run. First hash is computed before running the command, second hash after.
|
|
51
|
+
/// If the hashes differ, an error is raised.
|
|
52
|
+
#[arg(trailing_var_arg = true)]
|
|
53
|
+
command: Vec<String>,
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
pub(crate) fn command(args: CommandArgs, _global_opts: GlobalOpts) -> Result<()> {
|
|
57
|
+
// Prepare arguments
|
|
58
|
+
let target = absolute(PathBuf::from(&args.target))?;
|
|
59
|
+
if !target.exists() {
|
|
60
|
+
bail!("Target path does not exist: {}", target.display());
|
|
61
|
+
}
|
|
62
|
+
if args.command.is_empty() {
|
|
63
|
+
bail!("No command specified to run.");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Calculate hash
|
|
67
|
+
log::debug!("Calculating hash for: {}", target.display());
|
|
68
|
+
let before_hash = calculate_directory_hash(&target, &args.include, &args.exclude)?;
|
|
69
|
+
log::info!("Hash before command run: {}", before_hash);
|
|
70
|
+
|
|
71
|
+
// Run command
|
|
72
|
+
log::info!("Running command as child process: {:?}", args.command);
|
|
73
|
+
let mut child = std::process::Command::new(&args.command[0])
|
|
74
|
+
.args(&args.command[1..])
|
|
75
|
+
.spawn()?;
|
|
76
|
+
|
|
77
|
+
let status = child.wait()?;
|
|
78
|
+
log::debug!("Command exited with status: {:?}", status);
|
|
79
|
+
|
|
80
|
+
// Check for exit code
|
|
81
|
+
if !status.success() {
|
|
82
|
+
match args.on_command_error {
|
|
83
|
+
OnCommandError::Ignore => {
|
|
84
|
+
log::warn!(
|
|
85
|
+
"Command exited with non-zero status: {}, but ignoring as per configuration.",
|
|
86
|
+
status
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
OnCommandError::Propagate => {
|
|
90
|
+
if let Some(code) = status.code() {
|
|
91
|
+
log::warn!(
|
|
92
|
+
"Command exited with non-zero status: {}, propagating exit code.",
|
|
93
|
+
code
|
|
94
|
+
);
|
|
95
|
+
std::process::exit(code);
|
|
96
|
+
} else {
|
|
97
|
+
bail!("Command terminated by signal");
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Calculate hash again
|
|
104
|
+
let after_hash = calculate_directory_hash(&target, &args.include, &args.exclude)?;
|
|
105
|
+
log::info!("Hash after command run: {}", after_hash);
|
|
106
|
+
|
|
107
|
+
// Compare hashes
|
|
108
|
+
if before_hash != after_hash {
|
|
109
|
+
bail!(
|
|
110
|
+
"Hash has changed after running command: {} != {}",
|
|
111
|
+
before_hash,
|
|
112
|
+
after_hash
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// No changes detected
|
|
117
|
+
log::info!("Target hash matches, no changes detected.");
|
|
118
|
+
Ok(())
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// NOTE: There is more performant library [merkle_hash](https://github.com/hristogochev/merkle_hash) exists,
|
|
122
|
+
// but using our version here for more control over hashing process (hasher, include/exclude patterns, etc.)
|
|
123
|
+
// TODO(lasuillard): `DefaultHasher` may change between Rust versions, consider replacing it with more stable hasher
|
|
124
|
+
// IF speed becomes an issue, for large file handling (BLAKE3 or xxHash)
|
|
125
|
+
fn calculate_directory_hash(
|
|
126
|
+
path: &PathBuf,
|
|
127
|
+
include: &[String],
|
|
128
|
+
exclude: &[String],
|
|
129
|
+
) -> Result<String> {
|
|
130
|
+
log::debug!(
|
|
131
|
+
"Calculating hash for directory: {}; include: {:?}, exclude: {:?}",
|
|
132
|
+
path.display(),
|
|
133
|
+
include,
|
|
134
|
+
exclude
|
|
135
|
+
);
|
|
136
|
+
let mut hasher = DefaultHasher::new();
|
|
137
|
+
let mut buffer = [0; BUFFER_SIZE];
|
|
138
|
+
for path in list_files(&path, &include, &exclude) {
|
|
139
|
+
// ? Should take account directory structure in the hash?
|
|
140
|
+
if path.is_dir() {
|
|
141
|
+
log::debug!("Skipping directory: {}", path.display());
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
log::debug!("Calculating hash for file: {}", path.display());
|
|
146
|
+
let mut file = File::open(path)?;
|
|
147
|
+
loop {
|
|
148
|
+
let bytes_read = file.read(&mut buffer)?;
|
|
149
|
+
if bytes_read == 0 {
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
buffer[..bytes_read].hash(&mut hasher);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
let hash = hasher.finish();
|
|
156
|
+
let hash_as_hex = format!("{:x}", hash);
|
|
157
|
+
Ok(hash_as_hex)
|
|
158
|
+
}
|
|
@@ -12,7 +12,7 @@ use crate::{GlobalOpts,
|
|
|
12
12
|
|
|
13
13
|
/// Check for matching file exists.
|
|
14
14
|
#[derive(Args, Debug, Clone)]
|
|
15
|
-
pub struct CommandArgs {
|
|
15
|
+
pub(crate) struct CommandArgs {
|
|
16
16
|
/// Directory to check for matching files.
|
|
17
17
|
#[arg(long)]
|
|
18
18
|
from: String,
|
|
@@ -33,6 +33,7 @@ pub struct CommandArgs {
|
|
|
33
33
|
#[arg(long, num_args = 1.., value_delimiter = ',')]
|
|
34
34
|
exclude: Vec<String>,
|
|
35
35
|
|
|
36
|
+
// * Don't forget to update below doc when modifying available variables
|
|
36
37
|
/// Expected pattern for the file in the `to` directory.
|
|
37
38
|
///
|
|
38
39
|
/// Variables available for substitution:
|