Skip to content

Commit

Permalink
feat(imports): implement imports from local paths
Browse files Browse the repository at this point in the history
  • Loading branch information
kaspar030 committed Sep 13, 2024
1 parent 92aa4ff commit f6654ce
Show file tree
Hide file tree
Showing 22 changed files with 206 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased] - ReleaseDate

### Added

- implement `imports` from local paths

## [0.1.23] - 2024-09-07

## [0.1.22] - 2024-09-07
Expand Down
24 changes: 24 additions & 0 deletions book/src/reference/import/path.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# `path`

A `path` import allows using a local directory as import source.

If `path` is not absolute, it is considered relative to the project root.

Optionally, `path` can be symlinked into the `imports` folder inside the laze
build directory by setting `symlink: true` in the import.
The symlink name within `$build_dir/imports` defaults to the last path component
of `path`. This can be changed by setting `name`.
Using a symlink helps turning absolute pathnames into relative ones. This might
be desirable for privacy reasons, or help with reproducible builds.

Example:

```yaml
imports:
- path: /path/to/local/folder
- path: /path/to/another/local/folder
symlink: true
- path: /path/to/a/third/local/folder
symlink: true
name: folder3
```
1 change: 1 addition & 0 deletions book/src/reference/imports.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ imports:

- [`git`](./import/git.md)
- [`laze`](./import/laze.md)
- [`path`](./import/path.md)
3 changes: 3 additions & 0 deletions src/data/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,22 @@ use serde::{Deserialize, Serialize};

mod cmd;
mod download;
mod local;

#[derive(Debug, Serialize, Deserialize, Hash)]
#[serde(untagged)]
pub enum ImportEntry {
Download(crate::download::Download),
Command(cmd::Command),
Local(local::Local),
}

impl ImportEntry {
pub fn handle<T: AsRef<Utf8Path>>(&self, build_dir: T) -> Result<Utf8PathBuf, Error> {
match self {
Self::Download(download) => download.handle(build_dir),
Self::Command(command) => command.handle(build_dir),
Self::Local(local) => local.handle(build_dir),
}
}
}
Expand Down
78 changes: 78 additions & 0 deletions src/data/import/local.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use anyhow::{Context, Error};
use camino::{Utf8Path, Utf8PathBuf};
use serde::{Deserialize, Serialize};

use crate::serde_bool_helpers::default_as_false;

#[derive(Debug, Serialize, Deserialize, Hash)]
pub struct Local {
name: Option<String>,
path: Utf8PathBuf,
dldir: Option<String>,
#[serde(default = "default_as_false")]
symlink: bool,
}

impl super::Import for Local {
fn get_path<T: AsRef<Utf8Path>>(&self, build_dir: T) -> Result<Utf8PathBuf, Error> {
let mut res = Utf8PathBuf::from(build_dir.as_ref());
res.push("imports");
if let Some(dldir) = self.get_dldir() {
res.push(dldir);
} else if let Some(name) = self.get_name() {
res.push(name);
} else {
res.push(self.path.file_name().unwrap());
}
Ok(res)
}

fn get_name(&self) -> Option<String> {
self.name.clone()
}

fn get_dldir(&self) -> Option<&String> {
self.dldir.as_ref()
}

fn handle<T: AsRef<camino::Utf8Path>>(
&self,
build_dir: T,
) -> Result<camino::Utf8PathBuf, anyhow::Error> {
if self.symlink {
let path = self.get_path(&build_dir)?;

let path_parent = path.parent().unwrap();
std::fs::create_dir_all(path_parent).with_context(|| format!("creating {path}"))?;

let link_target = if self.path.is_relative() {
let relpath = pathdiff::diff_utf8_paths(&self.path, path_parent).unwrap();
relpath
} else {
self.path.clone()
};

let mut link_is_missing = true;
if path.is_symlink() {
if path.read_link().unwrap() == link_target {
link_is_missing = false;
} else {
std::fs::remove_file(&path).with_context(|| format!("removing {path}"))?;
}
} else if path.exists() {
return Err(anyhow!("import target {path} exists and is not empty!"));
}

if link_is_missing {
// TODO: windows support
std::os::unix::fs::symlink(&link_target, &path)
.with_context(|| format!("creating symlink {link_target}"))
.with_context(|| format!("importing path {}", self.path))?;
}
// using `path` here as that is the path relative to the project root.
super::get_lazefile(&path)
} else {
super::get_lazefile(&self.path)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
builddir = build
build ALWAYS: phony
rule CC_7950216292150676175
command = cat ${in} > ${out}
description = CC

build build/objects/testpath/foo.8352856137977294963.o: $
CC_7950216292150676175 $
testpath/foo.c

rule LINK_5506617845631750009
command = cat ${in} > ${out}
description = LINK

build build/single_builder/imported_app/imported_app.elf: $
LINK_5506617845631750009 $
build/objects/testpath/foo.8352856137977294963.o

build build/objects/build/imports/testpath2/foo.8352856137977294963.o: $
CC_7950216292150676175 $
build/imports/testpath2/foo.c

build build/single_builder/imported_app2/imported_app2.elf: $
LINK_5506617845631750009 $
build/objects/build/imports/testpath2/foo.8352856137977294963.o

build build/objects/build/imports/testpath3_renamed/foo.8352856137977294963.o: $
CC_7950216292150676175 $
build/imports/testpath3_renamed/foo.c

build build/single_builder/imported_app3/imported_app3.elf: $
LINK_5506617845631750009 $
build/objects/build/imports/testpath3_renamed/foo.8352856137977294963.o

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
foo
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
foo
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
foo
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
foo
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
foo
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
foo
24 changes: 24 additions & 0 deletions src/tests/45_import_from_local_path/laze-project.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
builders:
- name: single_builder
rules:
- name: CC
in: 'c'
out: 'o'
cmd: 'cat ${in} > ${out}'
- name: LINK
in: 'o'
cmd: 'cat ${in} > ${out}'

env:
bindir: build/${builder}/${app}

imports:
# test a relative import
- path: testpath
# test a relative import, symlinked
- path: testpath2
symlink: true
# test a relative import, symlinked, renamed
- path: testpath3
symlink: true
name: testpath3_renamed
15 changes: 15 additions & 0 deletions src/tests/45_import_from_local_path/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/sh

. ../test-common.sh

cleanup

${LAZE} build -g

clean_temp_files

diff -r build build_expected

echo TEST_OK

cleanup
1 change: 1 addition & 0 deletions src/tests/45_import_from_local_path/testpath/foo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
foo
4 changes: 4 additions & 0 deletions src/tests/45_import_from_local_path/testpath/laze.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
apps:
- name: imported_app
sources:
- foo.c
1 change: 1 addition & 0 deletions src/tests/45_import_from_local_path/testpath2/foo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
foo
4 changes: 4 additions & 0 deletions src/tests/45_import_from_local_path/testpath2/laze.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
apps:
- name: imported_app2
sources:
- foo.c
1 change: 1 addition & 0 deletions src/tests/45_import_from_local_path/testpath3/foo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
foo
4 changes: 4 additions & 0 deletions src/tests/45_import_from_local_path/testpath3/laze.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
apps:
- name: imported_app3
sources:
- foo.c

0 comments on commit f6654ce

Please sign in to comment.