Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
15 changes: 12 additions & 3 deletions crates/socket-patch-cli/src/commands/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,10 @@ pub async fn run(args: ListArgs) -> i32 {
detail: detail.clone(),
});
} else if !args.common.silent {
eprintln!("Warning: {}", crate::commands::rollback::capitalize_first(detail));
eprintln!(
"Warning: {}",
crate::commands::rollback::capitalize_first(detail)
);
}
}
let vendor_state = crate::commands::vendor_state_lenient(&loaded.vendor, args.common.silent);
Expand Down Expand Up @@ -773,12 +776,18 @@ mod tests {
let listings = HostedListing::from_pins(
&[
pin("pkg:npm/minimist@1.2.2", &record.uuid),
pin("pkg:npm/other@1.0.0", "33333333-3333-4333-8333-333333333333"),
pin(
"pkg:npm/other@1.0.0",
"33333333-3333-4333-8333-333333333333",
),
],
Some(&legacy),
);
assert_eq!(listings[0].record, record);
assert_eq!(listings[1].record.uuid, "33333333-3333-4333-8333-333333333333");
assert_eq!(
listings[1].record.uuid,
"33333333-3333-4333-8333-333333333333"
);
assert!(listings[1].record.vulnerabilities.is_empty());
assert_eq!(listings[1].lockfiles, vec!["yarn.lock".to_string()]);
}
Expand Down
22 changes: 11 additions & 11 deletions crates/socket-patch-cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
pub mod apply;
pub(crate) mod bun_preflight;
pub(crate) mod context;
pub(crate) mod composer_hints;
pub(crate) mod context;
pub(crate) mod fetch_stage;
pub mod get;
pub mod hosted_bundle;
pub mod list;
pub(crate) mod lock_cli;
pub mod remove;
pub mod repair;
pub(crate) mod vendored_backend;
pub mod rollback;
pub mod scan;
pub mod update;
pub mod vendor;
pub(crate) mod vendored_backend;
pub mod vex;
pub(crate) mod vex_consumed;
pub(crate) mod vex_sources;
Expand Down Expand Up @@ -141,9 +141,11 @@ pub(crate) async fn hosted_state_from_lockfiles(
common: &crate::args::GlobalArgs,
root: &Path,
) -> socket_patch_core::patch::redirect::RedirectState {
hosted_state_from_pins(&socket_patch_core::patch::redirect::upstream::HostedPin::all(
&discover_wiring(common, root).await,
))
hosted_state_from_pins(
&socket_patch_core::patch::redirect::upstream::HostedPin::all(
&discover_wiring(common, root).await,
),
)
}

/// [`hosted_state_from_lockfiles`] over already-discovered pins. A purl
Expand All @@ -153,18 +155,17 @@ pub(crate) fn hosted_state_from_pins(
) -> socket_patch_core::patch::redirect::RedirectState {
let mut state = socket_patch_core::patch::redirect::RedirectState::new();
for pin in pins {
state
.records
.entry(pin.purl.clone())
.or_insert_with(|| socket_patch_core::manifest::schema::PatchRecord {
state.records.entry(pin.purl.clone()).or_insert_with(|| {
socket_patch_core::manifest::schema::PatchRecord {
uuid: pin.uuid.clone(),
exported_at: String::new(),
files: Default::default(),
vulnerabilities: Default::default(),
description: String::new(),
license: String::new(),
tier: String::new(),
});
}
});
}
state
}
Expand All @@ -191,4 +192,3 @@ pub(crate) fn vendor_state_lenient(
}
}
}

62 changes: 36 additions & 26 deletions crates/socket-patch-cli/src/commands/scan/discovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,29 +168,32 @@ pub(crate) async fn vendored_ledger_supplement(
}
// `(ledger key, base purl, entry)`; the artifact fallback has no
// entries to probe, so it never reports unwired keys.
let candidates: Vec<(String, String, Option<&socket_patch_core::vendor::VendorEntry>)> =
match state {
Ok(state) => state
.entries
.iter()
.map(|(key, entry)| {
(
key.clone(),
strip_purl_qualifiers(&entry.base_purl).to_string(),
Some(entry),
)
})
.collect(),
// Corrupt/unreadable ledger (a MISSING file is Ok(empty) above):
// recover the vendored set from the committed artifacts, or
// `scan --prune` (whose ledger exemption also degrades to empty)
// would delete still-vendored packages' manifest entries and blobs.
Err(_) => vendored_purls_from_artifacts(common)
.await
.into_iter()
.map(|base| (base.clone(), base, None))
.collect(),
};
let candidates: Vec<(
String,
String,
Option<&socket_patch_core::vendor::VendorEntry>,
)> = match state {
Ok(state) => state
.entries
.iter()
.map(|(key, entry)| {
(
key.clone(),
strip_purl_qualifiers(&entry.base_purl).to_string(),
Some(entry),
)
})
.collect(),
// Corrupt/unreadable ledger (a MISSING file is Ok(empty) above):
// recover the vendored set from the committed artifacts, or
// `scan --prune` (whose ledger exemption also degrades to empty)
// would delete still-vendored packages' manifest entries and blobs.
Err(_) => vendored_purls_from_artifacts(common)
.await
.into_iter()
.map(|base| (base.clone(), base, None))
.collect(),
};
// Composer by release identity: a ledger `@3.0.2.0` is the crawled
// `@3.0.2`, not a second package to supplement.
let key = |p: &str| composer_purl_identity(p).unwrap_or_else(|| normalize_purl(p).into_owned());
Expand Down Expand Up @@ -1045,7 +1048,9 @@ mod tests {
..GlobalArgs::default()
};
let state = socket_patch_core::vendor::load_state(root).await;
vendored_ledger_supplement(&args, crawled, &state).await.packages
vendored_ledger_supplement(&args, crawled, &state)
.await
.packages
}

