nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: pacak/bpaf
Pull request #361 (2024-04-29 12:05:30)

Release 0.9.12
Improve error messages for a scenario where a flag that can be used just once is used twice or more and the whole parser contains a similarly looking flag


Patch:
diff --git a/Cargo.toml b/Cargo.toml
index 444b633..6012d93 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "bpaf"
-version = "0.9.11"
+version = "0.9.12"
 edition = "2021"
 categories = ["command-line-interface"]
 description = "A simple Command Line Argument Parser with parser combinators"
diff --git a/Changelog.md b/Changelog.md
index 9464409..ad13e64 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,5 +1,9 @@
 # Change Log
 
+
+## bpaf [0.9.12] - 2024-04-29
+- better error messages
+
 ## bpaf [0.9.11] - 2024-03-24
 - better error messages
 
diff --git a/src/error.rs b/src/error.rs
index df6e5f7..5927466 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -273,10 +273,10 @@ impl Message {
             Message::Unconsumed(ix) => {
                 if let Some(conflict) = check_conflicts(args) {
                     self = conflict;
-                } else if let Some((ix, suggestion)) = crate::meta_youmean::suggest(args, meta) {
-                    self = Message::Suggestion(ix, suggestion);
                 } else if let Some(prev_ix) = only_once(args, ix) {
                     self = Message::OnlyOnce(prev_ix, ix);
+                } else if let Some((ix, suggestion)) = crate::meta_youmean::suggest(args, meta) {
+                    self = Message::Suggestion(ix, suggestion);
                 }
             }
             Message::Missing(xs) => {


Test patch:
diff --git a/tests/errors.rs b/tests/errors.rs
index 36ae600..4eb28a2 100644
--- a/tests/errors.rs
+++ b/tests/errors.rs
@@ -271,3 +271,29 @@ fn two_required_fields_first_missing() {
     let r = parser.run_inner(&["--b", "1"]).unwrap_err().unwrap_stderr();
     assert_eq!(r, "expected `--a=A`, pass `--help` for usage information");
 }
+
+#[test]
+fn used_only_once_is_more_important_error() {
+    let format = long("format").switch();
+    let sort = long("sort").switch();
+    let filter = long("filter").switch();
+    let opts = construct!(format, sort, filter,).to_options();
+
+    let err = opts
+        .run_inner(&["--filter", "--filter"])
+        .unwrap_err()
+        .unwrap_stderr();
+    assert_eq!(
+        err,
+        "argument `--filter` cannot be used multiple times in this context"
+    );
+
+    let err = opts
+        .run_inner(&["--sort", "--sort"])
+        .unwrap_err()
+        .unwrap_stderr();
+    assert_eq!(
+        err,
+        "argument `--sort` cannot be used multiple times in this context"
+    );
+}
Repository: pacak/bpaf
Pull request #378 (2024-07-25 11:13:33)

`fallback_to_usage` fixes related to an `enum` of commands


Patch:
diff --git a/Changelog.md b/Changelog.md
index 6287b6b..75a6337 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -2,6 +2,11 @@
 
 ## bpaf [0.9.13] - Unreleased
 - You can now use `fallback_to_usage` in derive macro for options and subcommands
+- Bugfixes related to shell completion and file masks
+  thanks @ozwaldorf
+- `not_strict` restriction for positional items (TODO - check the docs)
+  thanks @ozwaldorf
+
 
 ## bpaf [0.9.12] - 2024-04-29
 - better error messages
diff --git a/bpaf_derive/src/top.rs b/bpaf_derive/src/top.rs
index b692d6d..6d3db3e 100644
--- a/bpaf_derive/src/top.rs
+++ b/bpaf_derive/src/top.rs
@@ -507,7 +507,7 @@ impl ParsedEnumBranch {
 
         if let Some(opts_at) = has_options {
             if fallback_usage {
-                attrs.push(EAttr::FallbackUsage);
+                attrs.insert(opts_at, EAttr::FallbackUsage);
             }
 
             if let Some(h) = std::mem::take(&mut help) {


Test patch:
diff --git a/bpaf_derive/src/top_tests.rs b/bpaf_derive/src/top_tests.rs
index 0b77477..80c4b2c 100644
--- a/bpaf_derive/src/top_tests.rs
+++ b/bpaf_derive/src/top_tests.rs
@@ -72,6 +72,32 @@ fn fallback_usage_subcommand() {
     assert_eq!(input.to_token_stream().to_string(), expected.to_string());
 }
 
+#[test]
+fn fallback_usage_lut() {
+    let input: Top = parse_quote! {
+        #[bpaf(options)]
+        enum Lutgen {
+            /// descr
+            #[bpaf(command, fallback_to_usage)]
+            Generate,
+        }
+    };
+
+    let expected = quote! {
+        fn lutgen() -> ::bpaf::OptionParser<Lutgen> {
+            #[allow(unused_imports)]
+            use ::bpaf::Parser;
+            ::bpaf::pure(Lutgen::Generate)
+                .to_options()
+                .descr("descr")
+                .fallback_to_usage()
+                .command("generate")
+                .to_options()
+        }
+    };
+    assert_eq!(input.to_token_stream().to_string(), expected.to_string());
+}
+
 #[test]
 fn top_struct_construct() {
     let top: Top = parse_quote! {
Repository: pacak/bpaf
Pull request #418 (2025-03-13 16:35:56)

Release 0.9.19
Fix one more problematic corner case of `fallback_to_usage`. It should not override inner parser printing usage or version info:

If parser supports subcommand "foo" then passing "app foo --help" should return help for "foo", not for the app itself


Patch:
diff --git a/Cargo.toml b/Cargo.toml
index fcd84d5..60e2611 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "bpaf"
-version = "0.9.18"
+version = "0.9.19"
 edition = "2021"
 categories = ["command-line-interface"]
 description = "A simple Command Line Argument Parser with parser combinators"
diff --git a/Changelog.md b/Changelog.md
index 2f6c51e..560d170 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,5 +1,9 @@
 # Change Log
 
+## bpaf [0.9.19] - 2025-03-13
+- Fix one more problematic corner case of `fallback_to_usage` - it should no override
+  inner parser printing usage or version info
+
 ## bpaf [0.9.18] - 2025-03-06
 - Several small documentation fixes (#414, #413)
   thanks @yerke
diff --git a/src/info.rs b/src/info.rs
index 6e605ef..d022558 100644
--- a/src/info.rs
+++ b/src/info.rs
@@ -240,9 +240,16 @@ impl<T> OptionParser<T> {
         //
         // outer parser gets value in ParseFailure format
 
+        let no_args = args.is_empty();
         let res = self.inner.eval(args);
 
-        if res.is_err() && self.info.help_if_no_args && args.is_empty() {
+        // Don't override inner parser printing usage info
+        let parser_failed = match res {
+            Ok(_) | Err(Error(Message::ParseFailure(ParseFailure::Stdout(..)))) => false,
+            Err(_) => true,
+        };
+
+        if parser_failed && self.info.help_if_no_args && no_args {
             let buffer = render_help(
                 &args.path,
                 &self.info,


Test patch:
diff --git a/tests/help_format.rs b/tests/help_format.rs
index e9668e9..db8ad2c 100644
--- a/tests/help_format.rs
+++ b/tests/help_format.rs
@@ -656,3 +656,26 @@ fn help_and_version_newline() {
         .unwrap_stdout();
     assert_eq!(r, "Version: 1\n");
 }
+
+#[test]
+fn fallback_to_usage_and_commands() {
+    let parser = pure(())
+        .to_options()
+        .descr("inner")
+        .command("cmd")
+        .to_options()
+        .descr("outer")
+        .fallback_to_usage();
+
+    let r = parser
+        .run_inner(&["cmd", "--help"])
+        .unwrap_err()
+        .unwrap_stdout();
+    let expected =
+        "inner\n\nUsage: cmd \n\nAvailable options:\n    -h, --help  Prints help information\n";
+    assert_eq!(r, expected);
+
+    let r = parser.run_inner(&[]).unwrap_err().unwrap_stdout();
+    let expected = "outer\n\nUsage: COMMAND ...\n\nAvailable options:\n    -h, --help  Prints help information\n\nAvailable commands:\n    cmd         inner\n";
+    assert_eq!(r, expected);
+}
Repository: huff-language/huff-rs
Pull request #156 (2022-07-04 02:28:18)

satisfy the nightly clappy gods
⚠️ clappy hotfix ⚠️ 


Patch:
diff --git a/huff_lexer/src/lib.rs b/huff_lexer/src/lib.rs
index f1c3a65..286f1b7 100644
--- a/huff_lexer/src/lib.rs
+++ b/huff_lexer/src/lib.rs
@@ -118,8 +118,8 @@ impl<'a> Lexer<'a> {
                     }
 
                     // Then we should have an import path between quotes
-                    match peekable_source.peek() {
-                        Some(char) => match char {
+                    if let Some(char) = peekable_source.peek() {
+                        match char {
                             '"' | '\'' => {
                                 peekable_source.next();
                                 let mut import = String::new();
@@ -134,8 +134,7 @@ impl<'a> Lexer<'a> {
                                 }
                             }
                             _ => { /* Ignore non-include tokens */ }
-                        },
-                        None => { /* EOF */ }
+                        }
                     }
                 } else if nc.ne(&include_chars_iterator.next().unwrap()) {
                     include_chars_iterator = "#include".chars().peekable();
@@ -619,7 +618,7 @@ impl<'a> Iterator for Lexer<'a> {
                         Some('"') => {
                             self.consume();
                             let str = self.slice();
-                            break TokenKind::Str((&str[1..str.len() - 1]).to_string())
+                            break TokenKind::Str((str[1..str.len() - 1]).to_string())
                         }
                         Some('\\') if matches!(self.nth_peek(1), Some('\\') | Some('"')) => {
                             self.consume();
@@ -642,7 +641,7 @@ impl<'a> Iterator for Lexer<'a> {
                         Some('\'') => {
                             self.consume();
                             let str = self.slice();
-                            break TokenKind::Str((&str[1..str.len() - 1]).to_string())
+                            break TokenKind::Str((str[1..str.len() - 1]).to_string())
                         }
                         Some('\\') if matches!(self.nth_peek(1), Some('\\') | Some('\'')) => {
                             self.consume();


Test patch:
diff --git a/huff_core/tests/erc20.rs b/huff_core/tests/erc20.rs
index 90a7279..7cd14d6 100644
--- a/huff_core/tests/erc20.rs
+++ b/huff_core/tests/erc20.rs
@@ -18,9 +18,7 @@ fn test_erc20_compile() {
     // Recurse file deps + generate flattened source
     let file_source = file_sources.get(0).unwrap();
     let recursed_file_source = Compiler::recurse_deps(Arc::clone(file_source)).unwrap();
-    println!("Recursed file source: {:?}", recursed_file_source);
     let flattened = FileSource::fully_flatten(Arc::clone(&recursed_file_source));
-    println!("File source path: {}", flattened.0);
     let full_source = FullFileSource {
         source: &flattened.0,
         file: Some(Arc::clone(file_source)),
Repository: huff-language/huff-rs
Pull request #197 (2022-08-06 17:35:10)

feat: custom bootstrap code
addresses #195 



Patch:
diff --git a/huff_codegen/src/lib.rs b/huff_codegen/src/lib.rs
index 6603887..9d88e4c 100644
--- a/huff_codegen/src/lib.rs
+++ b/huff_codegen/src/lib.rs
@@ -525,8 +525,15 @@ impl Codegen {
             )
         };
 
+        let has_custom_bootstrap = hex::decode(constructor_bytecode).unwrap().contains(&0xf3);
+
+        let bootstrap_code = if has_custom_bootstrap {
+            String::default()
+        } else {
+            format!("{}80{}3d393df3", contract_size, contract_code_offset)
+        };
+
         // Generate the final bytecode
-        let bootstrap_code = format!("{}80{}3d393df3", contract_size, contract_code_offset);
         let constructor_code = format!("{}{}", constructor_bytecode, bootstrap_code);
         artifact.bytecode =
             format!("{}{}{}", constructor_code, main_bytecode, constructor_args).to_lowercase();


Test patch:
diff --git a/huff_codegen/tests/churn.rs b/huff_codegen/tests/churn.rs
index e95de1b..03bffd0 100644
--- a/huff_codegen/tests/churn.rs
+++ b/huff_codegen/tests/churn.rs
@@ -28,6 +28,31 @@ fn churns_into_bytecode() {
     assert_eq!(cg.artifact.unwrap().runtime.len(), main_bytecode.len());
 }
 
+#[test]
+fn churns_custom_bootstrap() {
+    // Instantiate Codegen
+    let mut cg = Codegen::new();
+
+    // The codegen instance should have no artifact
+    assert!(cg.artifact.is_none());
+
+    // Churn Contract using the bytecode
+    let inputs: Vec<Token> = vec![];
+
+    // main bytecode never reached but still included in deploy code
+    let main_bytecode = "6001600216";
+    // custom bootstrap code
+    let constructor_bytecode = "64600160020160005260056000f3";
+    let churn_res =
+        cg.churn(Arc::new(FileSource::default()), inputs, main_bytecode, constructor_bytecode);
+
+    assert!(churn_res.is_ok());
+    assert_eq!(
+        churn_res.unwrap().bytecode,
+        "64600160020160005260056000f36001600216".to_lowercase()
+    );
+}
+
 #[test]
 fn churns_constructor_args() {
     // Instantiate Codegen
Repository: kubernetes-sigs/node-feature-discovery
Pull request #872 (2022-08-23 16:56:07)

[release-0.11] Fix templates for NodeFeatureRule with MatchAny
This is an automated cherry-pick of #865

/assign marquiz


Patch:
diff --git a/pkg/apis/nfd/v1alpha1/rule.go b/pkg/apis/nfd/v1alpha1/rule.go
index 267680326..1237a6f19 100644
--- a/pkg/apis/nfd/v1alpha1/rule.go
+++ b/pkg/apis/nfd/v1alpha1/rule.go
@@ -50,11 +50,13 @@ func (r *Rule) Execute(features feature.Features) (RuleOutput, error) {
 				matched = true
 				utils.KlogDump(4, "matches for matchAny "+r.Name, "  ", matches)
 
-				if r.labelsTemplate == nil {
-					// No templating so we stop here (further matches would just
-					// produce the same labels)
+				if r.LabelsTemplate == "" && r.VarsTemplate == "" {
+					// there's no need to evaluate other matchers in MatchAny
+					// if there are no templates to be executed on them - so
+					// short-circuit and stop on first match here
 					break
 				}
+
 				if err := r.executeLabelsTemplate(matches, labels); err != nil {
 					return RuleOutput{}, err
 				}


Test patch:
diff --git a/pkg/apis/nfd/v1alpha1/rule_test.go b/pkg/apis/nfd/v1alpha1/rule_test.go
index 87d9c7b3b..477f7a58c 100644
--- a/pkg/apis/nfd/v1alpha1/rule_test.go
+++ b/pkg/apis/nfd/v1alpha1/rule_test.go
@@ -300,6 +300,11 @@ var-2=
 		},
 	}
 
+	// test with empty MatchFeatures, but with MatchAny
+	r3 := r1.DeepCopy()
+	r3.MatchAny = []MatchAnyElem{{MatchFeatures: r3.MatchFeatures}}
+	r3.MatchFeatures = nil
+
 	expectedLabels := map[string]string{
 		"label-1": "label-val-1",
 		"label-2": "",
@@ -328,6 +333,11 @@ var-2=
 	assert.Equal(t, expectedLabels, m.Labels, "instances should have matched")
 	assert.Equal(t, expectedVars, m.Vars, "instances should have matched")
 
+	m, err = r3.Execute(f)
+	assert.Nilf(t, err, "unexpected error: %v", err)
+	assert.Equal(t, expectedLabels, m.Labels, "instances should have matched")
+	assert.Equal(t, expectedVars, m.Vars, "instances should have matched")
+
 	//
 	// Test error cases
 	//
Repository: kubernetes-sigs/node-feature-discovery
Pull request #897 (2022-09-20 17:01:27)

nfd-master: drop cleanup of ancient incubator labels
Remove the cleanup code that removes ancient NFD labels with the node.alpha.kubernetes-incubator.io/ prefix. This label namespace was deprecated/dropped already in v0.4.0 so it should be safe to drop this code.


Patch:
diff --git a/pkg/nfd-master/nfd-master.go b/pkg/nfd-master/nfd-master.go
index 9b5e3775e..ef22d466f 100644
--- a/pkg/nfd-master/nfd-master.go
+++ b/pkg/nfd-master/nfd-master.go
@@ -580,10 +580,6 @@ func (m *nfdMaster) updateNodeFeatures(nodeName string, labels Labels, annotatio
 	patches := createPatches(oldLabels, node.Labels, labels, "/metadata/labels")
 	patches = append(patches, createPatches(nil, node.Annotations, annotations, "/metadata/annotations")...)
 
-	// Also, remove all labels with the old prefix, and the old version label
-	patches = append(patches, removeLabelsWithPrefix(node, "node.alpha.kubernetes-incubator.io/nfd")...)
-	patches = append(patches, removeLabelsWithPrefix(node, "node.alpha.kubernetes-incubator.io/node-feature-discovery")...)
-
 	// Patch the node object in the apiserver
 	err = m.apihelper.PatchNode(cli, node.Name, patches)
 	if err != nil {
@@ -612,19 +608,6 @@ func (m *nfdMaster) getKubeconfig() (*restclient.Config, error) {
 	return m.kubeconfig, err
 }
 
-// Remove any labels having the given prefix
-func removeLabelsWithPrefix(n *api.Node, search string) []apihelper.JsonPatch {
-	var p []apihelper.JsonPatch
-
-	for k := range n.Labels {
-		if strings.HasPrefix(k, search) {
-			p = append(p, apihelper.NewJsonPatch("remove", "/metadata/labels", k, ""))
-		}
-	}
-
-	return p
-}
-
 // createPatches is a generic helper that returns json patch operations to perform
 func createPatches(removeKeys []string, oldItems map[string]string, newItems map[string]string, jsonPath string) []apihelper.JsonPatch {
 	patches := []apihelper.JsonPatch{}


Test patch:
diff --git a/pkg/nfd-master/nfd-master-internal_test.go b/pkg/nfd-master/nfd-master-internal_test.go
index e5823b3ab..3d36ad805 100644
--- a/pkg/nfd-master/nfd-master-internal_test.go
+++ b/pkg/nfd-master/nfd-master-internal_test.go
@@ -533,3 +533,16 @@ func sortJsonPatches(p []apihelper.JsonPatch) []apihelper.JsonPatch {
 	sort.Slice(p, func(i, j int) bool { return p[i].Path < p[j].Path })
 	return p
 }
+
+// Remove any labels having the given prefix
+func removeLabelsWithPrefix(n *api.Node, search string) []apihelper.JsonPatch {
+	var p []apihelper.JsonPatch
+
+	for k := range n.Labels {
+		if strings.HasPrefix(k, search) {
+			p = append(p, apihelper.NewJsonPatch("remove", "/metadata/labels", k, ""))
+		}
+	}
+
+	return p
+}