Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 91ba045

Browse files
committed
Write about user interfaces and the use/non-use of async
1 parent bca7ce2 commit 91ba045

10 files changed

Lines changed: 61 additions & 26 deletions

File tree

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,15 @@ small = ["lean-cli"]
3737
fast = ["git-features/parallel", "git-features/fast-sha1"]
3838
pretty-cli = ["structopt",
3939
"git-features/progress-prodash",
40-
"git-features/interuptible",
40+
"git-features/interruptible",
4141
"gitoxide-core/serde1",
4242
"prodash/log-renderer",
4343
"prodash-tui-renderer",
4444
"prodash-line-renderer",
4545
"prodash/localtime",
4646
"env_logger",
4747
"futures-lite"]
48-
lean-cli = ["argh", "git-features/progress-log", "env_logger", "git-features/interuptible"]
48+
lean-cli = ["argh", "git-features/progress-log", "env_logger", "git-features/interruptible"]
4949

5050
prodash-line-renderer-crossterm = ["prodash-line-renderer", "prodash/line-renderer-crossterm", "git-features/progress-prodash", "atty", "crosstermion"]
5151
prodash-line-renderer-termion = ["prodash-line-renderer", "prodash/line-renderer-termion", "git-features/progress-prodash", "atty", "crosstermion"]

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ check: ## Build all code in suitable configurations
7474
cd git-features && cargo check --all-features \
7575
&& cargo check --features parallel \
7676
&& cargo check --features fast-sha1 \
77-
&& cargo check --features interuptible
77+
&& cargo check --features interruptible
7878

7979
unit-tests: ## run all unit tests
8080
cargo test --all --no-fail-fast

README.md

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -235,11 +235,6 @@ Provide a CLI to for the most basic user journey:
235235
* [ ] create (thin) pack
236236
* [ ] transform _all_ `unwrap()` calls into `expect(…)` or `?` for quality. `parking_lot` will help for unwraps of poisoned locks.
237237

238-
### Roadmap to 1.1
239-
240-
* [ ] clone a repository via
241-
* [ ] ssh
242-
243238
## Cargo features guide
244239

245240
Cargo uses feature toggles to control which dependencies are pulled in, allowing users to specialize crates to fit their usage.
@@ -280,7 +275,7 @@ There are **convenience features**, which combine common choices of the above in
280275
* **light** = *lean-cli* + *fast*
281276
* crossplatform by nature as this comes with simplified log based progress
282277
* **small** = *lean-cli*
283-
* As small as it can possibly be, no threading, no fast sha1, log based progress only
278+
* As small as it can possibly be, no threading, no fast sha1, log based progress only, no cleanup of temporary files on interrupt
284279

285280
### git-features
286281

@@ -301,7 +296,7 @@ All feature toggles are additive.
301296
* **progress-prodash**
302297
* Implement the `Progress` trait for the tree data structures provided by `prodash`, which enables using a terminal user
303298
interface for progress.
304-
* **interuptible**
299+
* **interruptible**
305300
* Listen to interrupts and termination requests and provide long-running operations tooling to allow aborting the input stream.
306301
* If unset, these utilities will be a no-op which may lead to leaking temporary files when interrupted.
307302
* If the application already sets a handler, this handler will have no effect.
@@ -342,6 +337,32 @@ All feature toggles are additive.
342337

343338
### Guidelines
344339

340+
* **async**
341+
* **library client-side**
342+
* Don't use it client side, as operations there are usually bound by the CPU and ultra-fast access to memory mapped files.
343+
It's no problem to saturate either CPU or the IO system.
344+
* **User Interfaces**
345+
* User interfaces can greatly benefit from using async as it's much easier to maintain a responsive UI thread that way thanks
346+
to the wonderful future combinators.
347+
* `blocking` can be used to make `Read` and `Iterator` async, or move any operation onto a thread which blends it into the
348+
async world.
349+
* Most operations are fast and 'interrupting' them is as easy as ignoring their result by cancelling their task.
350+
* Long-running operations can be roughly interacted with using `git_features::interruptible::interrupt()` function, and after a moment
351+
of waiting the flag can be unset with the `…::uninterrupt()` function to allow new long-running operations to work.
352+
Every long running operation supports this.
353+
* **server-side**
354+
* Building a pack is CPU and at some point, IO bound, and it makes no sense to use async to handle more connections - git
355+
needs a lot of resources and threads will do just fine.
356+
357+
* **interruption of long-running operations**
358+
* Use `git-features::interruptible::*` for building support for interruptions of long-running operations only.
359+
* It's up to the author to decide how to best integrate it, generally we use a poll-based mechanism to check whether
360+
an interrupt flag is set.
361+
* **this is a must if…**
362+
* …temporary resources like files might otherwise be leaked
363+
* **this is optional but desirable if…**
364+
* …there is no leakage otherwise to support user interfaces. They background long-running operations and need them to be cancellable.
365+
345366
* **prepare for SHA256 support by using `owned::Id` and `borrowed::Id`**
346367
* eventually there will be the need to support both Sha1 and Sha256. We anticipate it by using the `Id` type instead
347368
of slices or arrays of 20 bytes. This way, eventually we can support multiple hash digest sizes.
@@ -381,6 +402,7 @@ From there, we can derive a few rules to try adhere to:
381402

382403
* does not show any progress or logging output by default
383404
* if supported and logging is enabled, it will show timestamps in UTC
405+
* it does not need a git repository, but instead takes all variables via the command-line
384406

385407
### Porcelain
386408

git-features/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ parallel = ["crossbeam-utils", "crossbeam-channel", "num_cpus"]
1616
fast-sha1 = ["fastsha1"]
1717
progress-log = ["log"]
1818
progress-prodash = ["prodash"]
19-
interuptible = ["ctrlc", "once_cell"]
19+
interruptible = ["ctrlc", "once_cell"]
2020

