Skip to content

Commit

Permalink
Provide a package manager for Inko
Browse files Browse the repository at this point in the history
This adds a package manager for Inko, creatively called "ipm" (Inko
Package Manager).

The package manager doesn't use a centralised package registry, instead
it relies entirely on Git repositories. These repositories can be hosted
anywhere (GitHub, GitLab, locally, etc), as long as the URL is supported
by the Git CLI. For GitHub and GitLab we also support URLs that leave
out the scheme, in which case we translate them to HTTPS URLs.

Packages are specified in the file `inko.pkg`, which must reside at the
root directory of a project. This file is a line based file and lists
the dependencies that are required. Such a file might look as follows:

    require github.com/alice/json 1.2.3 abcdef123
    require gitlab.com/inko-lang/foo 1.3.0 ffee465

Adding and removing entries is done using the commands `ipm add` and
`ipm remove respectively`. To install the dependencies into your
project, you run `ipm sync`. The result is a ./dep directory containing
all your dependencies. The compiler automatically adds this directory to
the load path, if it exists. Updating dependencies is done using `ipm
update`.

The package manager uses minimal version selection, as this is trivial
to implement, leads to predictable builds, doesn't require a SAT solver,
and doesn't require lock files. We don't allow different major versions
of the same package, as this can lead to subtle bugs when data is passed
between these versions.

I opted to make package management a separate process/tool as this makes
it easier to build packages without an internet connection, and because
it's easier to maintain. Packages are installed in a local ./dep
directory because this makes it easier for the compiler to load the
dependencies, and makes packaging a project including all its
dependencies trivial (= just archive the entire project and off you go).

In terms of features the package manager provides, it's quite basic.
Most notably, we don't support overriding packages with local copies at
this time, and error/progress reporting could be improved in various
places. Testing is partially done by hand, as automatic testing of the
various CLI components is a bit tricky due to heavy network usage. We
may improve this in the future.

Changelog: added
  • Loading branch information
yorickpeterse committed Sep 26, 2022
1 parent 5a3fca6 commit ecafac6
Show file tree
Hide file tree
Showing 26 changed files with 2,084 additions and 17 deletions.
69 changes: 69 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
@@ -1,5 +1,5 @@
[workspace]
members = ["ast", "bytecode", "inko", "compiler", "vm"]
members = ["ast", "bytecode", "inko", "compiler", "vm", "ipm"]

[profile.release]
panic = "abort"
Expand Down
20 changes: 15 additions & 5 deletions Makefile
Expand Up @@ -11,8 +11,11 @@ else
INSTALL_PREFIX = ${PREFIX}
endif

# The directory to place the executable in.
INSTALL_BIN := ${INSTALL_PREFIX}/bin/inko
# The directory to place the Inko executable in.
INSTALL_INKO := ${INSTALL_PREFIX}/bin/inko

# The directory to place the package manager executable in.
INSTALL_IPM := ${INSTALL_PREFIX}/bin/ipm

# The directory to place the standard library in.
INSTALL_STD := ${INSTALL_PREFIX}/lib/inko/libstd
Expand Down Expand Up @@ -82,6 +85,7 @@ ${SOURCE_TAR}: ${TMP_DIR}
libstd/src \
vm \
types \
ipm \
| gzip > "${@}"

