Skip to content
This repository has been archived by the owner on Jun 17, 2024. It is now read-only.

Commit

Permalink
Merge pull request #45 from axodotdev/generic_project_type
Browse files Browse the repository at this point in the history
feat: add generic project type
  • Loading branch information
mistydemeo authored Nov 9, 2023
2 parents e35f7a4 + eb77118 commit 873bf56
Show file tree
Hide file tree
Showing 11 changed files with 260 additions and 4 deletions.
10 changes: 10 additions & 0 deletions Cargo.lock

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

9 changes: 5 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,23 @@ name = "axoproject"
required-features = ["cli"]

[features]
default = ["cli", "cargo-projects", "npm-projects"]
default = ["cli", "generic-projects", "cargo-projects", "npm-projects"]
cli = ["axocli"]
generic-projects = ["semver"]
cargo-projects = ["guppy", "semver"]
npm-projects = ["oro-common", "oro-package-spec", "node-semver"]

[dependencies]
axoasset = { version = "0.6.0", default-features = false, features = ["json-serde", "toml-edit"] }
axoasset = { version = "0.6.0", default-features = false, features = ["json-serde", "toml-edit", "toml-serde"] }
axocli = { version = "0.1.0", optional = true }
camino = "1.1.4"
camino = { version = "1.1.4", default-features = true, features = ["serde1"] }
console = "0.15.5"
miette = "5.6.0"
guppy = { version = "0.17.1", optional = true }
tracing = "0.1.40"
oro-common = { version = "0.3.34", optional = true }
serde = "1.0.192"
semver = { version = "1.0.20", optional = true }
semver = { version = "1.0.20", optional = true, default-features = true, features = ["serde"] }
node-semver = { version = "2.1.0", optional = true }
oro-package-spec = { version = "0.3.34", optional = true }
thiserror = "1.0.50"
Expand Down
113 changes: 113 additions & 0 deletions src/generic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
//! Support for generic projects with cargo-dist build instructions

use axoasset::SourceFile;
use camino::{Utf8Path, Utf8PathBuf};
use serde::Deserialize;

use crate::{PackageInfo, Result, Version, WorkspaceInfo, WorkspaceSearch};

#[derive(Deserialize)]
struct Manifest {
package: Package,
}

#[derive(Deserialize)]
#[serde(rename_all = "kebab-case")]
struct Package {
name: String,
repository: Option<String>,
homepage: Option<String>,
documentation: Option<String>,
description: Option<String>,
readme: Option<Utf8PathBuf>,
#[serde(default = "Vec::new")]
authors: Vec<String>,
binaries: Vec<String>,
license: Option<String>,
changelog: Option<Utf8PathBuf>,
#[serde(default = "Vec::new")]
license_files: Vec<Utf8PathBuf>,
#[serde(default = "Vec::new")]
cstaticlibs: Vec<String>,
#[serde(default = "Vec::new")]
cdylibs: Vec<String>,
build_command: Vec<String>,
version: Option<semver::Version>,
}

/// Try to find a generic workspace at the given path
///
/// See [`crate::get_workspaces`][] for the semantics.
pub fn get_workspace(start_dir: &Utf8Path, clamp_to_dir: Option<&Utf8Path>) -> WorkspaceSearch {
let manifest_path = match crate::find_file("dist.toml", start_dir, clamp_to_dir) {
Ok(path) => path,
Err(e) => return WorkspaceSearch::Missing(e),
};

match workspace_from(&manifest_path) {
Ok(info) => WorkspaceSearch::Found(info),
Err(e) => WorkspaceSearch::Broken {
manifest_path,
cause: e,
},
}
}

fn workspace_from(manifest_path: &Utf8Path) -> Result<WorkspaceInfo> {
let workspace_dir = manifest_path.parent().unwrap().to_path_buf();
let root_auto_includes = crate::find_auto_includes(&workspace_dir)?;

let manifest: Manifest = load_root_dist_toml(manifest_path)?;
let package = manifest.package;
let version = package.version.map(Version::Generic);

let manifest_path = manifest_path.to_path_buf();

let package_info = PackageInfo {
manifest_path: manifest_path.clone(),
package_root: manifest_path.clone(),
name: package.name,
version,
description: package.description,
authors: package.authors,
license: package.license,
publish: true,
keywords: None,
repository_url: package.repository.clone(),
homepage_url: package.homepage,
documentation_url: package.documentation,
readme_file: package.readme,
license_files: package.license_files,
changelog_file: package.changelog,
binaries: package.binaries,
cstaticlibs: package.cstaticlibs,
cdylibs: package.cdylibs,
#[cfg(feature = "cargo-projects")]
cargo_metadata_table: None,
#[cfg(feature = "cargo-projects")]
cargo_package_id: None,
};

Ok(WorkspaceInfo {
kind: crate::WorkspaceKind::Generic,
target_dir: workspace_dir.join("target"),
workspace_dir,
package_info: vec![package_info],
manifest_path,
repository_url: package.repository,
root_auto_includes,
warnings: vec![],
build_command: Some(package.build_command),
#[cfg(feature = "cargo-projects")]
cargo_metadata_table: None,
#[cfg(feature = "cargo-projects")]
cargo_profiles: crate::rust::CargoProfiles::new(),
})
}