2121
[[test]]
2222
name = "parallel"
@@ -48,7 +48,7 @@ fastsha1 = { package = "sha-1", version = "0.9.1", optional = true }
4848
log = { version = "0.4.8", optional = true }
4949
prodash = { version = "7.0.2", optional = true, default-features = false }
5050

51-
# interuptible
51+
# interruptible
5252
ctrlc = { version = "3.1.4", optional = true, default-features = false, features = ['termination'] }
5353
once_cell = { version = "1.4.0", optional = true, default-features = false, features = ["std"] }
5454

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#[cfg(feature = "interuptible")]
1+
#[cfg(feature = "interruptible")]
22
mod _impl {
33
use ctrlc;
44
use once_cell::sync::Lazy;
@@ -24,23 +24,26 @@ mod _impl {
2424
R: io::Read,
2525
{
2626
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
27-
if is_interupted() {
27+
if is_interrupted() {
2828
return Err(io::Error::new(io::ErrorKind::Other, "interrupted by user"));
2929
}
3030
self.inner.read(buf)
3131
}
3232
}
3333

34-
pub fn is_interupted() -> bool {
34+
pub fn is_interrupted() -> bool {
3535
IS_INTERRUPTED.load(Ordering::Relaxed)
3636
}
3737

38-
pub fn interupt() {
38+
pub fn interrupt() {
3939
IS_INTERRUPTED.store(true, Ordering::Relaxed);
4040
}
41+
pub fn uninterrupt() {
42+
IS_INTERRUPTED.store(false, Ordering::Relaxed);
43+
}
4144
}
4245

43-
#[cfg(not(feature = "interuptible"))]
46+
#[cfg(not(feature = "interruptible"))]
4447
mod _impl {
4548
use std::io;
4649

@@ -60,6 +63,10 @@ mod _impl {
6063
pub fn is_interrupted() -> bool {
6164
false
6265
}
66+
67+
pub fn interrupt() {}
68+
69+
pub fn uninterrupt() {}
6370
}
6471

6572
pub use _impl::*;

git-features/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![forbid(unsafe_code)]
22

33
pub mod hash;
4-
pub mod interuptible;
4+
pub mod interruptible;
55
pub mod parallel;
66
pub mod progress;

git-odb/src/pack/bundle/write/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::pack;
2-
use git_features::{interuptible, progress, progress::Progress};
2+
use git_features::{interruptible, progress, progress::Progress};
33
use std::{
44
io,
55
path::{Path, PathBuf},
@@ -53,7 +53,7 @@ impl pack::Bundle {
5353
};
5454
let data_path: Option<PathBuf> = data_file.as_ref().map(|f| f.as_ref().into());
5555
let mut pack = PassThrough {
56-
reader: interuptible::Read { inner: pack },
56+
reader: interruptible::Read { inner: pack },
5757
writer: data_file,
5858
};
5959
let eight_pages = 4096 * 8;

git-odb/src/pack/tree/traverse/mod.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::{
33
pack::data::EntrySlice,
44
pack::tree::{Item, Tree},
55
};
6-
use git_features::{parallel, parallel::in_parallel_if, progress::Progress};
6+
use git_features::{interruptible::is_interrupted, parallel, parallel::in_parallel_if, progress::Progress};
77
use quick_error::quick_error;
88

99
mod resolve;
@@ -23,6 +23,9 @@ quick_error! {
2323
source(&**err)
2424
from()
2525
}
26+
Interrupted {
27+
display("Interrupted by user")
28+
}
2629
}
2730
}
2831

@@ -112,6 +115,9 @@ where
112115
let input = input?;
113116
self.item_count += input;
114117
self.progress.lock().set(self.item_count as u32);
118+
if is_interrupted() {
119+
return Err(Error::Interrupted);
120+
}
115121
Ok(())
116122
}
117123

src/plumbing/pretty.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ fn prepare_and_run<T: Send + 'static>(
198198
+ 'static,
199199
) -> Result<T> {
200200
super::init_env_logger(false);
201-
use git_features::interuptible::{interupt, is_interupted};
201+
use git_features::interruptible::{interrupt, is_interrupted};
202202
match (verbose, progress) {
203203
(false, false) => run(None, &mut stdout(), &mut stderr()),
204204
(true, false) => {
@@ -214,7 +214,7 @@ fn prepare_and_run<T: Send + 'static>(
214214
let tx = tx.clone();
215215
move || loop {
216216
std::thread::sleep(std::time::Duration::from_millis(500));
217-
if is_interupted() {
217+
if is_interrupted() {
218218
tx.send(Event::UIDone).ok();
219219
break;
220220
}
@@ -274,7 +274,7 @@ fn prepare_and_run<T: Send + 'static>(
274274
Event::UIDone => {
275275
// We don't know why the UI is done, usually it's the user aborting.
276276
// We need the computation to stop as well so let's wait for that to happen
277-
interupt();
277+
interrupt();
278278
continue;
279279
}
280280
Event::ComputationDone(res, out, err) => {

tasks.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@
3131
system temp files)
3232
* [x] for lean mode
3333
* [x] for pretty mode
34-
* [ ] allow interrupting the resolution phase too
35-
* [ ] fix typo :D - thanks IJ for confusing me
34+
* [x] allow interrupting the resolution phase too
35+
* [x] fix typo :D - thanks IJ for confusing me
3636
* [ ] move --verbose, --progress and --progress-keep-open to the top-level
3737
* [ ] unit tests for bundle index write
3838
* [ ] journey test for command-line capabilities

0 commit comments

Comments
 (0)