release/source: ${SOURCE_TAR}
Expand Down Expand Up @@ -117,21 +121,27 @@ ${INSTALL_STD}:
mkdir -p "${@}"
cp -r libstd/src/* "${@}"

${INSTALL_BIN}:
${INSTALL_INKO}:
mkdir -p "$$(dirname ${@})"
install -m755 target/release/inko "${@}"

${INSTALL_IPM}:
mkdir -p "$$(dirname ${@})"
install -m755 target/release/ipm "${@}"

${INSTALL_LICENSE}:
mkdir -p "$$(dirname ${@})"
install -m644 LICENSE "${@}"

install: ${INSTALL_STD} \
${INSTALL_BIN} \
${INSTALL_INKO} \
${INSTALL_IPM} \
${INSTALL_LICENSE}

uninstall:
rm -rf ${INSTALL_STD}
rm -f ${INSTALL_BIN}
rm -f ${INSTALL_INKO}
rm -f ${INSTALL_IPM}
rm -rf ${INSTALL_PREFIX}/share/licenses/inko

clean:
Expand Down
11 changes: 11 additions & 0 deletions compiler/src/config.rs
Expand Up @@ -17,6 +17,9 @@ pub(crate) const MAIN_MODULE: &str = "main";
/// The name of the directory containing a project's source code.
pub(crate) const SOURCE: &str = "src";

/// The name of the directory containing third-party dependencies.
const DEP: &str = "dep";

/// The name of the directory containing a project's unit tests.
const TESTS: &str = "test";

Expand All @@ -32,6 +35,9 @@ pub struct Config {
/// The directory containing the project's source code.
pub(crate) source: PathBuf,

/// The directory containing the project's dependencies.
pub(crate) dependencies: PathBuf,

/// The directory containing the project's unit tests.
pub tests: PathBuf,

Expand Down Expand Up @@ -73,6 +79,7 @@ impl Config {
source: cwd.join(SOURCE),
tests: cwd.join(TESTS),
build: cwd.join(BUILD),
dependencies: cwd.join(DEP),
sources: SourcePaths::new(),
presenter: Box::new(TextPresenter::with_colors()),
implicit_imports: vec![],
Expand All @@ -88,6 +95,10 @@ impl Config {
if self.source.is_dir() && self.source != self.libstd {
self.sources.add(self.source.clone());
}

if self.dependencies.is_dir() {
self.sources.add(self.dependencies.clone());
}
}

fn add_default_implicit_imports(&mut self) {
Expand Down
7 changes: 1 addition & 6 deletions deny.toml
Expand Up @@ -6,11 +6,7 @@ unmaintained = "warn"
yanked = "warn"
notice = "warn"
unsound = "warn"
ignore = [
# https://gitlab.com/inko-lang/inko/-/issues/240#note_798519215
"RUSTSEC-2020-0071",
"RUSTSEC-2020-0056"
]
ignore = []

[licenses]
unlicensed = "deny"
Expand All @@ -20,7 +16,6 @@ allow = [
"MPL-2.0",
"ISC",
"CC0-1.0",
"Unicode-DFS-2016",
"BSD-3-Clause",
]
copyleft = "deny"
Expand Down
1 change: 1 addition & 0 deletions docs/mkdocs.yml
Expand Up @@ -43,6 +43,7 @@ nav:
- getting-started/error-handling.md
- getting-started/concurrency.md
- getting-started/pattern-matching.md
- getting-started/modules.md
- Guides:
- guides/contributing.md
- guides/style-guide.md
Expand Down
8 changes: 7 additions & 1 deletion docs/source/getting-started/installation.md
Expand Up @@ -17,6 +17,9 @@ Unix compatibility layer such as [MSYS2][msys2].
- A CPU with AES-NI support
- Rust 1.62 or newer

Inko's package manager (ipm) also required Git to be installed, and the `git`
executable to be available in your PATH.

For Unix based platforms, the following must also be available

- Make
Expand Down Expand Up @@ -131,7 +134,10 @@ cd 0.10.0
```

To compile a development build, run `cargo build`. For a release build,
run `cargo build --release` instead.
run `cargo build --release` instead. After building you can find the `inko`
executable in `target/release/inko` (or `target/debug/inko` for a debug build),
and the `ipm` executable in `target/release/ipm` (or `target/debug/ipm` for
debug builds).

By default Inko uses the standard library provided in the Git repository,
located in `libstd/src`. If you wish to use a different directory, set the
Expand Down

0 comments on commit ecafac6

Please sign in to comment.