nushell / nupm

A manager for Nushell packages.
MIT License
153 stars 9 forks source link

augment the install capabilities of `nupm install` #10

Closed amtoine closed 1 year ago

amtoine commented 1 year ago

there was no particular entry on this in the design document, so i thought we might want to discuss a bit before implementing :yum:

currently nupm install assumes the --path directory is the root of a module. this both

installing...

... a script

assuming $path is the full path to the script, installing a script boils down to

let script = ($path | path basename)
let destination = (nupm-home | path join $script)

cp $path $destination
chmod +x $destination

... a plugin

the question here really is: how can we specify all this in a package.nuon metadata file?

amtoine commented 1 year ago

currently, a valid package.nuon looks like

{
    name: "nu-package"
    version: 0.1.0
    description: "some package"
    license: "https://my_license.com"
}

maybe this kind of metadata file could mean: install the package as a module with a mod.nu in it's root

we could also be explicit about it with

{
    name: "nu-package"
    version: 0.1.0
    description: "some package"
    license: "https://my_license.com"
    type: ROOT_MODULE
}

non-root module

{
    name: "nu-package"
    version: 0.1.0
    description: "some package"
    license: "https://my_license.com"
    type: NON_ROOT_MODULE
}

this could mean: install the module from the directory with the same name, e.g. ./nu-package/ or ./package/ instead of ./

plugins

{
    name: "nu-package"
    version: 0.1.0
    description: "some package"
    license: "https://my_license.com"
    type: PLUGIN
}

this would install the --path as a plugin

scripts

maybe here we need to give a list of scripts to be installed?

