Skip to content

Commit

Permalink
Merge pull request #1099 from veryl-lang/relative_path_dep
Browse files Browse the repository at this point in the history
Support relative path dependency
  • Loading branch information
dalance authored Nov 26, 2024
2 parents c073b24 + c7ce6b4 commit ea13d5a
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 32 deletions.
10 changes: 5 additions & 5 deletions crates/metadata/src/git/command.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
use crate::metadata::UrlPath;
use crate::metadata_error::MetadataError;
use log::debug;
use std::path::{Path, PathBuf};
use std::process::Command;
use thiserror::Error;
use url::Url;

pub struct Git {
path: PathBuf,
}

#[derive(Error, Debug)]
#[error("git operation failure: \"{msg}\"\n {context}")]
#[error("git command failed: \"{msg}\"\n {context}")]
pub struct GitCommandError {
msg: String,
context: String,
Expand Down Expand Up @@ -52,14 +52,14 @@ impl Git {
})
}

pub fn clone(url: &Url, path: &Path) -> Result<Self, MetadataError> {
pub fn clone(url: &UrlPath, path: &Path) -> Result<Self, MetadataError> {
let current_dir = path.parent().unwrap();
let target = path.file_name().unwrap();

if !path.exists() {
let output = Command::new(GIT_COMMAND)
.arg("clone")
.arg(url.as_str())
.arg(url.to_string())
.arg(target)
.current_dir(current_dir)
.output()?;
Expand All @@ -80,7 +80,7 @@ impl Git {
}

let context = String::from_utf8_lossy(&output.stderr).to_string();
let msg = format!("failed to clone repository: {}", url.as_str());
let msg = format!("failed to clone repository: {}", url);
return Err(GitCommandError { msg, context }.into());
}
debug!("Cloned repository ({})", url);
Expand Down
2 changes: 1 addition & 1 deletion crates/metadata/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub use doc::Doc;
pub use format::Format;
pub use lint::{Case, Lint};
pub use lockfile::Lockfile;
pub use metadata::{BumpKind, Metadata};
pub use metadata::{BumpKind, Metadata, UrlPath};
pub use metadata_error::MetadataError;
pub use project::Project;
pub use pubfile::{Pubfile, Release};
Expand Down
62 changes: 42 additions & 20 deletions crates/metadata/src/lockfile.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::git::Git;
use crate::metadata::{Dependency, Metadata};
use crate::metadata::{Dependency, Metadata, UrlPath};
use crate::metadata_error::MetadataError;
use crate::pubfile::{Pubfile, Release};
use log::info;
Expand All @@ -9,7 +9,6 @@ use std::collections::{HashMap, HashSet};
use std::fs;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use url::Url;
use uuid::Uuid;
use veryl_path::PathSet;

Expand All @@ -18,9 +17,11 @@ use veryl_path::PathSet;
pub struct Lockfile {
projects: Vec<Lock>,
#[serde(skip)]
pub lock_table: HashMap<Url, Vec<Lock>>,
pub lock_table: HashMap<UrlPath, Vec<Lock>>,
#[serde(skip)]
force_update: bool,
#[serde(skip)]
pub metadata_path: PathBuf,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
Expand All @@ -29,7 +30,7 @@ pub struct Lock {
pub name: String,
pub uuid: Uuid,
pub version: Version,
pub url: Url,
pub url: UrlPath,
pub revision: String,
pub dependencies: Vec<LockDependency>,
#[serde(skip)]
Expand All @@ -41,15 +42,17 @@ pub struct Lock {
pub struct LockDependency {
pub name: String,
pub version: Version,
pub url: Url,
pub url: UrlPath,
pub revision: String,
}

impl Lockfile {
pub fn load<T: AsRef<Path>>(path: T) -> Result<Self, MetadataError> {
let path = path.as_ref().canonicalize()?;
pub fn load(metadata: &Metadata) -> Result<Self, MetadataError> {
let path = metadata.lockfile_path.canonicalize()?;
let text = fs::read_to_string(path)?;
let mut ret = Self::from_str(&text)?;
ret.metadata_path = metadata.metadata_path.clone();

let mut locks = Vec::new();
locks.append(&mut ret.projects);

Expand Down Expand Up @@ -82,7 +85,10 @@ impl Lockfile {
}

pub fn new(metadata: &Metadata) -> Result<Self, MetadataError> {
let mut ret = Lockfile::default();
let mut ret = Lockfile {
metadata_path: metadata.metadata_path.clone(),
..Default::default()
};

let mut name_table = HashSet::new();
let mut uuid_table = HashSet::new();
Expand Down Expand Up @@ -196,14 +202,30 @@ impl Lockfile {
Ok(())
}

fn git_clone(&self, url: &UrlPath, path: &Path) -> Result<Git, MetadataError> {
let url = match url {
UrlPath::Url(x) => UrlPath::Url(x.clone()),
UrlPath::Path(x) => {
if x.is_relative() {
let path = self.metadata_path.parent().unwrap().join(x);
UrlPath::Path(path)
} else {
UrlPath::Path(x.clone())
}
}
};

Git::clone(&url, path)
}

fn sort_table(&mut self) {
for locks in self.lock_table.values_mut() {
locks.sort_by(|a, b| b.version.cmp(&a.version));
}
}

fn gen_uuid(url: &Url, revision: &str) -> Result<Uuid, MetadataError> {
let mut url = url.as_str().to_string();
fn gen_uuid(url: &UrlPath, revision: &str) -> Result<Uuid, MetadataError> {
let mut url = url.to_string();
url.push_str(revision);
Ok(Uuid::new_v5(&Uuid::NAMESPACE_URL, url.as_bytes()))
}
Expand Down Expand Up @@ -287,7 +309,7 @@ impl Lockfile {

fn resolve_dependency(
&mut self,
url: &Url,
url: &UrlPath,
dep: &Dependency,
) -> Result<Vec<(Release, Option<String>)>, MetadataError> {
Ok(match dep {
Expand All @@ -312,7 +334,7 @@ impl Lockfile {

fn resolve_version(
&mut self,
url: &Url,
url: &UrlPath,
version_req: &VersionReq,
) -> Result<Release, MetadataError> {
if let Some(release) = self.resolve_version_from_lockfile(url, version_req)? {
Expand All @@ -330,7 +352,7 @@ impl Lockfile {

fn resolve_version_from_lockfile(
&mut self,
url: &Url,
url: &UrlPath,
version_req: &VersionReq,
) -> Result<Option<Release>, MetadataError> {
if let Some(locks) = self.lock_table.get_mut(url) {
Expand All @@ -348,15 +370,15 @@ impl Lockfile {
Ok(None)
}

fn resolve_path(url: &Url) -> Result<PathBuf, MetadataError> {
fn resolve_path(url: &UrlPath) -> Result<PathBuf, MetadataError> {
let resolve_dir = veryl_path::cache_path().join("resolve");
let uuid = Self::gen_uuid(url, "")?;
Ok(resolve_dir.join(uuid.simple().encode_lower(&mut Uuid::encode_buffer())))
}

fn resolve_version_from_latest(
&mut self,
url: &Url,
url: &UrlPath,
version_req: &VersionReq,
) -> Result<Release, MetadataError> {
let resolve_dir = veryl_path::cache_path().join("resolve");
Expand All @@ -367,7 +389,7 @@ impl Lockfile {

let path = Self::resolve_path(url)?;
let lock = veryl_path::lock_dir("resolve")?;
let git = Git::clone(url, &path)?;
let git = self.git_clone(url, &path)?;
git.fetch()?;
git.checkout(None)?;
veryl_path::unlock_dir(lock)?;
Expand All @@ -389,13 +411,13 @@ impl Lockfile {
})
}

fn dependency_path(url: &Url, revision: &str) -> Result<PathBuf, MetadataError> {
fn dependency_path(url: &UrlPath, revision: &str) -> Result<PathBuf, MetadataError> {
let dependencies_dir = veryl_path::cache_path().join("dependencies");
let uuid = Self::gen_uuid(url, revision)?;
Ok(dependencies_dir.join(uuid.simple().encode_lower(&mut Uuid::encode_buffer())))
}

fn get_metadata(&self, url: &Url, revision: &str) -> Result<Metadata, MetadataError> {
fn get_metadata(&self, url: &UrlPath, revision: &str) -> Result<Metadata, MetadataError> {
let dependencies_dir = veryl_path::cache_path().join("dependencies");

if !dependencies_dir.exists() {
Expand All @@ -407,7 +429,7 @@ impl Lockfile {

if !path.exists() {
let lock = veryl_path::lock_dir("dependencies")?;
let git = Git::clone(url, &path)?;
let git = self.git_clone(url, &path)?;
git.fetch()?;
git.checkout(Some(revision))?;
veryl_path::unlock_dir(lock)?;
Expand All @@ -419,7 +441,7 @@ impl Lockfile {
if !ret || !toml.exists() {
let lock = veryl_path::lock_dir("dependencies")?;
fs::remove_dir_all(&path)?;
let git = Git::clone(url, &path)?;
let git = self.git_clone(url, &path)?;
git.fetch()?;
git.checkout(Some(revision))?;
veryl_path::unlock_dir(lock)?;
Expand Down
24 changes: 22 additions & 2 deletions crates/metadata/src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use serde::{Deserialize, Serialize};
use spdx::Expression;
use std::collections::HashMap;
use std::env;
use std::fmt;
use std::fs;
use std::path::{Path, PathBuf};
use std::str::FromStr;
Expand Down Expand Up @@ -47,7 +48,7 @@ pub struct Metadata {
#[serde(default)]
pub test: Test,
#[serde(default)]
pub dependencies: HashMap<Url, Dependency>,
pub dependencies: HashMap<UrlPath, Dependency>,
#[serde(skip)]
pub metadata_path: PathBuf,
#[serde(skip)]
Expand All @@ -60,6 +61,25 @@ pub struct Metadata {
pub lockfile: Lockfile,
}

#[derive(Clone, Debug, Serialize, Deserialize, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[serde(untagged)]
pub enum UrlPath {
Url(Url),
Path(PathBuf),
}

impl fmt::Display for UrlPath {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
UrlPath::Url(x) => x.fmt(f),
UrlPath::Path(x) => {
let text = x.to_string_lossy();
text.fmt(f)
}
}
}
}

static VALID_PROJECT_NAME: Lazy<Regex> =
Lazy::new(|| Regex::new(r"^[a-zA-Z_][0-9a-zA-Z_]*$").unwrap());

Expand Down Expand Up @@ -201,7 +221,7 @@ impl Metadata {

pub fn update_lockfile(&mut self) -> Result<(), MetadataError> {
let modified = if self.lockfile_path.exists() {
let mut lockfile = Lockfile::load(&self.lockfile_path)?;
let mut lockfile = Lockfile::load(self)?;
let modified = lockfile.update(self, false)?;
self.lockfile = lockfile;
modified
Expand Down
5 changes: 3 additions & 2 deletions crates/metadata/src/metadata_error.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::metadata::UrlPath;
use miette::{self, Diagnostic};
use semver::Version;
use std::path::PathBuf;
Expand All @@ -24,7 +25,7 @@ pub enum MetadataError {
StripPrefix(#[from] std::path::StripPrefixError),

#[diagnostic(code(MetadataError::Git), help(""))]
#[error("git operation failure")]
#[error("git operation failure: {0}")]
Git(Box<dyn std::error::Error + Sync + Send>),

#[diagnostic(
Expand Down Expand Up @@ -55,7 +56,7 @@ pub enum MetadataError {

#[diagnostic(code(MetadataError::VersionNotFound), help(""))]
#[error("{version} @ {url} is not found")]
VersionNotFound { url: Url, version: String },
VersionNotFound { url: UrlPath, version: String },

#[diagnostic(code(MetadataError::GitSpec), help(""))]
#[error("no version/rev/tag/branch specification of {0}")]
Expand Down
11 changes: 10 additions & 1 deletion crates/veryl/src/cmd_publish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use log::{info, warn};
use miette::{bail, IntoDiagnostic, Result, WrapErr};
use std::fs;
use veryl_analyzer::Analyzer;
use veryl_metadata::Metadata;
use veryl_metadata::{Metadata, UrlPath};
use veryl_parser::Parser;

pub struct CmdPublish {
Expand All @@ -29,6 +29,15 @@ impl CmdPublish {
}
}

for url in metadata.dependencies.keys() {
if let UrlPath::Path(x) = url {
bail!(
"path dependency \"{}\" is used, it can't be published",
x.to_string_lossy()
);
}
}

let mut check_error = CheckError::default();
let mut contexts = Vec::new();

Expand Down
2 changes: 1 addition & 1 deletion crates/veryl/src/cmd_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ impl CmdUpdate {

pub fn exec(&self, metadata: &mut Metadata) -> Result<bool> {
if metadata.lockfile_path.exists() {
let mut lockfile = Lockfile::load(&metadata.lockfile_path)?;
let mut lockfile = Lockfile::load(metadata)?;
let modified = lockfile.update(metadata, true)?;
if modified {
lockfile.save(&metadata.lockfile_path)?;
Expand Down

0 comments on commit ea13d5a

Please sign in to comment.