Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,11 @@ impl Updater {
pub fn new(text: Rope, map: InputMap) -> Self {
let mut inputs = vec![];
for (_id, input) in map {
// Skip inputs without a URL (e.g. expanded type/owner/repo/ref format
// or follows-only stubs) — there is no quoted URL value to modify.
if input.url.is_empty() || input.range.start == 0 && input.range.end == 0 {
continue;
}
inputs.push(UpdateInput { input });
}
Self {
Expand Down
45 changes: 40 additions & 5 deletions src/walk/inputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ pub fn insert_with_ctx(
if let Some(node) = inputs.get_mut(&id) {
if !input.url.to_string().is_empty() {
node.url = input.url;
node.range = input.range;
}
if !input.flake {
node.flake = input.flake;
Expand Down Expand Up @@ -380,7 +381,7 @@ fn handle_nested_input(
for binding in attr.children() {
if binding.to_string() == "url" {
let url = binding.next_sibling().unwrap();
let input = Input::with_url(id_str.clone(), url.to_string(), input_id.text_range());
let input = Input::with_url(id_str.clone(), url.to_string(), url.text_range());
insert_with_ctx(inputs, id_str.clone(), input, ctx);
}
if should_remove_input(change, ctx, &id_str) {
Expand Down Expand Up @@ -991,12 +992,46 @@ fn handle_input_attr_set(

if leaf.to_string().starts_with("inputs") {
let id = child.prev_sibling().unwrap();
let context = id.to_string().into();
if let Some(replacement) =
walk_inputs(inputs, child.clone(), &Some(context), change)
{
let context: Context = id.to_string().into();
let ctx_some = Some(context);
if let Some(replacement) = walk_inputs(inputs, child.clone(), &ctx_some, change) {
return Some(substitute_child(node, child.index(), &replacement));
}

// Handle deeply nested inputs attrset removal:
// `inputs = { nixpkgs = { follows = "nixpkgs"; }; }`
if leaf.to_string() == "inputs"
&& change.is_remove()
&& let Some(inputs_attrset) = attr
.children()
.find(|c| c.kind() == SyntaxKind::NODE_ATTR_SET)
{
for nested_entry in inputs_attrset.children() {
if nested_entry.kind() != SyntaxKind::NODE_ATTRPATH_VALUE {
continue;
}
let Some(nested_path) = nested_entry.first_child() else {
continue;
};
let Some(nested_id) = nested_path.first_child() else {
continue;
};
if should_remove_nested_input(change, &ctx_some, &nested_id.to_string()) {
let new_inputs_attrset = remove_child_with_whitespace(
&inputs_attrset,
&nested_entry,
nested_entry.index(),
);
let new_attr = substitute_child(
&attr,
inputs_attrset.index(),
&new_inputs_attrset,
);
let new_child = substitute_child(child, attr.index(), &new_attr);
return Some(substitute_child(node, child.index(), &new_child));
}
}
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions tests/edit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ fn test_remove_input_walker(#[case] fixture: &str, #[case] input_id: &str) {
#[case("root", "rust-overlay.flake-utils")]
#[case("completely_flat_toplevel", "crane.rust-overlay")]
#[case("one_level_nesting_flat", "rust-overlay.flake-utils")]
#[case("deeply_nested_inputs", "disko.nixpkgs")]
fn test_remove_nested_input(#[case] fixture: &str, #[case] input_id: &str) {
let content = load_flake(fixture);
let mut flake_edit = FlakeEdit::from_text(&content).unwrap();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,20 @@ exit_code: 0
----- stdout -----
--- original
+++ modified
@@ -2,7 +2,6 @@
@@ -2,14 +2,10 @@
description = "Deeply nested inputs attrset";

inputs = {
- nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";

disko = {
url = "github:nix-community/disko";
inputs = {
- nixpkgs = {
- follows = "nixpkgs";
- };
};
};
};

----- stderr -----
16 changes: 16 additions & 0 deletions tests/snapshots/cli__remove@root_alt_nixpkgs.snap
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,21 @@ exit_code: 0

flake-utelinos.url = "github:numtide/flake-utils";

@@ -9,7 +8,6 @@
rust-overlay = {
url = "github:oxalica/rust-overlay";
inputs = {
- nixpkgs.follows = "nixpkgs";
flake-utils.follows = "flake-utils";
};
};
@@ -16,7 +14,6 @@
crane = {
url = "github:ipetkov/crane";
inputs = {
- nixpkgs.follows = "nixpkgs";
rust-overlay.follows = "rust-overlay";
flake-utils.follows = "flake-utils";
};

----- stderr -----
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ crane:
- rust-overlay
- "\"rust-overlay\""
range:
start: 0
end: 0
start: 466
end: 488
flake-utelinos:
id: flake-utelinos
flake: true
Expand Down Expand Up @@ -50,5 +50,5 @@ rust-overlay:
- nixpkgs
- "\"nixpkgs\""
range:
start: 0
end: 0
start: 256
end: 285
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ not-a-flake:
url: "\"github:a-kenji/not-a-flake\""
follows: []
range:
start: 585
end: 596
start: 611
end: 639
rust-overlay:
id: rust-overlay
flake: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ also-not-a-flake:
url: "\"github:a-kenji/also-not-a-flake\""
follows: []
range:
start: 72
end: 88
start: 131
end: 164
crane:
id: crane
flake: true
Expand Down
8 changes: 4 additions & 4 deletions tests/snapshots/edit__flake_edit_list@toplevel_nesting.snap
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ crane:
- rust-overlay
- "\"rust-overlay\""
range:
start: 272
end: 277
start: 292
end: 314
nixpkgs:
id: nixpkgs
flake: true
Expand All @@ -42,5 +42,5 @@ rust-overlay:
- nixpkgs
- "\"nixpkgs\""
range:
start: 111
end: 123
start: 138
end: 167
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
source: tests/edit.rs
expression: result
info:
flake_nix: ""
changes:
- Remove:
ids:
- disko.nixpkgs
---
{
description = "Deeply nested inputs attrset";

inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";

disko = {
url = "github:nix-community/disko";
inputs = {
};
};
};

outputs = _: { };
}
14 changes: 14 additions & 0 deletions tests/snapshots/update__pin_follows_before_url.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
source: tests/update.rs
expression: updater.get_changes()
---
{
inputs = {
myInput = {
inputs.nixpkgs.follows = "nixpkgs";
url = "github:foo/bar/abc123";
};
};

outputs = { self, myInput }: { };
}
17 changes: 17 additions & 0 deletions tests/snapshots/update__unpin_expanded_format_no_crash.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
source: tests/update.rs
expression: updater.get_changes()
---
{
inputs = {
myInput = {
type = "github";
owner = "NixOS";
repo = "nixpkgs";
ref = "nixos-25.11";
};
pinned.url = "github:foo/bar";
};

outputs = { self, myInput, pinned }: { };
}
14 changes: 14 additions & 0 deletions tests/snapshots/update__unpin_follows_before_url.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
source: tests/update.rs
expression: updater.get_changes()
---
{
inputs = {
myInput = {
inputs.nixpkgs.follows = "nixpkgs";
url = "github:foo/bar";
};
};

outputs = { self, myInput }: { };
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ crane:
- rust-overlay
- "\"rust-overlay\""
range:
start: 0
end: 0
start: 466
end: 488
flake-utelinos:
id: flake-utelinos
flake: true
Expand Down Expand Up @@ -50,5 +50,5 @@ rust-overlay:
- nixpkgs
- "\"nixpkgs\""
range:
start: 0
end: 0
start: 256
end: 285
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,5 @@ poetry2nix:
- nixpkgs
- "\"nixpkgs\""
range:
start: 0
end: 0
start: 292
end: 332
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ crane:
- rust-overlay
- "\"rust-overlay\""
range:
start: 272
end: 277
start: 292
end: 314
nixpkgs:
id: nixpkgs
flake: true
Expand All @@ -42,5 +42,5 @@ rust-overlay:
- nixpkgs
- "\"nixpkgs\""
range:
start: 111
end: 123
start: 138
end: 167
74 changes: 74 additions & 0 deletions tests/update.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use flake_edit::edit::FlakeEdit;
use flake_edit::update::Updater;
use ropey::Rope;

fn flake_with_pins() -> String {
r#"{
Expand Down Expand Up @@ -37,3 +38,76 @@ fn unpin_removes_rev_param() {

insta::assert_snapshot!(updater.get_changes());
}

#[test]
fn unpin_follows_before_url() {
let flake = r#"{
inputs = {
myInput = {
inputs.nixpkgs.follows = "nixpkgs";
url = "github:foo/bar?ref=some-branch";
};
};

outputs = { self, myInput }: { };
}
"#
.to_string();
let mut flake_edit = FlakeEdit::from_text(&flake).unwrap();
let inputs = flake_edit.list().clone();
let mut updater = Updater::new(Rope::from_str(&flake), inputs);

updater.unpin_input("myInput");

insta::assert_snapshot!(updater.get_changes());
}

#[test]
fn unpin_expanded_format_no_crash() {
let flake = r#"{
inputs = {
myInput = {
type = "github";
owner = "NixOS";
repo = "nixpkgs";
ref = "nixos-25.11";
};
pinned.url = "github:foo/bar?ref=v1.0";
};

outputs = { self, myInput, pinned }: { };
}
"#
.to_string();
let mut flake_edit = FlakeEdit::from_text(&flake).unwrap();
let inputs = flake_edit.list().clone();
let mut updater = Updater::new(Rope::from_str(&flake), inputs);

// Should not crash even though myInput has no url
updater.unpin_input("pinned");

insta::assert_snapshot!(updater.get_changes());
}

#[test]
fn pin_follows_before_url() {
let flake = r#"{
inputs = {
myInput = {
inputs.nixpkgs.follows = "nixpkgs";
url = "github:foo/bar";
};
};

outputs = { self, myInput }: { };
}
"#
.to_string();
let mut flake_edit = FlakeEdit::from_text(&flake).unwrap();
let inputs = flake_edit.list().clone();
let mut updater = Updater::new(Rope::from_str(&flake), inputs);

updater.pin_input_to_ref("myInput", "abc123");

insta::assert_snapshot!(updater.get_changes());
}
Loading