diff --git a/client/src/command/push.rs b/client/src/command/push.rs index c93d22d..b2bb661 100644 --- a/client/src/command/push.rs +++ b/client/src/command/push.rs @@ -1,3 +1,4 @@ +use std::io::IsTerminal; use std::path::PathBuf; use std::sync::Arc; @@ -57,6 +58,16 @@ struct PushContext { impl PushContext { async fn push_static(self, paths: Vec) -> Result<()> { + if paths.is_empty() { + eprintln!("🤷 Nothing specified."); + if !std::io::stdin().is_terminal() { + eprintln!( + "Hint: Pass --stdin to read the list of store paths from standard input." + ); + } + return Ok(()); + } + let roots = paths .into_iter() .map(|p| self.store.follow_store_path(p)) @@ -108,6 +119,10 @@ impl PushContext { let stdin = BufReader::new(io::stdin()); let mut lines = stdin.lines(); while let Some(line) = lines.next_line().await? { + if line.is_empty() { + continue; + } + let path = self.store.follow_store_path(line)?; session.queue_many(vec![path])?; } @@ -167,6 +182,12 @@ pub async fn run(opts: Opts) -> Result<()> { }; if sub.stdin { + if !sub.paths.is_empty() { + return Err(anyhow!( + "No paths can be specified on the command line with --stdin" + )); + } + push_ctx.push_stdin().await?; } else { push_ctx.push_static(sub.paths.clone()).await?; diff --git a/integration-tests/basic/default.nix b/integration-tests/basic/default.nix index 9896d29..f54b467 100644 --- a/integration-tests/basic/default.nix +++ b/integration-tests/basic/default.nix @@ -203,12 +203,12 @@ in { with subtest("Check that we can push a path"): client.succeed("${makeTestDerivation} test.nix") - test_file = client.succeed("nix-build --no-out-link test.nix") + test_file = client.succeed("nix-build --no-out-link test.nix").strip() test_file_hash = test_file.removeprefix("/nix/store/")[:32] client.succeed(f"attic push test {test_file}") client.succeed(f"nix-store --delete {test_file}") - client.fail(f"grep hello {test_file}") + client.fail(f"ls {test_file}") with subtest("Check that we can pull a path"): client.succeed("attic use readonly:test") @@ -219,6 +219,25 @@ in { client.fail(f"attic push readonly:test {test_file}") client.fail(f"attic push anon:test {test_file} 2>&1") + with subtest("Check that we can push a list of paths from stdin"): + paths = [] + for i in range(10): + client.succeed(f"${makeTestDerivation} seq{i}.nix") + path = client.succeed(f"nix-build --no-out-link seq{i}.nix").strip() + client.succeed(f"echo {path} >>paths.txt") + paths.append(path) + + client.succeed("attic push test --stdin &1") + + for path in paths: + client.succeed(f"nix-store --delete {path}") + + with subtest("Check that we can pull the paths back"): + for path in paths: + client.fail(f"ls {path}") + client.succeed(f"nix-store -r {path}") + client.succeed(f"grep hello {path}") + with subtest("Check that we can make the cache public"): client.fail("curl -sL --fail-with-body http://server:8080/test/nix-cache-info") client.fail(f"curl -sL --fail-with-body http://server:8080/test/{test_file_hash}.narinfo")