Skip to content

Commit

Permalink
Add nupm search for searching packages
Browse files Browse the repository at this point in the history
  • Loading branch information
kubouch committed Jan 28, 2024
1 parent 0b68963 commit e327017
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 105 deletions.
146 changes: 41 additions & 105 deletions nupm/install.nu
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use utils/completions.nu complete-registries
use utils/dirs.nu [ nupm-home-prompt cache-dir module-dir script-dir tmp-dir ]
use utils/log.nu throw-error
use utils/misc.nu check-cols
use utils/registry.nu search-package
use utils/version.nu filter-by-version

def open-package-file [dir: path] {
Expand Down Expand Up @@ -149,110 +150,6 @@ def install-path [
}
}

def fetch-package [
package: string # Name of the package
--registry: string # Which registry to use
--version: any # Package version to install (string or null)
] {
let registries = if (not ($registry | is-empty)) and ($registry in $env.NUPM_REGISTRIES) {
# If $registry is a valid column in $env.NUPM_REGISTRIES, use that
{ $registry : ($env.NUPM_REGISTRIES | get $registry) }
} else if (not ($registry | is-empty)) and ($registry | path exists) {
# If $registry is a path, use that
let reg_name = $registry | path parse | get stem
{ $reg_name: $registry }
} else {
# Otherwise use $env.NUPM_REGISTRIES
$env.NUPM_REGISTRIES
}

# Collect all registries matching the package and all matching packages
let regs = $registries
| items {|name, path|
print $path

# Open registry (online or offline)
let registry = if ($path | path type) == file {
open $path
} else {
try {
let reg = http get $path

if local in $reg {
throw-error ("Can't have local packages in online registry"
+ $" '($path)'.")
}

$reg
} catch {
throw-error $"Cannot open '($path)' as a file or URL."
}
}

$registry | check-cols --missing-ok "registry" [ git local ] | ignore

# Find all packages matching $package in the registry
let pkgs_local = $registry.local?
| default []
| check-cols "local packages" [ name version path ]
| where name == $package

let pkgs_git = $registry.git?
| default []
| check-cols "git packages" [ name version url revision path ]
| where name == $package

# Detect duplicate versions
let all_versions = $pkgs_local.version?
| default []
| append ($pkgs_git.version? | default [])

if ($all_versions | uniq | length) != ($all_versions | length) {
throw-error ($'Duplicate versions of package ($package) detected'
+ $' in registry ($name).')
}

let pkgs = $pkgs_local
| insert type local
| insert url null
| insert revision null
| append ($pkgs_git | insert type git)

{
name: $name
path: $path
pkgs: $pkgs
}
}
| compact

if ($regs | is-empty) {
throw-error 'No registries found'
} else if ($regs | length) > 1 {
# TODO: Here could be interactive prompt
throw-error 'Multiple registries contain the same package'
}

# Now, only one registry contains the package
let reg = $regs | first
let pkgs = $reg.pkgs | filter-by-version $version

let pkg = try {
$pkgs | last
} catch {
throw-error $'No package matching version `($version)`'
}

print $pkg

if $pkg.type == 'git' {
download-pkg $pkg
} else {
# local package path is relative to the registry file (absolute paths
# are discouraged but work)
$reg.path | path dirname | path join $pkg.path
}
}

# Downloads a package and returns its downloaded path
def download-pkg [
Expand Down Expand Up @@ -310,6 +207,45 @@ def download-pkg [
$pkg_dir
}

# Fetch a package from a registry
def fetch-package [
package: string # Name of the package
--registry: string # Which registry to use
--version: string # Package version to install (string or null)
]: nothing -> path {
let regs = (search-package $package
--registry $registry
--version $version
--exact-match)

if ($regs | is-empty) {
throw-error 'No registries found'
} else if ($regs | length) > 1 {
# TODO: Here could be interactive prompt
throw-error 'Multiple registries contain the same package'
}

# Now, only one registry contains the package
let reg = $regs | first
let pkgs = $reg.pkgs | filter-by-version $version

let pkg = try {
$pkgs | last
} catch {
throw-error $'No package matching version `($version)`'
}

print $pkg

if $pkg.type == 'git' {
download-pkg $pkg
} else {
# local package path is relative to the registry file (absolute paths
# are discouraged but work)
$reg.path | path dirname | path join $pkg.path
}
}

# Install a nupm package
#
# Installation consists of two parts:
Expand All @@ -328,7 +264,7 @@ export def main [
return
}

let pkg = if not $path {
let pkg: path = if not $path {
fetch-package $package --registry $registry --version $pkg_version
} else {
if $pkg_version != null {
Expand Down
1 change: 1 addition & 0 deletions nupm/mod.nu
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use utils/dirs.nu [

export module install.nu
export module test.nu
export module search.nu

export-env {
# Ensure that $env.NUPM_HOME is always set when running nupm. Any missing
Expand Down
12 changes: 12 additions & 0 deletions nupm/search.nu
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use utils/completions.nu complete-registries
use utils/registry.nu search-package

# Search for a package
export def main [
package # Name, path, or link to the package
--registry: string@complete-registries # Which registry to use (either a name
# in $env.NUPM_REGISTRIES or a path)
--pkg-version(-v): string # Package version to install
]: nothing -> table {
search-package $package --registry $registry --version $pkg_version
}
79 changes: 79 additions & 0 deletions nupm/utils/registry.nu
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Utilities related to nupm registries

# Search for a package in a registry
export def search-package [
package: string # Name of the package
--registry: string # Which registry to use
--version: any # Package version to install (string or null)
--exact-match # Searched package name must match exactly
] -> table {
let registries = if (not ($registry | is-empty)) and ($registry in $env.NUPM_REGISTRIES) {
# If $registry is a valid column in $env.NUPM_REGISTRIES, use that
{ $registry : ($env.NUPM_REGISTRIES | get $registry) }
} else if (not ($registry | is-empty)) and ($registry | path exists) {
# If $registry is a path, use that
let reg_name = $registry | path parse | get stem
{ $reg_name: $registry }
} else {
# Otherwise use $env.NUPM_REGISTRIES
$env.NUPM_REGISTRIES
}

let name_matcher: closure = if $exact_match {
{|row| $row.name == $package }
} else {
{|row| $package in $row.name }
}

# Collect all registries matching the package and all matching packages
let regs = $registries
| items {|name, path|
print $path

# Open registry (online or offline)
let registry = if ($path | path type) == file {
open $path
} else {
try {
let reg = http get $path

if local in $reg {
throw-error ("Can't have local packages in online registry"
+ $" '($path)'.")
}

$reg
} catch {
throw-error $"Cannot open '($path)' as a file or URL."
}
}

$registry | check-cols --missing-ok "registry" [ git local ] | ignore

# Find all packages matching $package in the registry
let pkgs_local = $registry.local?
| default []
| check-cols "local packages" [ name version path ]
| filter $name_matcher

let pkgs_git = $registry.git?
| default []
| check-cols "git packages" [ name version url revision path ]
| filter $name_matcher

let pkgs = $pkgs_local
| insert type local
| insert url null
| insert revision null
| append ($pkgs_git | insert type git)

{
name: $name
path: $path
pkgs: $pkgs
}
}
| compact

$regs | where not ($it.pkgs | is-empty)
}

0 comments on commit e327017

Please sign in to comment.