Compare commits

...

7 commits
v0.3.0 ... main

Author SHA1 Message Date
31e76661f4 fix(cmd_sync): progress handler printing 2025-04-09 23:49:55 +09:00
qwjyh
e9c1872d79
Use git cli in sync subcommand, and make custom implementation optional (#27)
* new: add use_cl option and separate to function

* refactor: format

* new(sync): add option to use git cli

* change(sync)!: now it use git cli by default

* lint: remove unnecessary ref

* fix(sync): use stderr for log prints

* update: CHANGELOG
2025-03-02 11:20:19 +09:00
851c0259a1 post v0.4.0 2025-03-01 10:19:59 +09:00
qwjyh
cdb01ee708
release 0.4.0 (#23)
* bump versions

* run cargo update

* update: rust edition to 2024

* update: CHANGELOG
2025-03-01 09:57:08 +09:00
qwjyh
e3b1e77f7d
feat: add option to statically link openssl (#22)
* feat: add feature to statically link openssl and libgit2

* update CHANGELOG

* update CHANGELOG
2025-02-28 01:13:38 +09:00
qwjyh
bd8e2019fe
implement sync subcommand (#21)
* new(sync): implement sync subcommand (WIP)

TODO
- update CHANGELOG
- refactor sync func

* fix(sync): add pull (only fast forward)

* update(test): use sync command

The first sync from 2nd device didn't work, maybe due to that it is the
first push.

* refactor: separate push and pull to funcs

* refactor: change merge analysis match order

* refactor: add logs

* update: CHANGELOG

* fix: CHANGELOG was wrong
2025-02-27 02:56:39 +09:00
qwjyh
47b3a5e69d
fix: polluting gitconfig in integrated test (#20)
* fix: polluting gitconfig in integrated test

* debug(CI): add eprintln

* debug(CI): git config

* debug(CI): git init test

* fix(CI): command construction

* debug(CI): change workdir & add same config setup

* debug(CI): use libgit2

* debug(CI): return err at the end of test using libgit2

* debug(CI): change current_dir in git config

* fix(git): git config now gets local config

CI was failing since xdbm init didn't get local git config.

* debug: add trace log

* debug: increase log level in CI

* fix: getting gitconfig now respects local config

* debug(CI): clean up debugging codes

* fix(CI): add setup_gitconfig to two_devices test

* debug(CI): inspect git config

* fix(CI): add env var to allow setting git global config

* refactor(CI): remove unnecessary arg for setup_gitconfig

* update changelog
2025-02-09 08:39:57 +09:00
10 changed files with 710 additions and 248 deletions

View file

@ -8,6 +8,7 @@ on:
env:
CARGO_TERM_COLOR: always
XDBM_ENABLE_OVERWRITE_GITCONFIG: true
jobs:
build-and-lint:

View file

@ -1,5 +1,20 @@
# Changelog
## [Unreleased]
### Added
- Option to use `git` cli in `sync` subcommand. This is now the default (#27)
## [0.4.0] - 2025-03-01
### Added
- `sync` subcommand, which performs git pull (fast-forward) and push (#21)
- Feature `vendored-openssl` to statically link openssl and libgit2 (#22)
### Fixed
- Git local config is now looked up. (#20)
- Git global config will not be polluted in test by default. (#20)
## [0.3.0] - 2024-12-02
### Added
@ -39,7 +54,8 @@
- `backup done` subcommand
- `completion` subcommand
[Unreleased]: https://github.com/qwjyh/xdbm/compare/v0.3.0...HEAD
[Unreleased]: https://github.com/qwjyh/xdbm/compare/v0.4.0...HEAD
[0.4.0]: https://github.com/qwjyh/xdbm/compare/v0.3.0...v0.4.0
[0.3.0]: https://github.com/qwjyh/xdbm/compare/v0.2.1...v0.3.0
[0.2.1]: https://github.com/qwjyh/xdbm/compare/v0.2.0...v0.2.1
[0.2.0]: https://github.com/qwjyh/xdbm/releases/tag/v0.2.0

394
Cargo.lock generated
View file

@ -8,7 +8,7 @@ version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9"
dependencies = [
"getrandom",
"getrandom 0.2.15",
"once_cell",
"version_check",
]
@ -78,19 +78,20 @@ dependencies = [
[[package]]
name = "anstyle-wincon"
version = "3.0.6"
version = "3.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e"
dependencies = [
"anstyle",
"once_cell",
"windows-sys 0.59.0",
]
[[package]]
name = "anyhow"
version = "1.0.93"
version = "1.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775"
checksum = "6b964d184e89d9b6b67dd2715bc8e74cf3107fb2b529990c90cf517326150bf4"
[[package]]
name = "arrayvec"
@ -143,9 +144,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.6.0"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
[[package]]
name = "bitvec"
@ -161,9 +162,9 @@ dependencies = [
[[package]]
name = "borsh"
version = "1.5.3"
version = "1.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2506947f73ad44e344215ccd6403ac2ae18cd8e046e581a441bf8d199f257f03"
checksum = "5430e3be710b68d984d1391c854eb431a9d548640711faa54eecb1df93db91cc"
dependencies = [
"borsh-derive",
"cfg_aliases",
@ -171,22 +172,22 @@ dependencies = [
[[package]]
name = "borsh-derive"
version = "1.5.3"
version = "1.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2593a3b8b938bd68373196c9832f516be11fa487ef4ae745eb282e6a56a7244"
checksum = "f8b668d39970baad5356d7c83a86fee3a539e6f93bf6764c97368243e17a0487"
dependencies = [
"once_cell",
"proc-macro-crate",
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
]
[[package]]
name = "bstr"
version = "1.11.0"
version = "1.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a68f1f47cdf0ec8ee4b941b2eee2a80cb796db73118c0dd09ac63fbe405be22"
checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0"
dependencies = [
"memchr",
"regex-automata",
@ -195,9 +196,9 @@ dependencies = [
[[package]]
name = "bumpalo"
version = "3.16.0"
version = "3.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
[[package]]
name = "byte-unit"
@ -240,15 +241,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
version = "1.9.0"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b"
checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9"
[[package]]
name = "cc"
version = "1.2.2"
version = "1.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc"
checksum = "c736e259eea577f443d5c86c304f9f4ae0295c43f3ba05c21f1d66b5f06001af"
dependencies = [
"jobserver",
"libc",
@ -269,9 +270,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]]
name = "chrono"
version = "0.4.38"
version = "0.4.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
dependencies = [
"android-tzdata",
"iana-time-zone",
@ -279,14 +280,14 @@ dependencies = [
"num-traits",
"serde",
"wasm-bindgen",
"windows-targets 0.52.6",
"windows-link",
]
[[package]]
name = "clap"
version = "4.5.21"
version = "4.5.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f"
checksum = "027bb0d98429ae334a8698531da7077bdf906419543a35a55c2cb1b66437d767"
dependencies = [
"clap_builder",
"clap_derive",
@ -294,9 +295,9 @@ dependencies = [
[[package]]
name = "clap-verbosity-flag"
version = "3.0.1"
version = "3.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54381ae56ad222eea3f529c692879e9c65e07945ae48d3dc4d1cb18dbec8cf44"
checksum = "2678fade3b77aa3a8ff3aae87e9c008d3fb00473a41c71fbf74e91c8c7b37e84"
dependencies = [
"clap",
"log",
@ -304,9 +305,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.21"
version = "4.5.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec"
checksum = "5589e0cba072e0f3d23791efac0fd8627b49c829c196a492e88168e6a669d863"
dependencies = [
"anstream",
"anstyle",
@ -316,30 +317,30 @@ dependencies = [
[[package]]
name = "clap_complete"
version = "4.5.38"
version = "4.5.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9647a559c112175f17cf724dc72d3645680a883c58481332779192b0d8e7a01"
checksum = "f5c5508ea23c5366f77e53f5a0070e5a84e51687ec3ef9e0464c86dc8d13ce98"
dependencies = [
"clap",
]
[[package]]
name = "clap_derive"
version = "4.5.18"
version = "4.5.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
]
[[package]]
name = "clap_lex"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7"
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
[[package]]
name = "colorchoice"
@ -349,15 +350,15 @@ checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]]
name = "console"
version = "0.15.8"
version = "0.15.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
checksum = "ea3c6ecd8059b57859df5c69830340ed3c41d30e3da0c1cbed90a96ac853041b"
dependencies = [
"encode_unicode",
"lazy_static",
"libc",
"unicode-width 0.1.14",
"windows-sys 0.52.0",
"once_cell",
"unicode-width 0.2.0",
"windows-sys 0.59.0",
]
[[package]]
@ -368,9 +369,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]]
name = "crossbeam-deque"
version = "0.8.5"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
@ -387,9 +388,9 @@ dependencies = [
[[package]]
name = "crossbeam-utils"
version = "0.8.20"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
name = "crossterm"
@ -451,7 +452,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
]
[[package]]
@ -468,27 +469,27 @@ checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
[[package]]
name = "dyn-clone"
version = "1.0.17"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125"
checksum = "feeef44e73baff3a26d371801df019877a9866a8c493d315ab00177843314f35"
[[package]]
name = "either"
version = "1.13.0"
version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
checksum = "b7914353092ddf589ad78f25c5c1c21b7f80b0ff8621e7c814c3485b5306da9d"
[[package]]
name = "encode_unicode"
version = "0.3.6"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
[[package]]
name = "env_filter"
version = "0.1.2"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab"
checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0"
dependencies = [
"log",
"regex",
@ -496,9 +497,9 @@ dependencies = [
[[package]]
name = "env_logger"
version = "0.11.5"
version = "0.11.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d"
checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0"
dependencies = [
"anstream",
"anstyle",
@ -509,9 +510,9 @@ dependencies = [
[[package]]
name = "equivalent"
version = "1.0.1"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "errno"
@ -525,15 +526,15 @@ dependencies = [
[[package]]
name = "fastrand"
version = "2.2.0"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4"
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
[[package]]
name = "float-cmp"
version = "0.9.0"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4"
checksum = "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8"
dependencies = [
"num-traits",
]
@ -579,7 +580,19 @@ checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
"libc",
"wasi",
"wasi 0.11.0+wasi-snapshot-preview1",
]
[[package]]
name = "getrandom"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8"
dependencies = [
"cfg-if",
"libc",
"wasi 0.13.3+wasi-0.2.2",
"windows-targets 0.52.6",
]
[[package]]
@ -588,7 +601,7 @@ version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b903b73e45dc0c6c596f2d37eccece7c1c8bb6e4407b001096387c63d0d93724"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.8.0",
"libc",
"libgit2-sys",
"log",
@ -616,7 +629,7 @@ version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.8.0",
"ignore",
"walkdir",
]
@ -786,7 +799,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
]
[[package]]
@ -828,9 +841,9 @@ dependencies = [
[[package]]
name = "indexmap"
version = "2.7.0"
version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652"
dependencies = [
"equivalent",
"hashbrown 0.15.2",
@ -842,7 +855,7 @@ version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fddf93031af70e75410a2511ec04d49e758ed2f26dad3404a934e0fb45cc12a"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.8.0",
"crossterm",
"dyn-clone",
"fuzzy-matcher",
@ -876,25 +889,19 @@ dependencies = [
[[package]]
name = "js-sys"
version = "0.3.74"
version = "0.3.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a865e038f7f6ed956f788f0d7d60c541fff74c7bd74272c5d4cf15c63743e705"
checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
dependencies = [
"once_cell",
"wasm-bindgen",
]
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
version = "0.2.167"
version = "0.2.170"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc"
checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828"
[[package]]
name = "libgit2-sys"
@ -916,15 +923,15 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.8.0",
"libc",
]
[[package]]
name = "libssh2-sys"
version = "0.3.0"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dc8a030b787e2119a731f1951d6a773e2280c660f8ec4b0f5e1505a386e71ee"
checksum = "220e4f05ad4a218192533b300327f5150e809b54c4ec83b5a1d91833601811b9"
dependencies = [
"cc",
"libc",
@ -936,9 +943,9 @@ dependencies = [
[[package]]
name = "libz-sys"
version = "1.1.20"
version = "1.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472"
checksum = "df9b68e50e6e0b26f672573834882eb57759f6db9b3be2ea3c35c91188bb4eaa"
dependencies = [
"cc",
"libc",
@ -948,9 +955,9 @@ dependencies = [
[[package]]
name = "linux-raw-sys"
version = "0.4.14"
version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
[[package]]
name = "litemap"
@ -970,9 +977,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.22"
version = "0.4.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e"
[[package]]
name = "memchr"
@ -988,7 +995,7 @@ checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
dependencies = [
"libc",
"log",
"wasi",
"wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys 0.48.0",
]
@ -1027,24 +1034,34 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.20.2"
version = "1.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e"
[[package]]
name = "openssl-probe"
version = "0.1.5"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
[[package]]
name = "openssl-src"
version = "300.4.2+3.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "168ce4e058f975fe43e89d9ccf78ca668601887ae736090aacc23ae353c298e2"
dependencies = [
"cc",
]
[[package]]
name = "openssl-sys"
version = "0.9.104"
version = "0.9.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741"
checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd"
dependencies = [
"cc",
"libc",
"openssl-src",
"pkg-config",
"vcpkg",
]
@ -1107,9 +1124,9 @@ dependencies = [
[[package]]
name = "predicates"
version = "3.1.2"
version = "3.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e9086cc7640c29a356d1a29fd134380bee9d8f79a17410aa76e7ad295f42c97"
checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573"
dependencies = [
"anstyle",
"difflib",
@ -1121,15 +1138,15 @@ dependencies = [
[[package]]
name = "predicates-core"
version = "1.0.8"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae8177bee8e75d6846599c6b9ff679ed51e882816914eec639944d7c9aa11931"
checksum = "727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa"
[[package]]
name = "predicates-tree"
version = "1.0.11"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41b740d195ed3166cd147c8047ec98db0e22ec019eb8eeb76d343b795304fb13"
checksum = "72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c"
dependencies = [
"predicates-core",
"termtree",
@ -1146,9 +1163,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.92"
version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
dependencies = [
"unicode-ident",
]
@ -1175,9 +1192,9 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.37"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
dependencies = [
"proc-macro2",
]
@ -1215,7 +1232,7 @@ version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
"getrandom 0.2.15",
]
[[package]]
@ -1240,11 +1257,11 @@ dependencies = [
[[package]]
name = "redox_syscall"
version = "0.5.7"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
checksum = "82b568323e98e49e2a0899dcee453dd679fae22d69adf9b11dd508d1549b7e2f"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.8.0",
]
[[package]]
@ -1253,7 +1270,7 @@ version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
dependencies = [
"getrandom",
"getrandom 0.2.15",
"libredox",
"thiserror",
]
@ -1343,22 +1360,28 @@ dependencies = [
[[package]]
name = "rustix"
version = "0.38.41"
version = "0.38.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6"
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.8.0",
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.52.0",
"windows-sys 0.59.0",
]
[[package]]
name = "ryu"
version = "1.0.18"
name = "rustversion"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
[[package]]
name = "ryu"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd"
[[package]]
name = "same-file"
@ -1383,29 +1406,29 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
[[package]]
name = "serde"
version = "1.0.215"
version = "1.0.218"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.215"
version = "1.0.218"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
]
[[package]]
name = "serde_json"
version = "1.0.133"
version = "1.0.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377"
checksum = "44f86c3acccc9c65b153fe1b85a3be07fe5515274ec9f0653b4a0875731c72a6"
dependencies = [
"itoa",
"memchr",
@ -1470,9 +1493,9 @@ checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
[[package]]
name = "smallvec"
version = "1.13.2"
version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd"
[[package]]
name = "stable_deref_trait"
@ -1499,9 +1522,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.90"
version = "2.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1"
dependencies = [
"proc-macro2",
"quote",
@ -1516,7 +1539,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
]
[[package]]
@ -1542,12 +1565,13 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]]
name = "tempfile"
version = "3.14.0"
version = "3.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c"
checksum = "22e5a0acb1f3f55f65cc4a866c361b2fb2a0ff6366785ae6fbb5f85df07ba230"
dependencies = [
"cfg-if",
"fastrand",
"getrandom 0.3.1",
"once_cell",
"rustix",
"windows-sys 0.59.0",
@ -1555,9 +1579,9 @@ dependencies = [
[[package]]
name = "termtree"
version = "0.4.1"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76"
checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683"
[[package]]
name = "thiserror"
@ -1576,7 +1600,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
]
[[package]]
@ -1601,9 +1625,9 @@ dependencies = [
[[package]]
name = "tinyvec"
version = "1.8.0"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938"
checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8"
dependencies = [
"tinyvec_macros",
]
@ -1622,9 +1646,9 @@ checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
[[package]]
name = "toml_edit"
version = "0.22.22"
version = "0.22.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474"
dependencies = [
"indexmap",
"toml_datetime",
@ -1633,9 +1657,9 @@ dependencies = [
[[package]]
name = "unicode-ident"
version = "1.0.14"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe"
[[package]]
name = "unicode-segmentation"
@ -1698,9 +1722,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "uuid"
version = "1.11.0"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a"
checksum = "bd8dcafa1ca14750d8d7a05aa05988c17aab20886e1f3ae33a40223c58d92ef7"
[[package]]
name = "vcpkg"
@ -1716,9 +1740,9 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "wait-timeout"
version = "0.2.0"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11"
dependencies = [
"libc",
]
@ -1740,36 +1764,45 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.97"
name = "wasi"
version = "0.13.3+wasi-0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d15e63b4482863c109d70a7b8706c1e364eb6ea449b201a76c5b89cedcec2d5c"
checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2"
dependencies = [
"wit-bindgen-rt",
]
[[package]]
name = "wasm-bindgen"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
dependencies = [
"cfg-if",
"once_cell",
"rustversion",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.97"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d36ef12e3aaca16ddd3f67922bc63e48e953f126de60bd33ccc0101ef9998cd"
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.97"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "705440e08b42d3e4b36de7d66c944be628d579796b8090bfa3471478a2260051"
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@ -1777,22 +1810,25 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.97"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98c9ae5a76e46f4deecd0f0255cc223cfa18dc9b261213b8aa0c7b36f61b3f1d"
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.97"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ee99da9c5ba11bd675621338ef6fa52296b76b83305e9b6e5c77d4c286d6d49"
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
dependencies = [
"unicode-ident",
]
[[package]]
name = "winapi"
@ -1864,7 +1900,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
]
[[package]]
@ -1875,9 +1911,15 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
]
[[package]]
name = "windows-link"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3"
[[package]]
name = "windows-result"
version = "0.1.2"
@ -1896,15 +1938,6 @@ dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.59.0"
@ -2037,13 +2070,22 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "winnow"
version = "0.6.20"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b"
checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1"
dependencies = [
"memchr",
]
[[package]]
name = "wit-bindgen-rt"
version = "0.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c"
dependencies = [
"bitflags 2.8.0",
]
[[package]]
name = "write16"
version = "1.0.0"
@ -2067,7 +2109,7 @@ dependencies = [
[[package]]
name = "xdbm"
version = "0.3.0"
version = "0.4.0"
dependencies = [
"anyhow",
"assert_cmd",
@ -2112,7 +2154,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
"synstructure",
]
@ -2134,7 +2176,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
]
[[package]]
@ -2154,7 +2196,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
"synstructure",
]
@ -2177,5 +2219,5 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
]

View file

@ -1,8 +1,8 @@
[package]
name = "xdbm"
version = "0.3.0"
version = "0.4.0"
authors = ["qwjyh <urataw421@gmail.com>"]
edition = "2021"
edition = "2024"
description = "Cross device backup manager, which manages backups on several storages mounted on multiple devices."
readme = "README.md"
homepage = "https://github.com/qwjyh/xdbm"
@ -36,3 +36,6 @@ console = "0.15"
assert_cmd = "2.0.16"
assert_fs = "1.1.2"
predicates = "3.1.2"
[features]
vendored-openssl = ["git2/vendored-openssl"]

View file

@ -1,7 +1,7 @@
//! CLI arguments
use crate::path;
use crate::PathBuf;
use crate::path;
use clap::Args;
use clap::{Parser, Subcommand};
use clap_verbosity_flag::Verbosity;
@ -63,6 +63,15 @@ pub(crate) enum Commands {
Sync {
/// Remote name to sync.
remote_name: Option<String>,
/// Use custom git implementation.
#[arg(short, long)]
use_libgit2: bool,
/// Whether to use ssh-agent
#[arg(long)]
use_sshagent: bool,
/// Manually specify ssh key
#[arg(long)]
ssh_key: Option<PathBuf>,
},
/// Check config files validity.

View file

@ -2,11 +2,13 @@
//! Initialize xdbm for the device.
use crate::backups::Backups;
use crate::storages::{Storages, STORAGESFILE};
use crate::storages::{STORAGESFILE, Storages};
use crate::{
add_and_commit, backups, full_status, get_devices, write_devices, Device, DEVICESFILE,
DEVICESFILE, Device, add_and_commit, backups,
devices::{get_devices, write_devices},
full_status,
};
use anyhow::{anyhow, Context, Ok, Result};
use anyhow::{Context, Ok, Result, anyhow};
use core::panic;
use git2::{Cred, RemoteCallbacks, Repository};
use inquire::Password;
@ -40,9 +42,7 @@ fn clone_repo(
}
};
Cred::ssh_key(
username_from_url
.context("No username found from the url")
.unwrap(),
username_from_url.ok_or(git2::Error::from_str("No username found from the url"))?,
None,
key as &Path,
passwd.as_deref(),
@ -51,9 +51,7 @@ fn clone_repo(
// use ssh agent
info!("Using ssh agent to access the repository");
Cred::ssh_key_from_agent(
username_from_url
.context("No username found from the url")
.unwrap(),
username_from_url.ok_or(git2::Error::from_str("No username found from the url"))?,
)
} else {
error!("no ssh_key and use_sshagent");

View file

@ -1,10 +1,79 @@
use std::path::PathBuf;
use std::{
io::{self, Write},
path::{Path, PathBuf},
process,
};
use anyhow::{anyhow, Result};
use git2::Repository;
use anyhow::{Context, Result, anyhow};
use git2::{Cred, FetchOptions, PushOptions, RemoteCallbacks, Repository, build::CheckoutBuilder};
pub(crate) fn cmd_sync(config_dir: &PathBuf, remote_name: Option<String>) -> Result<()> {
warn!("Experimental");
pub(crate) fn cmd_sync(
config_dir: &PathBuf,
remote_name: Option<String>,
use_sshagent: bool,
ssh_key: Option<PathBuf>,
use_libgit2: bool,
) -> Result<()> {
if use_libgit2 {
cmd_sync_custom(config_dir, remote_name, use_sshagent, ssh_key)
} else {
cmd_sync_cl(config_dir, remote_name, ssh_key)
}
}
fn cmd_sync_cl(
config_dir: &PathBuf,
remote_name: Option<String>,
ssh_key: Option<PathBuf>,
) -> Result<()> {
info!("cmd_sync (command line version)");
trace!("pull");
let args = |cmd| {
let mut args = vec![cmd];
if let Some(ref remote_name) = remote_name {
args.push(remote_name.clone());
}
if let Some(ref ssh_key) = ssh_key {
args.push("-i".to_string());
args.push(ssh_key.to_str().unwrap().to_owned());
}
args
};
let git_pull_result = process::Command::new("git")
.args(args("pull".to_owned()))
.current_dir(config_dir)
.status()
.context("error while executing git pull")?
.success();
if git_pull_result {
eprintln!("git pull completed");
} else {
return Err(anyhow!("failed to complete git pull"));
}
trace!("push");
let git_push_result = process::Command::new("git")
.args(args("push".to_owned()))
.current_dir(config_dir)
.status()
.context("error while executing git push")?
.success();
if git_push_result {
eprintln!("git push completed");
} else {
return Err(anyhow!("failed to complete git push"));
}
Ok(())
}
fn cmd_sync_custom(
config_dir: &PathBuf,
remote_name: Option<String>,
use_sshagent: bool,
ssh_key: Option<PathBuf>,
) -> Result<()> {
info!("cmd_sync");
let repo = Repository::open(config_dir)?;
let remote_name = match remote_name {
Some(remote_name) => remote_name,
@ -16,7 +85,252 @@ pub(crate) fn cmd_sync(config_dir: &PathBuf, remote_name: Option<String>) -> Res
remotes.get(0).unwrap().to_string()
}
};
debug!("resolved remote name: {remote_name}");
let mut remote = repo.find_remote(&remote_name)?;
remote.push(&[] as &[&str], None)?;
pull(
&repo,
&mut remote,
remote_name,
&use_sshagent,
ssh_key.as_ref(),
)?;
push(&repo, &mut remote, &use_sshagent, ssh_key.as_ref())?;
Ok(())
}
fn remote_callback<'b, 'a>(
use_sshagent: &'a bool,
ssh_key: Option<&'a PathBuf>,
) -> RemoteCallbacks<'a>
where
'b: 'a,
{
// using credentials
let mut callbacks = RemoteCallbacks::new();
callbacks
.credentials(move |_url, username_from_url, _allowed_types| {
if let Some(key) = ssh_key {
info!("Using provided ssh key to access the repository");
let passwd = match inquire::Password::new("SSH passphrase").prompt() {
std::result::Result::Ok(s) => Some(s),
Err(err) => {
error!("Failed to get ssh passphrase: {:?}", err);
None
}
};
Cred::ssh_key(
username_from_url
.ok_or(git2::Error::from_str("No username found from the url"))?,
None,
key as &Path,
passwd.as_deref(),
)
} else if *use_sshagent {
// use ssh agent
info!("Using ssh agent to access the repository");
Cred::ssh_key_from_agent(
username_from_url
.ok_or(git2::Error::from_str("No username found from the url"))?,
)
} else {
error!("no ssh_key and use_sshagent");
panic!("This option must be unreachable.")
}
})
.transfer_progress(|progress| {
if progress.received_objects() == progress.total_objects() {
print!(
"\rResolving deltas {}/{}",
progress.indexed_deltas(),
progress.total_deltas()
);
} else {
print!(
"\rReceived {}/{} objects ({}) in {} bytes",
progress.received_objects(),
progress.total_objects(),
progress.indexed_objects(),
progress.received_bytes(),
);
}
io::stderr().flush().unwrap();
true
})
.sideband_progress(|text| {
let msg = String::from_utf8_lossy(text);
eprintln!("remote: {msg}");
true
})
.push_transfer_progress(|current, total, bytes| {
trace!("{current}/{total} files sent \t{bytes} bytes");
})
.push_update_reference(|reference_name, status_msg| {
debug!("remote reference_name {reference_name}");
match status_msg {
None => {
info!("successfully pushed");
eprintln!("successfully pushed to {}", reference_name);
Ok(())
}
Some(status) => {
error!("failed to push: {}", status);
Err(git2::Error::from_str(&format!(
"failed to push to {}: {}",
reference_name, status
)))
}
}
});
callbacks
}
fn pull(
repo: &Repository,
remote: &mut git2::Remote,
remote_name: String,
use_sshagent: &bool,
ssh_key: Option<&PathBuf>,
) -> Result<()> {
debug!("pull");
let callbacks = remote_callback(use_sshagent, ssh_key);
let mut fetchoptions = FetchOptions::new();
fetchoptions.remote_callbacks(callbacks);
let fetch_refspec: Vec<String> = remote
.refspecs()
.filter_map(|rs| match rs.direction() {
git2::Direction::Fetch => rs.str().map(|s| s.to_string()),
git2::Direction::Push => None,
})
.collect();
remote
.fetch(&fetch_refspec, Some(&mut fetchoptions), None)
.context("Failed to fetch (pull)")?;
let stats = remote.stats();
if stats.local_objects() > 0 {
eprintln!(
"\rReceived {}/{} objects in {} bytes (used {} local objects)",
stats.indexed_objects(),
stats.total_objects(),
stats.received_bytes(),
stats.local_objects(),
);
} else {
eprintln!(
"\rReceived {}/{} objects in {} bytes",
stats.indexed_objects(),
stats.total_objects(),
stats.received_bytes(),
);
}
let fetch_head = repo
.reference_to_annotated_commit(
&repo
.resolve_reference_from_short_name(&remote_name)
.context("failed to get reference from fetch refspec")?,
)
.context("failed to get annotated commit")?;
let (merge_analysis, merge_preference) = repo
.merge_analysis(&[&fetch_head])
.context("failed to do merge_analysis")?;
trace!("merge analysis: {:?}", merge_analysis);
trace!("merge preference: {:?}", merge_preference);
match merge_analysis {
ma if ma.is_up_to_date() => {
info!("HEAD is up to date. skip merging");
}
ma if ma.is_fast_forward() => {
// https://github.com/rust-lang/git2-rs/blob/master/examples/pull.rs
info!("fast forward is available");
let mut ref_remote = repo
.find_reference(
remote
.default_branch()
.context("failed to get remote default branch")?
.as_str()
.unwrap(),
)
.context("failed to get remote reference")?;
let name = match ref_remote.name() {
Some(s) => s.to_string(),
None => String::from_utf8_lossy(ref_remote.name_bytes()).to_string(),
};
let msg = format!("Fast-Forward: Setting {} to id: {}", name, fetch_head.id());
eprintln!("{}", msg);
ref_remote
.set_target(fetch_head.id(), &msg)
.context("failed to set target")?;
repo.checkout_head(Some(CheckoutBuilder::default().force()))
.context("failed to checkout")?;
}
ma if ma.is_unborn() => {
warn!("HEAD is invalid (unborn)");
return Err(anyhow!(
"HEAD is invalid: merge_analysis: {:?}",
merge_analysis
));
}
ma if ma.is_none() => {
error!("no merge is possible");
return Err(anyhow!("no merge is possible"));
}
ma if ma.is_normal() => {
error!("unable to fast-forward. manual merge is required");
return Err(anyhow!("unable to fast-forward. manual merge is required"));
}
_ma => {
error!(
"this code must not reachable: merge_analysis {:?}",
merge_analysis
);
return Err(anyhow!("must not be reachabel (uncovered merge_analysis)"));
}
}
Ok(())
}
fn push(
repo: &Repository,
remote: &mut git2::Remote,
use_sshagent: &bool,
ssh_key: Option<&PathBuf>,
) -> Result<()> {
debug!("push");
let callbacks = remote_callback(use_sshagent, ssh_key);
let mut push_options = PushOptions::new();
push_options.remote_callbacks(callbacks);
let num_push_refspecs = remote
.refspecs()
.filter(|rs| rs.direction() == git2::Direction::Push)
.count();
if num_push_refspecs > 1 {
warn!("more than one push refspecs are configured");
warn!("using the first one");
}
let head = repo.head().context("Failed to get HEAD")?;
if num_push_refspecs >= 1 {
trace!("using push refspec");
let push_refspec = remote
.refspecs()
.filter_map(|rs| match rs.direction() {
git2::Direction::Fetch => None,
git2::Direction::Push => Some(rs),
})
.next()
.expect("this must be unreachabe")
.str()
.context("failed to get valid utf8 push refspec")?
.to_string();
remote.push(&[push_refspec.as_str()] as &[&str], Some(&mut push_options))?;
} else {
trace!("using head as push refspec");
trace!("head is branch: {:?}", head.is_branch());
trace!("head is remote: {:?}", head.is_remote());
let push_refspec = head.name().context("failed to get head name")?;
remote.push(&[push_refspec] as &[&str], Some(&mut push_options))?;
};
Ok(())
}

40
src/git.rs Normal file
View file

@ -0,0 +1,40 @@
use std::path::{Path, PathBuf};
use git2::{Cred, RemoteCallbacks};
use inquire::Password;
pub(crate) fn get_credential<'a>(
use_sshagent: bool,
ssh_key: Option<PathBuf>,
) -> RemoteCallbacks<'a> {
// using credentials
let mut callbacks = RemoteCallbacks::new();
callbacks.credentials(move |_url, username_from_url, _allowed_types| {
if let Some(key) = &ssh_key {
info!("Using provided ssh key to access the repository");
let passwd = match Password::new("SSH passphrase").prompt() {
std::result::Result::Ok(s) => Some(s),
Err(err) => {
error!("Failed to get ssh passphrase: {:?}", err);
None
}
};
Cred::ssh_key(
username_from_url.ok_or(git2::Error::from_str("No username found from the url"))?,
None,
key as &Path,
passwd.as_deref(),
)
} else if use_sshagent {
// use ssh agent
info!("Using ssh agent to access the repository");
Cred::ssh_key_from_agent(
username_from_url.ok_or(git2::Error::from_str("No username found from the url"))?,
)
} else {
error!("no ssh_key and use_sshagent");
panic!("This option must be unreachable.")
}
});
callbacks
}

View file

@ -23,7 +23,7 @@ use std::path::{self, PathBuf};
use storages::Storages;
use crate::cmd_args::{BackupSubCommands, Cli, Commands, StorageCommands};
use devices::{Device, DEVICESFILE, *};
use devices::{DEVICESFILE, Device};
mod backups;
mod cmd_args;
@ -35,6 +35,7 @@ mod cmd_status;
mod cmd_storage;
mod cmd_sync;
mod devices;
mod git;
mod inquire_filepath_completer;
mod storages;
mod util;
@ -91,7 +92,12 @@ fn main() -> Result<()> {
Commands::Path {} => {
println!("{}", &config_dir.display());
}
Commands::Sync { remote_name } => cmd_sync::cmd_sync(&config_dir, remote_name)?,
Commands::Sync {
remote_name,
use_libgit2,
use_sshagent,
ssh_key,
} => cmd_sync::cmd_sync(&config_dir, remote_name, use_sshagent, ssh_key, use_libgit2)?,
Commands::Status {
path,
storage,
@ -156,7 +162,7 @@ fn add_and_commit(repo: &Repository, path: &Path, message: &str) -> Result<Oid,
index.write()?;
let oid = index.write_tree()?;
let tree = repo.find_tree(oid)?;
let config = git2::Config::open_default()?;
let config = repo.config()?;
let signature = git2::Signature::now(
config.get_entry("user.name")?.value().unwrap(),
config.get_entry("user.email")?.value().unwrap(),

View file

@ -1,27 +1,62 @@
mod integrated_test {
use std::{
fs::{DirBuilder, File},
fs::{self, DirBuilder, File},
io::{self, BufWriter, Write},
path,
};
use anyhow::{Context, Ok, Result};
use assert_cmd::{assert::OutputAssertExt, Command};
use dirs::home_dir;
use anyhow::{Context, Ok, Result, anyhow};
use assert_cmd::{Command, assert::OutputAssertExt};
use git2::Repository;
use log::trace;
use log::{debug, trace};
use predicates::{boolean::PredicateBooleanExt, prelude::predicate};
const IS_GIT_CONFIG_WRITABLE: &str = "XDBM_ENABLE_OVERWRITE_GITCONFIG";
/// Setup global gitconfig if it doesn't exist.
///
/// # Errors
///
/// This function will return an error if it failed to get home directory.
/// This function will return an error if it failed to get git global config and environment
/// variable [XDBM_ENABLE_OVERWRITE_GITCONFIG](`IS_GIT_CONFIG_WRITABLE`) is not set.
fn setup_gitconfig() -> Result<()> {
let f = match File::create_new(
home_dir()
.context("Failed to find home directory")?
.join(".gitconfig"),
) {
let config = git2::Config::open_default().expect("failed to get default");
if config.get_string("user.name").is_ok() && config.get_string("user.email").is_ok() {
return Ok(());
};
match std::env::var_os(IS_GIT_CONFIG_WRITABLE) {
Some(_) => {
debug!(
"global git config not found & env var `{}` found",
IS_GIT_CONFIG_WRITABLE
);
}
None => {
eprintln!("Failed to get git global config");
eprintln!(
"Set env var `{}` to set automatically (mainly for CI)",
IS_GIT_CONFIG_WRITABLE
);
return Err(anyhow!("failed to get git global config"));
}
};
let config_file = git2::Config::find_global().map_or_else(
|e| {
trace!("global git config file not found: {e:?}");
Ok(dirs::home_dir()
.context("Failed to get home dir")?
.join(".gitconfig"))
},
Ok,
)?;
let f = match File::options()
.create(true)
.truncate(true)
.write(true)
.open(config_file)
{
io::Result::Ok(f) => f,
io::Result::Err(_err) => return Ok(()),
};
@ -38,6 +73,25 @@ mod integrated_test {
Ok(())
}
fn run_sync_cmd(config_dir: &path::Path, use_cl: bool) -> Result<()> {
if use_cl {
Command::cargo_bin("xdbm")?
.arg("-c")
.arg(config_dir)
.args(["sync", "-vvvv"])
.assert()
.success();
} else {
Command::cargo_bin("xdbm")?
.arg("-c")
.arg(config_dir)
.args(["sync", "-vvvv", "-u"])
.assert()
.success();
}
Ok(())
}
#[test]
fn single_device() -> Result<()> {
let config_dir = assert_fs::TempDir::new()?;
@ -47,8 +101,10 @@ mod integrated_test {
cmd.arg("-c")
.arg(config_dir.path())
.arg("init")
.arg("testdev");
.arg("testdev")
.arg("-vvvv");
cmd.assert().success().stdout(predicate::str::contains(""));
eprintln!("{:?}", fs::read_dir(config_dir.path())?.collect::<Vec<_>>());
assert_eq!(
std::fs::read_to_string(config_dir.path().join("devname"))?,
"testdev\n"
@ -253,6 +309,7 @@ mod integrated_test {
//
// devices: first, second
let config_dir_2 = assert_fs::TempDir::new()?;
setup_gitconfig()?;
let mut cmd2 = Command::cargo_bin("xdbm")?;
cmd2.arg("-c")
.arg(config_dir_2.path())
@ -276,15 +333,15 @@ mod integrated_test {
assert!(config_dir_2.join("backups").join("second.yml").exists());
// sync
std::process::Command::new("git")
.arg("push")
.current_dir(&config_dir_2)
Command::cargo_bin("xdbm")?
.arg("-c")
.arg(config_dir_2.path())
.arg("sync")
.arg("-vvvv")
.arg("-u")
.assert()
.success();
// let repo_2 = Repository::open(config_dir_2)?;
// // return Err(anyhow!("{:?}", repo_2.remotes()?.iter().collect::<Vec<_>>()));
// let mut repo_2_remote = repo_2.find_remote(repo_2.remotes()?.get(0).unwrap())?;
// repo_2_remote.push(&[] as &[&str], None)?;
.success()
.stderr(predicate::str::contains("successfully pushed"));
std::process::Command::new("git")
.arg("pull")
.current_dir(&config_dir_1)
@ -344,16 +401,8 @@ mod integrated_test {
std::fs::read_to_string(config_dir_1.join("storages.yml"))?.contains("parent: gdrive1")
);
std::process::Command::new("git")
.arg("push")
.current_dir(&config_dir_1)
.assert()
.success();
std::process::Command::new("git")
.arg("pull")
.current_dir(&config_dir_2)
.assert()
.success();
run_sync_cmd(&config_dir_1, false)?;
run_sync_cmd(&config_dir_2, false)?;
// bind
//
@ -567,16 +616,8 @@ mod integrated_test {
.and(predicate::str::contains("foodoc").not()),
);
std::process::Command::new("git")
.arg("push")
.current_dir(&config_dir_2)
.assert()
.success();
std::process::Command::new("git")
.arg("pull")
.current_dir(&config_dir_1)
.assert()
.success();
run_sync_cmd(&config_dir_2, true)?;
run_sync_cmd(&config_dir_1, true)?;
// bind
//
@ -691,16 +732,8 @@ mod integrated_test {
.assert()
.success();
std::process::Command::new("git")
.arg("push")
.current_dir(&config_dir_1)
.assert()
.success();
std::process::Command::new("git")
.arg("pull")
.current_dir(&config_dir_2)
.assert()
.success();
run_sync_cmd(&config_dir_1, false)?;
run_sync_cmd(&config_dir_2, false)?;
// backup add
//