Skip to content

Commit 2aa7d3e

Browse files
committed
cli: Add lockfile mode
1 parent e78fadb commit 2aa7d3e

File tree

3 files changed

+111
-63
lines changed

3 files changed

+111
-63
lines changed

README.md

+19-27
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,11 @@ Commands:
116116
help Print this message or the help of the given subcommand(s)
117117

118118
Options:
119-
-d, --directory <FOLDER> Base folder for sources.json and the boilerplate default.nix [env: NPINS_DIRECTORY=] [default: npins]
120-
-v, --verbose Print debug messages
121-
-h, --help Print help
122-
-V, --version Print version
119+
-d, --directory <FOLDER> Base folder for sources.json and the boilerplate default.nix [env: NPINS_DIRECTORY=] [default: npins]
120+
--lock-file <LOCK_FILE> Specifies the path to the sources.json and activates lockfile mode. In lockfile mode, no default.nix will be generated and --directory will be ignored
121+
-v, --verbose Print debug messages
122+
-h, --help Print help
123+
-V, --version Print version
123124
```
124125

125126
### Initialization
@@ -139,10 +140,9 @@ Intializes the npins directory. Running this multiple times will restore/upgrade
139140
Usage: npins init [OPTIONS]
140141

141142
Options:
142-
--bare Don't add an initial `nixpkgs` entry
143-
-d, --directory <FOLDER> Base folder for sources.json and the boilerplate default.nix [env: NPINS_DIRECTORY=] [default: npins]
144-
-v, --verbose Print debug messages
145-
-h, --help Print help
143+
--bare Don't add an initial `nixpkgs` entry
144+
-v, --verbose Print debug messages
145+
-h, --help Print help
146146
```
147147

148148
### Migrate from Niv
@@ -168,10 +168,9 @@ Arguments:
168168
[PATH] [default: nix/sources.json]
169169

170170
Options:
171-
-d, --directory <FOLDER> Base folder for sources.json and the boilerplate default.nix [env: NPINS_DIRECTORY=] [default: npins]
172-
-n, --name <NAME> Only import one entry from Niv
173-
-v, --verbose Print debug messages
174-
-h, --help Print help
171+
-n, --name <NAME> Only import one entry from Niv
172+
-v, --verbose Print debug messages
173+
-h, --help Print help
175174
```
176175

177176
### Adding dependencies
@@ -232,8 +231,6 @@ Arguments:
232231
Options:
233232
-b, --branch <BRANCH>
234233
Track a branch instead of a release
235-
-d, --directory <FOLDER>
236-
Base folder for sources.json and the boilerplate default.nix [env: NPINS_DIRECTORY=] [default: npins]
237234
--name <NAME>
238235
Add the pin with a custom name. If a pin with that name already exists, it will be overwritten
239236
--at <tag or rev>
@@ -244,6 +241,8 @@ Options:
244241
Print debug messages
245242
--pre-releases
246243
Also track pre-releases. Conflicts with the --branch option
244+
-v, --verbose
245+
Print debug messages
247246
--upper-bound <version>
248247
Bound the version resolution. For example, setting this to "2" will restrict updates to 1.X versions. Conflicts with the --branch option
249248
--release-prefix <RELEASE_PREFIX>
@@ -266,9 +265,8 @@ Arguments:
266265
<NAME>
267266

268267
Options:
269-
-d, --directory <FOLDER> Base folder for sources.json and the boilerplate default.nix [env: NPINS_DIRECTORY=] [default: npins]
270-
-v, --verbose Print debug messages
271-
-h, --help Print help
268+
-v, --verbose Print debug messages
269+
-h, --help Print help
272270
```
273271

274272
### Show current entries
@@ -282,9 +280,8 @@ Lists the current pin entries
282280
Usage: npins show [OPTIONS]
283281

284282
Options:
285-
-d, --directory <FOLDER> Base folder for sources.json and the boilerplate default.nix [env: NPINS_DIRECTORY=] [default: npins]
286-
-v, --verbose Print debug messages
287-
-h, --help Print help
283+
-v, --verbose Print debug messages
284+
-h, --help Print help
288285
```
289286

290287
### Updating dependencies
@@ -301,14 +298,10 @@ Arguments:
301298
[NAMES]... Updates only the specified pins
302299

303300
Options:
304-
-d, --directory <FOLDER>
305-
Base folder for sources.json and the boilerplate default.nix [env: NPINS_DIRECTORY=] [default: npins]
306301
-p, --partial
307302
Don't update versions, only re-fetch hashes
308303
-f, --full
309304
Re-fetch hashes even if the version hasn't changed. Useful to make sure the derivations are in the Nix store
310-
-v, --verbose
311-
Print debug messages
312305
-n, --dry-run
313306
Print the diff, but don't write back the changes
314307
--frozen
@@ -330,9 +323,8 @@ Upgrade the sources.json and default.nix to the latest format version. This may
330323
Usage: npins upgrade [OPTIONS]
331324

332325
Options:
333-
-d, --directory <FOLDER> Base folder for sources.json and the boilerplate default.nix [env: NPINS_DIRECTORY=] [default: npins]
334-
-v, --verbose Print debug messages
335-
-h, --help Print help
326+
-v, --verbose Print debug messages
327+
-h, --help Print help
336328
```
337329