/// A ledger entry vendored as `@3.0.2.0` is the crawled composer
Expand Down Expand Up @@ -1080,7 +1085,9 @@ mod tests {
out.iter().map(|p| &p.purl).collect::<Vec<_>>()
);

let out = vendored_ledger_supplement(&args, &[], &Ok(state)).await.packages;
let out = vendored_ledger_supplement(&args, &[], &Ok(state))
.await
.packages;
assert_eq!(
out.iter().map(|p| p.purl.as_str()).collect::<Vec<_>>(),
vec!["pkg:composer/psr/log@3.0.2.0"]
Expand Down Expand Up @@ -1183,7 +1190,10 @@ mod tests {
let state = npm_ledger_with_lock(tmp.path(), lock.as_deref()).await;
let out = vendored_ledger_supplement(&args, &[], &state).await;
assert_eq!(
out.packages.iter().map(|p| p.purl.as_str()).collect::<Vec<_>>(),
out.packages
.iter()
.map(|p| p.purl.as_str())
.collect::<Vec<_>>(),
vec!["pkg:npm/left-pad@1.3.0"],
"lock={lock:?}"
);
Expand Down
54 changes: 43 additions & 11 deletions crates/socket-patch-cli/src/commands/scan/hosted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -982,7 +982,8 @@ pub(crate) async fn run_redirect_selected(
socket_patch_core::utils::fs::read_regular_to_string_sync(path).ok()
})
};
let rewrite_options = || RewriteOptions {
let rewrite_options = || {
RewriteOptions {
dry_run: common.dry_run,
targets_pipenv_lock,
pipenv_major,
Expand All @@ -994,6 +995,7 @@ pub(crate) async fn run_redirect_selected(
npm_allow_remote_config: !common.no_npm_allow_remote_config,
npm_outer: &npm_outer,
blocking: true,
}
};
// The rollout gate plans again without its deferred rows: keep what
// the second pass needs.
Expand Down Expand Up @@ -2431,13 +2433,19 @@ fn join_names(names: &[String], max: usize) -> String {
/// artifacts, then verify with `vex`. After a vendored→hosted takeover
/// (`vendored_removed`) the commit also has to carry the deleted vendored
/// ledger entries and artifacts.
fn format_next_steps(files: &[String], edits: &[socket_patch_core::patch::redirect::FileEdit], vendored_removed: bool) -> Vec<String> {
fn format_next_steps(
files: &[String],
edits: &[socket_patch_core::patch::redirect::FileEdit],
vendored_removed: bool,
) -> Vec<String> {
if files.is_empty() && !vendored_removed {
return Vec::new();
}
let mut commit: Vec<String> = Vec::new();
if vendored_removed {
commit.push(".socket/vendor/ (the removed vendored ledger entries and artifacts)".to_string());
commit.push(
".socket/vendor/ (the removed vendored ledger entries and artifacts)".to_string(),
);
}
commit.extend(files.iter().cloned());
let npm = files
Expand Down Expand Up @@ -4624,19 +4632,43 @@ mod tests {
use super::npm_allow_remote_one_line;
let hosts = ["patch.socket.dev"];
let cases = [
(npm_allow_remote_configured_detail(&hosts, true, false), "Note: set"),
(npm_allow_remote_configured_detail(&hosts, false, false), "Note: set"),
(npm_allow_remote_configured_detail(&hosts, true, true), "Note: would set"),
(npm_allow_remote_already_detail(&hosts), "Note: .npmrc already"),
(npm_allow_remote_user_set_detail(&hosts, "none"), "Warning: npm >=12"),
(npm_allow_remote_env_set_detail(&hosts, "npm_config_allow_remote", "none"), "Warning: npm >=12"),
(
npm_allow_remote_configured_detail(&hosts, true, false),
"Note: set",
),
(
npm_allow_remote_configured_detail(&hosts, false, false),
"Note: set",
),
(
npm_allow_remote_configured_detail(&hosts, true, true),
"Note: would set",
),
(
npm_allow_remote_already_detail(&hosts),
"Note: .npmrc already",
),
(
npm_allow_remote_user_set_detail(&hosts, "none"),
"Warning: npm >=12",
),
(
npm_allow_remote_env_set_detail(&hosts, "npm_config_allow_remote", "none"),
"Warning: npm >=12",
),
(npm_allow_remote_manual_detail(&hosts), "Warning: npm >=12"),
(npm_allow_remote_unreadable_detail(&hosts, "is a symlink"), "Warning: npm >=12"),
(
npm_allow_remote_unreadable_detail(&hosts, "is a symlink"),
"Warning: npm >=12",
),
];
for (detail, start) in cases {
let line = npm_allow_remote_one_line(&detail);
assert!(line.starts_with(start), "{line}");
assert!(!line.contains('\n') && line.ends_with("(details: --verbose)."), "{line}");
assert!(
!line.contains('\n') && line.ends_with("(details: --verbose)."),
"{line}"
);
}
}
}
Loading
Loading