{
    name: "nu-package"
    version: 0.1.0
    description: "some package"
    license: "https://my_license.com"
    type: SCRIPTS
    scripts: [  # this would not be required in general but would here with `type` set to `SCRIPTS`
        global_script.nu
        scripts/default/*.nu
    ]
}

what do you guys think about that? :yum:

fdncred commented 1 year ago

assuming $path is the full path to the script, installing a script boils down to

Just throwing this in, chmod +x $destination isn't a Windows thing. I mention this because I'm hoping we stay as cross-platform as possible.

On Windows, file type association would have to take place for a script to be executable, although I'm not sure that would be the right way to go.

amtoine commented 1 year ago

@fdncred good catch Darren :ok_hand:

we could do something like

if $nu.os-info.name == windows {
    ...
} else {
    chmod +x $destination
}

i'd just need some steps to follow for the windows case, because i have no idea what should be done to make that happen :thinking:

how would you make a Nushell script executable on Windows?

fdncred commented 1 year ago

I think the only way to do it is to use the cmd.exe internal command assoc. However, most people don't like something fiddling with their file associations since it's a windows registry change and traditionally can hork things no matter how benign it appears. I think the safest thing to do would be to run nu script.nu.

amtoine commented 1 year ago

I think the only way to do it is to use the cmd.exe internal command assoc. However, most people don't like something fiddling with their file associations since it's a windows registry change and traditionally can hork things no matter how benign it appears.

mm ok, not sure how to do that concretely then... i mean, for instance when you cargo install something on windows, it will put a crate.exe binary executable in $env.CARGO_HOME | path join "bin" so that if it's in your $env.PATH, you can run the application with crate directly, right?

I think the safest thing to do would be to run nu script.nu.

mm i don't think we want that :thinking: the idea is to install a script, directly in the PATH and have it available right away by calling the name of the script in the REPL :confused:

fdncred commented 1 year ago

you can run the application with crate directly, right?

right.

mm i don't think we want that 🤔 the idea is to install a script, directly in the PATH and have it available right away by calling the name of the script in the REPL 😕

I'm not sure we're going to have much of a choice. Windows doesn't have shebangs and like i said, messing with file associations is kind of a no-no. Some people may not have problems with it, some will get very irate. At the end of the day, even if you use this file association methodology I'm talking about, it's just going to do nu script.nu anyway. It's not like nu is a runnable file type. We could look at adding it to $env.PATHEXT, but that's messing with the registry again. It would take some research just to figure out how that works.

kubouch commented 1 year ago

Yes, the type field is a required metadata field and basically tells nupm how to install the package: https://github.com/nushell/nupm/blob/main/docs/design/references/METADATA.md . I'd consider three options for now:

We could specialize these later (e.g., plugins). I'd leave these for later as they could be worked around with build.nu and would be good to design them separately. For example, I wouldn't require Cargo.toml for plugins because you can write plugins in any language, not just Rust. We also probably need to look into how plugins work in general in Nushell.

Finally, this is not specific to nupm install. We need to define a set of standardized package types that nupm recognizes and these would be respected in other commands as well, like nupm uninstall and need to work with overlays. So I would start with a small set (like the three I suggested), then add more one-by-one, as needed, considering the entire nupm, not just nupm install.

For the chmod +x problem, we could expect the package author to commit the file with the right permissions. On Windows, you'd need to run it with nu script.nu where one help would be to add built-in completions to nu to complete scripts found in PATH. It would be interesting to see how other package managers, like cargo, do this.

amtoine commented 1 year ago

Yes, the type field is a required metadata field and basically tells nupm how to install the package: https://github.com/nushell/nupm/blob/main/docs/design/references/METADATA.md .

yup you're right :thumbsup:

I'd consider three options for now:

  • module: requires directory with the package name with mod.nu. IMO, it's not necessary to have single-file modules, it just adds more complexity. I'm not strongly against it but I don't see much value vs. the added complexity.
  • script: single file, meant as executable
  • custom: runs build.nu

We could specialize these later (e.g., plugins). I'd leave these for later as they could be worked around with build.nu and would be good to design them separately. For example, I wouldn't require Cargo.toml for plugins because you can write plugins in any language, not just Rust. We also probably need to look into how plugins work in general in Nushell.

looks sensible to me :ok_hand: type: module, type: script and type: custom then!

Finally, this is not specific to nupm install. We need to define a set of standardized package types that nupm recognizes and these would be respected in other commands as well, like nupm uninstall and need to work with overlays. So I would start with a small set (like the three I suggested), then add more one-by-one, as needed, considering the entire nupm, not just nupm install.

yup, i mention nupm install each time because we do not have anything else for now, but yeah this will be for the other commands as well.

For the chmod +x problem, we could expect the package author to commit the file with the right permissions.

mm i don't know... it's probably better to make it executable anyway. imagine as a user installing a script with the wrong x permissions :open_mouth:

On Windows, you'd need to run it with nu script.nu where one help would be to add built-in completions to nu to complete scripts found in PATH. It would be interesting to see how other package managers, like cargo, do this.

:thumbsup:

amtoine commented 1 year ago

and also about the type key :thinking:

apart from type: custom which would use a custom build.nu script, the other two would need to have default behaviours.

maybe something like this:

and the last question to answer i'd say: what if the package is like a module AND has a script in it? maybe the type: script should just come as a list of paths in the repo everytime :thinking:

skelly37 commented 1 year ago
* `type: module` will try to install in order

  * a module based on `mod.nu` inside a directory in the root with the same name as the package
  * the same but with `mod.nu` in the root of the repo next
  * what if the module is in `src/`? => there could be a path given in `package.nuon`
* `type: script` will try to install in order

  * a file with the same name as the package with the `.nu` extension
  * a `script.nu`

Nothing to comment, seems just about right 😃

    what if the script is not in the root of the repo?

I think that we can specify a few standard places, e.g. root, bin/, apps/, scripts/ and so on... And if the maintaner wants more flexibility, they should simply use custom imo

* `type: custom` will use a `build.nu` in the root of the repo

Yes

and the last question to answer i'd say: what if the package is like a module AND has a script in it? maybe the type: script should just come as a list of paths in the repo everytime thinking

Could you elaborate further on what's a package like a module that has a script in it? Are you talking about something that has both script to execute and library code to use directly instead of calling the CLI script?

amtoine commented 1 year ago

Could you elaborate further on what's a package like a module that has a script in it? Are you talking about something that has both script to execute and library code to use directly instead of calling the CLI script?

iirc what my past me was trying to say, let me give you an example :yum:

i have the following package, nu-goat-scripts, which is both a module and has executable scripts.

the question is: how should nupm install know how to install these scripts to the Nupm location in the PATH?

skelly37 commented 1 year ago

Hm, for now I would stick with:

It is a valid concern but I think it is too much for a single PR — let us do it incrementally 😃