/// Load the root workspace toml
fn load_root_dist_toml(manifest_path: &Utf8Path) -> Result<Manifest> {
let manifest_src = SourceFile::load_local(manifest_path)?;
let manifest = manifest_src.deserialize_toml()?;
Ok(manifest)
}
1 change: 1 addition & 0 deletions src/javascript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ fn read_workspace(manifest_path: &Utf8Path) -> Result<WorkspaceInfo> {
repository_url,
root_auto_includes,
warnings: vec![],
build_command: None,
#[cfg(feature = "cargo-projects")]
cargo_metadata_table: None,
#[cfg(feature = "cargo-projects")]
Expand Down
39 changes: 39 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ pub use guppy::PackageId;

pub mod changelog;
pub mod errors;
#[cfg(feature = "generic-projects")]
pub mod generic;
#[cfg(feature = "npm-projects")]
pub mod javascript;
pub mod platforms;
Expand All @@ -34,6 +36,9 @@ use crate::repo::GithubRepoInput;

/// Information about various kinds of workspaces
pub struct Workspaces {
/// Info about the generic workspace
#[cfg(feature = "generic-projects")]
pub generic: WorkspaceSearch,
/// Info about the cargo/rust workspace
#[cfg(feature = "cargo-projects")]
pub rust: WorkspaceSearch,
Expand All @@ -51,6 +56,9 @@ impl Workspaces {
let mut max_depth = 0;
let mut projects = vec![];

#[cfg(feature = "generic-projects")]
projects.push(self.generic);

// FIXME: should we provide feedback/logging here?
#[cfg(feature = "cargo-projects")]
projects.push(self.rust);
Expand Down Expand Up @@ -96,6 +104,9 @@ pub enum WorkspaceSearch {
/// Kind of workspace
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum WorkspaceKind {
/// generic cargo-dist compatible workspace
#[cfg(feature = "generic-projects")]
Generic,
/// cargo/rust workspace
#[cfg(feature = "cargo-projects")]
Rust,
Expand Down Expand Up @@ -137,6 +148,8 @@ pub struct WorkspaceInfo {
pub root_auto_includes: AutoIncludes,
/// Non-fatal issues that were encountered and should probably be reported
pub warnings: Vec<AxoprojectError>,
/// Build command to run for this workspace; not required for cargo
pub build_command: Option<Vec<String>>,
/// Raw cargo `[workspace.metadata]` table
#[cfg(feature = "cargo-projects")]
pub cargo_metadata_table: Option<serde_json::Value>,
Expand Down Expand Up @@ -312,6 +325,9 @@ pub struct PackageIdx(pub usize);
/// A Version abstracted over project type
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Version {
/// generic version (assumed to be semver)
#[cfg(feature = "generic-projects")]
Generic(semver::Version),
/// cargo version
#[cfg(feature = "cargo-projects")]
Cargo(semver::Version),
Expand All @@ -323,6 +339,8 @@ pub enum Version {
impl Display for Version {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
#[cfg(feature = "generic-projects")]
Version::Generic(v) => v.fmt(f),
#[cfg(feature = "cargo-projects")]
Version::Cargo(v) => v.fmt(f),
#[cfg(feature = "npm-projects")]
Expand All @@ -343,6 +361,19 @@ impl Version {
}
}

/// Returns a semver-based Version
#[cfg(any(feature = "generic-projects", feature = "cargo-projects"))]
pub fn semver(&self) -> &semver::Version {
#[allow(unreachable_patterns)]
match self {
#[cfg(feature = "generic-projects")]
Version::Generic(v) => v,
#[cfg(feature = "cargo-projects")]
Version::Cargo(v) => v,
_ => panic!("Version wasn't in semver format"),
}
}

/// Assume it's an npm Version
#[cfg(feature = "npm-projects")]
pub fn npm(&self) -> &node_semver::Version {
Expand All @@ -357,6 +388,8 @@ impl Version {
/// Returns whether the version is stable (no pre/build component)
pub fn is_stable(&self) -> bool {
match self {
#[cfg(feature = "generic-projects")]
Version::Generic(v) => v.pre.is_empty() && v.build.is_empty(),
#[cfg(feature = "cargo-projects")]
Version::Cargo(v) => v.pre.is_empty() && v.build.is_empty(),
#[cfg(feature = "npm-projects")]
Expand All @@ -367,6 +400,10 @@ impl Version {
/// Gets a copy of the version with only the stable parts (pre/build components stripped)
pub fn stable_part(&self) -> Self {
match self {
#[cfg(feature = "generic-projects")]
Version::Generic(v) => {
Version::Generic(semver::Version::new(v.major, v.minor, v.patch))
}
#[cfg(feature = "cargo-projects")]
Version::Cargo(v) => Version::Cargo(semver::Version::new(v.major, v.minor, v.patch)),
#[cfg(feature = "npm-projects")]
Expand Down Expand Up @@ -411,6 +448,8 @@ pub struct AutoIncludes {
/// the top level [`WorkspaceKind`][].
pub fn get_workspaces(start_dir: &Utf8Path, clamp_to_dir: Option<&Utf8Path>) -> Workspaces {
Workspaces {
#[cfg(feature = "generic-projects")]
generic: generic::get_workspace(start_dir, clamp_to_dir),
#[cfg(feature = "cargo-projects")]
rust: rust::get_workspace(start_dir, clamp_to_dir),
#[cfg(feature = "npm-projects")]
Expand Down
12 changes: 12 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ fn real_main(app: &axocli::CliApp<Cli>) -> Result<(), Report> {
}

fn print_searches(workspaces: Workspaces) {
#[cfg(feature = "generic-projects")]
print_search(workspaces.generic, "generic");
#[cfg(feature = "cargo-projects")]
print_search(workspaces.rust, "rust");
#[cfg(feature = "npm-projects")]
Expand Down Expand Up @@ -158,6 +160,8 @@ fn print_workspace(project: &WorkspaceInfo) {
fn print_searches_json(root: Option<&Utf8Path>, workspaces: Workspaces) {
let output = JsonOutput {
root: root.map(|p| p.to_owned()),
#[cfg(feature = "generic-projects")]
generic: JsonWorkspaceSearch::from_real(root, workspaces.generic),
#[cfg(feature = "cargo-projects")]
rust: JsonWorkspaceSearch::from_real(root, workspaces.rust),
#[cfg(feature = "npm-projects")]
Expand All @@ -170,6 +174,8 @@ fn print_searches_json(root: Option<&Utf8Path>, workspaces: Workspaces) {
#[derive(Serialize, Deserialize)]
struct JsonOutput {
root: Option<Utf8PathBuf>,
#[cfg(feature = "generic-projects")]
generic: JsonWorkspaceSearch,
#[cfg(feature = "cargo-projects")]
rust: JsonWorkspaceSearch,
#[cfg(feature = "npm-projects")]
Expand Down Expand Up @@ -357,6 +363,10 @@ impl JsonRelPath {
/// Kind of workspace
#[derive(Debug, Serialize, Deserialize)]
pub enum JsonWorkspaceKind {
/// generic workspace
#[cfg(feature = "generic-projects")]
#[serde(rename = "generic")]
Generic,
/// cargo/rust workspace
#[cfg(feature = "cargo-projects")]
#[serde(rename = "rust")]
Expand All @@ -370,6 +380,8 @@ pub enum JsonWorkspaceKind {
impl JsonWorkspaceKind {
fn from_real(real: WorkspaceKind) -> Self {
match real {
#[cfg(feature = "generic-projects")]
WorkspaceKind::Generic => Self::Generic,
#[cfg(feature = "cargo-projects")]
WorkspaceKind::Rust => Self::Rust,
#[cfg(feature = "npm-projects")]
Expand Down
1 change: 1 addition & 0 deletions src/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ fn workspace_info(pkg_graph: &PackageGraph) -> Result<WorkspaceInfo> {
cargo_profiles,

warnings,
build_command: None,
})
}

Expand Down
16 changes: 16 additions & 0 deletions src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,3 +559,19 @@ fn test_changelog_errors() {
Err(AxoprojectError::ParseChangelog(..))
));
}

#[test]
fn test_generic_c() {
let project = crate::get_workspaces("tests/projects/generic-c/".into(), None)
.best()
.unwrap();
assert_eq!(project.kind, WorkspaceKind::Generic);
assert_eq!(project.package_info.len(), 1);

let package = &project.package_info[0];
assert_eq!(package.name, "testprog");
assert_eq!(package.binaries.len(), 1);

let binary = &package.binaries[0];
assert_eq!(binary, "main");
}
13 changes: 13 additions & 0 deletions tests/projects/generic-c/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
CC := gcc
RM := rm
EXEEXT :=

all: main$(EXEEXT)

main$(EXEEXT):
$(CC) main.c -o main$(EXEEXT)

clean:
$(RM) -f main$(EXEEXT)

.PHONY: all clean
Loading

0 comments on commit 873bf56

Please sign in to comment.