338330
### Using private GitLab repositories

src/cli.rs

+60-36
Original file line numberDiff line numberDiff line change
@@ -556,14 +556,18 @@ fn print_diff(name: &str, diff: impl AsRef<[diff::DiffEntry]>) {
556556
pub struct Opts {
557557
/// Base folder for sources.json and the boilerplate default.nix
558558
#[arg(
559-
global = true,
560559
short = 'd',
561560
long = "directory",
562561
default_value = "npins",
563562
env = "NPINS_DIRECTORY"
564563
)]
565564
folder: std::path::PathBuf,
566565

566+
/// Specifies the path to the sources.json and activates lockfile mode.
567+
/// In lockfile mode, no default.nix will be generated and --directory will be ignored.
568+
#[arg(long)]
569+
lock_file: Option<std::path::PathBuf>,
570+
567571
/// Print debug messages.
568572
#[arg(global = true, short = 'v', long = "verbose")]
569573
pub verbose: bool,
@@ -574,7 +578,11 @@ pub struct Opts {
574578

575579
impl Opts {
576580
fn read_pins(&self) -> Result<NixPins> {
577-
let path = self.folder.join("sources.json");
581+
let path = if let Some(lock_file) = self.lock_file.as_ref() {
582+
lock_file.to_owned()
583+
} else {
584+
self.folder.join("sources.json")
585+
};
578586
let fh = std::io::BufReader::new(std::fs::File::open(&path).with_context(move || {
579587
format!(
580588
"Failed to open {}. You must initialize npins before you can show current pins.",
@@ -586,10 +594,14 @@ impl Opts {
586594
}
587595

588596
fn write_pins(&self, pins: &NixPins) -> Result<()> {
589-
if !self.folder.exists() {
590-
std::fs::create_dir(&self.folder)?;
591-
}
592-
let path = self.folder.join("sources.json");
597+
let path = if let Some(lock_file) = &self.lock_file {
598+
lock_file.to_owned()
599+
} else {
600+
if !self.folder.exists() {
601+
std::fs::create_dir(&self.folder)?;
602+
}
603+
self.folder.join("sources.json")
604+
};
593605
let mut fh = std::fs::File::create(&path)
594606
.with_context(move || format!("Failed to open {} for writing.", path.display()))?;
595607
serde_json::to_writer_pretty(&mut fh, &versions::to_value_versioned(pins))?;
@@ -599,23 +611,27 @@ impl Opts {
599611

600612
async fn init(&self, o: &InitOpts) -> Result<()> {
601613
log::info!("Welcome to npins!");
602-
let default_nix = DEFAULT_NIX;
603-
if !self.folder.exists() {
604-
log::info!("Creating `{}` directory", self.folder.display());
605-
std::fs::create_dir(&self.folder).context("Failed to create npins folder")?;
606-
}
607-
log::info!("Writing default.nix");
608-
let p = self.folder.join("default.nix");
609-
let mut fh = std::fs::File::create(&p).context("Failed to create npins default.nix")?;
610-
fh.write_all(default_nix.as_bytes())?;
611614

612-
// Only create the pins if the file isn't there yet
613-
if self.folder.join("sources.json").exists() {
614-
log::info!(
615-
"The file '{}' already exists; nothing to do.",
616-
self.folder.join("pins.json").display()
617-
);
618-
return Ok(());
615+
// Skip the entire default.nix and convenience creating folders bit in lockfile mode
616+
if self.lock_file.is_none() {
617+
let default_nix = DEFAULT_NIX;
618+
if !self.folder.exists() {
619+
log::info!("Creating `{}` directory", self.folder.display());
620+
std::fs::create_dir(&self.folder).context("Failed to create npins folder")?;
621+
}
622+
log::info!("Writing default.nix");
623+
let p = self.folder.join("default.nix");
624+
let mut fh = std::fs::File::create(&p).context("Failed to create npins default.nix")?;
625+
fh.write_all(default_nix.as_bytes())?;
626+
627+
// Only create the pins if the file isn't there yet
628+
if self.folder.join("sources.json").exists() {
629+
log::info!(
630+
"The file '{}' already exists; nothing to do.",
631+
self.folder.join("pins.json").display()
632+
);
633+
return Ok(());
634+
}
619635
}
620636

621637
let initial_pins = if o.bare {
@@ -632,7 +648,7 @@ impl Opts {
632648
self.write_pins(&initial_pins)?;
633649
log::info!(
634650
"Successfully written initial files to '{}'.",
635-
self.folder.display()
651+
self.lock_file.as_ref().unwrap_or(&self.folder).display()
636652
);
637653
Ok(())
638654
}
@@ -793,19 +809,22 @@ impl Opts {
793809
}
794810

795811
fn upgrade(&self) -> Result<()> {
796-
anyhow::ensure!(
797-
self.folder.exists(),
798-
"Could not find npins folder at {}",
799-
self.folder.display(),
800-
);
812+
if self.lock_file.is_none() {
813+
anyhow::ensure!(
814+
self.folder.exists(),
815+
"Could not find npins folder at {}",
816+
self.folder.display(),
817+
);
801818

802-
let nix_path = self.folder.join("default.nix");
803-
let nix_file = DEFAULT_NIX;
804-
if std::fs::read_to_string(&nix_path)? == nix_file {
805-
log::info!("default.nix is already up to date");
806-
} else {
807-
log::info!("Replacing default.nix with an up to date version");
808-
std::fs::write(&nix_path, nix_file).context("Failed to create npins default.nix")?;
819+
let nix_path = self.folder.join("default.nix");
820+
let nix_file = DEFAULT_NIX;
821+
if std::fs::read_to_string(&nix_path)? == nix_file {
822+
log::info!("default.nix is already up to date");
823+
} else {
824+
log::info!("Replacing default.nix with an up to date version");
825+
std::fs::write(&nix_path, nix_file)
826+
.context("Failed to create npins default.nix")?;
827+
}
809828
}
810829

811830
log::info!("Upgrading sources.json to the newest format version");
@@ -823,7 +842,9 @@ impl Opts {
823842
let pins_raw_new = versions::upgrade(pins_raw.clone()).context("Upgrading failed")?;
824843
let pins: NixPins = serde_json::from_value(pins_raw_new.clone())?;
825844
if pins_raw_new != serde_json::Value::Object(pins_raw) {
826-
log::info!("Done. It is recommended to at least run `update --partial` afterwards.");
845+
log::info!(
846+
"Done. It is recommended to at least run `npins update --partial` afterwards."
847+
);
827848
}
828849
self.write_pins(&pins)
829850
}
@@ -1038,6 +1059,9 @@ impl Opts {
10381059
}
10391060

10401061
pub async fn run(&self) -> Result<()> {
1062+
if self.lock_file.is_some() && &*self.folder != std::path::Path::new("npins") {
1063+
anyhow::bail!("If --lock-file is set, --directory will be ignored and thus should not be set to a non-default value (which is \"npins\")");
1064+
}
10411065
match &self.command {
10421066
Command::Init(o) => self.init(o).await?,
10431067
Command::Show => self.show()?,

test.nix

+32
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,38 @@ let
277277
'';
278278
in
279279
{
280+
initNoDefaultNix = mkGitTest {
281+
name = "init-no-default-nix";
282+
repositories."foo" = gitRepo;
283+
commands = ''
284+
npins --lock-file sources.json init --bare
285+
# Setting a custom directory should fail in lockfile mode
286+
! npins --lock-file sources.json -d npins2 show
287+
npins --lock-file sources.json -d npins show
288+
test -e npins/default.nix && exit 1
289+
V=$(jq -r .pins sources.json)
290+
[[ "$V" = "{}" ]]
291+
'';
292+
};
293+
294+
addInLockfileMode = mkGitTest rec {
295+
name = "add-in-lockfile-mode";
296+
repositories."foo" = gitRepo;
297+
commands = ''
298+
npins --lock-file sources2.json init --bare
299+
npins --lock-file sources2.json add git http://localhost:8000/foo -b test-branch
300+
301+
# Check version and url
302+
eq "$(jq -r .pins.foo.version sources2.json)" "null"
303+
eq "$(jq -r .pins.foo.revision sources2.json)" "$(resolveGitCommit ${repositories."foo"} HEAD)"
304+
eq "$(jq -r .pins.foo.url sources2.json)" "null"
305+
306+
# Check setting the directory in normal mode still works
307+
npins -d testing init --bare
308+
NPINS_DIRECTORY=testing npins show
309+
'';
310+
};
311+
280312
addDryRun = mkGitTest {
281313
name = "add-dry-run";
282314
repositories."foo" = gitRepo;

0 commit comments

Comments
 (0)