-
Notifications
You must be signed in to change notification settings - Fork 98
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for index packages #2175
base: master
Are you sure you want to change the base?
Conversation
|
Branch | npm-index |
Testbed | ubuntu-latest |
Click to view all benchmark results
Benchmark | Latency | microseconds (µs) |
---|---|---|
fibonacci 10 | 📈 view plot 🚷 view threshold | 385.66 µs |
foldl arrays 50 | 📈 view plot 🚷 view threshold | 1,542.80 µs |
foldl arrays 500 | 📈 view plot 🚷 view threshold | 5,700.30 µs |
foldr strings 50 | 📈 view plot 🚷 view threshold | 6,541.00 µs |
foldr strings 500 | 📈 view plot 🚷 view threshold | 56,608.00 µs |
generate normal 250 | 📈 view plot 🚷 view threshold | 41,402.00 µs |
generate normal 50 | 📈 view plot 🚷 view threshold | 1,862.20 µs |
generate normal unchecked 1000 | 📈 view plot 🚷 view threshold | 2,732.80 µs |
generate normal unchecked 200 | 📈 view plot 🚷 view threshold | 633.06 µs |
pidigits 100 | 📈 view plot 🚷 view threshold | 2,716.60 µs |
pipe normal 20 | 📈 view plot 🚷 view threshold | 1,271.40 µs |
pipe normal 200 | 📈 view plot 🚷 view threshold | 8,273.00 µs |
product 30 | 📈 view plot 🚷 view threshold | 740.17 µs |
scalar 10 | 📈 view plot 🚷 view threshold | 1,301.30 µs |
sum 30 | 📈 view plot 🚷 view threshold | 731.57 µs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Partial review. Stopped just before package/index/mod.rs
, will continue later.
cli/src/package.rs
Outdated
/// names *must* match the package id in the index, and you must ensure that | ||
/// the version you push to github matches the SHA-1 hash in the index. | ||
/// 7. Open a pull request to `github.com/nickel-lang/nickel-mind` to make your index | ||
/// modifications public. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if the whole description of the process really belongs to the CLI help message. What do you think about putting it somewhere (manual maybe?) and linking to the page here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I've added a manual page about package management in general and included this there.
let snap = manifest.snapshot_dependencies(config.clone())?; | ||
let index = PackageIndex::shared(config.clone())?; | ||
let resolution = resolve::resolve(&manifest, snap, index, config)?; | ||
let package_map = resolution.package_map(&manifest)?; | ||
eprintln!("{package_map}"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
left-over debug statement?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, printing the package map is the main job of this command. (It maybe be time to remove the command, though. It was mainly just to help debug things while implementing...)
cli/src/package.rs
Outdated
@@ -92,7 +125,23 @@ impl PackageCommand { | |||
..config | |||
}; | |||
|
|||
manifest.snapshot_dependencies(config)?; | |||
manifest.snapshot_dependencies(config.clone())?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out of curiosity, why do we need to take a config as an owned value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, I think maybe I can get rid of this one. In some other places it's just convenient to store copies of the config so that we can figure out where various files go.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, we now no longer store Config
in Snapshot
.
cli/src/package.rs
Outdated
/// the version you push to github matches the SHA-1 hash in the index. | ||
/// 7. Open a pull request to `github.com/nickel-lang/nickel-mind` to make your index | ||
/// modifications public. | ||
PublishToLocalIndex { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: this sounds a bit long for a command name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed to "publish".
package/src/error.rs
Outdated
write!(f, "package {id}@{version} is already present in the index") | ||
} | ||
Error::PackageIndexSerialization { error, pkg } => { | ||
write!(f, "error serializing package. Failed package {pkg:?}, caused by {error}\n{INTERNAL_ERROR_MSG}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is some duplication in the error message. Maybe it's a mix of two different versions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I shorted the message. For some reason, rustfmt took that as a cue to spread the code over more lines 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Second chunk: I stopped just before resolve.rs
.
|
||
fn ensure_downloaded_to(&self, index_id: &PreciseId, target_dir: &Path) -> Result<(), Error> { | ||
let PreciseId::Github { org, name, commit } = index_id; | ||
let url = format!("https://github.com/{org}/{name}.git"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we have any injection/url encoding issue here, or are org
and name
sanitized as an invariant?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The manifest format ensures that org
and name
are nickel idents (in the lexer sense, not the "interned string" sense). I'll add a comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I take it back: the FromStr
implementation checks the names, but the manifest doesn't go through that. I'll fix this...
package/src/index/mod.rs
Outdated
return Ok(()); | ||
} | ||
|
||
eprintln!( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
random thought: maybe we will want to have separate macros for outputting status update and errors (so that we can style them a bit, like putting 🫠 in front of errors (or not))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added info
and warn
macros that just wrap eprintln
for now.
package/src/index/mod.rs
Outdated
} | ||
} | ||
|
||
static ID_REGEX: LazyLock<Regex> = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't know something like LazyLock
existed in the standard library. I wonder if this deprecates the usage we make of lazy_static
elsewhere in Nickel.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think so. It's only been in the stdlib since 1.80
package/src/lib.rs
Outdated
} | ||
} | ||
|
||
/// The same as [`Dependency`], but only for the packages that have fixed, unresolvable, versions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does "unresolvable" means in this context? Just we don't get to pick a different one, like rigid version constraints, or something like a precise git ref?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It means that the resolver doesn't care about (or get to pick) the version. Or in other words, a path or git dependency.
Git deps don't need precise versions to be "unresolvable": if a git dep points at HEAD, then we just fetch HEAD and that's the package we depend on. The resolver won't consider whether it should take a different revision.
On the other hand, rigid version constraints on an index package are still "resolvable" in this sense, because their presence affects the resolver's decisions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. Maybe it would be clearer to mention it explicitly ("git ref or path"), because "version" is overloaded quite a bit in our context (I initially though version would only correspond to version bounds, which is why "unresolvable version" sounded a bit paradoxical).
/// This is currently identical to `IndexDependency`, but we keep | ||
/// them separate so it's clear which things are part of our public | ||
/// serialization API. | ||
struct IndexDependencyFormat { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isn't this struct defined two times, here in manifest
but also in index::serialize
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, but one of them defines how to deserialize the manifest (going through the RichTerm
deserializer) and the other defines how to serialize/deserialize the index through serde_json
. The current differences are just cosmetic for now (for some reason I decided to have "github" lower case in the index, but it needs to be upper case for the manifest to match the 'Github
enum), but I think there's some value in allowing them to be different. For example, if we add support for other forges then an old nickel version reading 'Codeberg
from a manifest is allowed to error out immediately (because it won't know how to fetch that dependency), but an old nickel version shouldn't fail to deserialize an index that contains a package hosted on codeberg. (It can fail if the dependency tree contains such a package, though)
Co-authored-by: Yann Hamdaoui <[email protected]>
Co-authored-by: Yann Hamdaoui <[email protected]>
Co-authored-by: Yann Hamdaoui <[email protected]>
Co-authored-by: Yann Hamdaoui <[email protected]>
Co-authored-by: Yann Hamdaoui <[email protected]>
This adds support for a package index, but requires that all the index packages have exact version constraints. As a result, we don't yet need to do version resolution.
The main points of this PR are