recipe: basic recipe parsing
This commit is contained in:
+52
-47
@@ -23,23 +23,23 @@ pub enum PlanError {
|
||||
CycleDetected,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum PlanKey<'a> {
|
||||
SourceFetch(&'a SourceRecipe),
|
||||
SourcePatch(&'a SourceRecipe),
|
||||
SourcePrepare(&'a SourceRecipe),
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum PlanKey {
|
||||
SourceFetch(String),
|
||||
SourcePatch(String),
|
||||
SourcePrepare(String),
|
||||
|
||||
ToolConfigure(&'a ToolRecipe),
|
||||
ToolBuild(&'a ToolRecipe),
|
||||
ToolInstall(&'a ToolRecipe),
|
||||
ToolConfigure(String),
|
||||
ToolBuild(String),
|
||||
ToolInstall(String),
|
||||
|
||||
PkgConfigure(&'a PackageRecipe),
|
||||
PkgBuild(&'a PackageRecipe),
|
||||
PkgInstall(&'a PackageRecipe),
|
||||
PkgPackage(&'a PackageRecipe),
|
||||
PkgConfigure(String),
|
||||
PkgBuild(String),
|
||||
PkgInstall(String),
|
||||
PkgPackage(String),
|
||||
}
|
||||
|
||||
impl<'a> PlanKey<'a> {
|
||||
impl PlanKey {
|
||||
fn weight(&self) -> i8 {
|
||||
match self {
|
||||
PlanKey::SourceFetch(_) => 0,
|
||||
@@ -55,67 +55,72 @@ impl<'a> PlanKey<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn dependencies(
|
||||
&self,
|
||||
recipes: &'a RecipeSet,
|
||||
) -> Result<SmallVec<[PlanKey<'a>; 8]>, PlanError> {
|
||||
fn dependencies(&self, recipes: &RecipeSet) -> Result<SmallVec<[PlanKey; 8]>, PlanError> {
|
||||
match self {
|
||||
PlanKey::SourceFetch(_) => Ok(smallvec![]),
|
||||
PlanKey::SourcePatch(recipe) => Ok(smallvec![PlanKey::SourceFetch(recipe)]),
|
||||
PlanKey::SourcePrepare(recipe) => Ok(smallvec![PlanKey::SourcePatch(recipe)]),
|
||||
PlanKey::SourcePatch(recipe) => Ok(smallvec![PlanKey::SourceFetch(recipe.clone())]),
|
||||
PlanKey::SourcePrepare(recipe) => Ok(smallvec![PlanKey::SourcePatch(recipe.clone())]),
|
||||
PlanKey::ToolConfigure(recipe) => {
|
||||
let recipe = recipes
|
||||
.tool(recipe)
|
||||
.ok_or(PlanError::MissingTool(recipe.clone()))?;
|
||||
|
||||
let source_deps = recipe.sources.iter().map(|name| {
|
||||
recipes
|
||||
.source(name)
|
||||
.map(PlanKey::SourcePrepare)
|
||||
.ok_or(PlanError::MissingSource(name.clone()))
|
||||
.map(|_| PlanKey::SourcePrepare(name.to_string()))
|
||||
.ok_or(PlanError::MissingSource(name.to_string()))
|
||||
});
|
||||
|
||||
let tool_deps = recipe.tools_wanted.iter().map(|name| {
|
||||
recipes
|
||||
.tool(name)
|
||||
.map(PlanKey::ToolInstall)
|
||||
.ok_or(PlanError::MissingTool(name.clone()))
|
||||
.map(|_| PlanKey::ToolInstall(name.to_string()))
|
||||
.ok_or(PlanError::MissingTool(name.to_string()))
|
||||
});
|
||||
|
||||
let pkg_deps = recipe.pkgs_wanted.iter().map(|name| {
|
||||
recipes
|
||||
.package(name)
|
||||
.map(PlanKey::PkgPackage)
|
||||
.ok_or(PlanError::MissingPackage(name.clone()))
|
||||
.map(|_| PlanKey::PkgPackage(name.to_string()))
|
||||
.ok_or(PlanError::MissingPackage(name.to_string()))
|
||||
});
|
||||
|
||||
source_deps.chain(tool_deps).chain(pkg_deps).collect()
|
||||
}
|
||||
PlanKey::ToolBuild(recipe) => Ok(smallvec![PlanKey::ToolConfigure(recipe)]),
|
||||
PlanKey::ToolInstall(recipe) => Ok(smallvec![PlanKey::ToolBuild(recipe)]),
|
||||
PlanKey::ToolBuild(recipe) => Ok(smallvec![PlanKey::ToolConfigure(recipe.clone())]),
|
||||
PlanKey::ToolInstall(recipe) => Ok(smallvec![PlanKey::ToolBuild(recipe.clone())]),
|
||||
PlanKey::PkgConfigure(recipe) => {
|
||||
let recipe = recipes
|
||||
.package(recipe)
|
||||
.ok_or(PlanError::MissingPackage(recipe.clone()))?;
|
||||
|
||||
let source_deps = recipe.sources.iter().map(|name| {
|
||||
recipes
|
||||
.source(name)
|
||||
.map(PlanKey::SourcePrepare)
|
||||
.ok_or(PlanError::MissingSource(name.clone()))
|
||||
.map(|_| PlanKey::SourcePrepare(name.to_string()))
|
||||
.ok_or(PlanError::MissingSource(name.to_string()))
|
||||
});
|
||||
|
||||
let tool_deps = recipe.tools_wanted.iter().map(|name| {
|
||||
recipes
|
||||
.tool(name)
|
||||
.map(PlanKey::ToolInstall)
|
||||
.ok_or(PlanError::MissingTool(name.clone()))
|
||||
.map(|_| PlanKey::ToolInstall(name.to_string()))
|
||||
.ok_or(PlanError::MissingTool(name.to_string()))
|
||||
});
|
||||
|
||||
let pkg_deps = recipe.pkgs_wanted.iter().map(|name| {
|
||||
recipes
|
||||
.package(name)
|
||||
.map(PlanKey::PkgPackage)
|
||||
.ok_or(PlanError::MissingPackage(name.clone()))
|
||||
.map(|_| PlanKey::PkgPackage(name.to_string()))
|
||||
.ok_or(PlanError::MissingPackage(name.to_string()))
|
||||
});
|
||||
|
||||
source_deps.chain(tool_deps).chain(pkg_deps).collect()
|
||||
}
|
||||
PlanKey::PkgBuild(recipe) => Ok(smallvec![PlanKey::PkgConfigure(recipe)]),
|
||||
PlanKey::PkgInstall(recipe) => Ok(smallvec![PlanKey::PkgBuild(recipe)]),
|
||||
PlanKey::PkgPackage(recipe) => Ok(smallvec![PlanKey::PkgInstall(recipe)]),
|
||||
PlanKey::PkgBuild(recipe) => Ok(smallvec![PlanKey::PkgConfigure(recipe.clone())]),
|
||||
PlanKey::PkgInstall(recipe) => Ok(smallvec![PlanKey::PkgBuild(recipe.clone())]),
|
||||
PlanKey::PkgPackage(recipe) => Ok(smallvec![PlanKey::PkgInstall(recipe.clone())]),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,8 +130,8 @@ impl<'a> PlanKey<'a> {
|
||||
}
|
||||
|
||||
pub struct Plan<'a> {
|
||||
recipes: &'a RecipeSet,
|
||||
wanted: HashSet<PlanKey<'a>>,
|
||||
recipes: &'a RecipeSet<'a>,
|
||||
wanted: HashSet<PlanKey>,
|
||||
}
|
||||
|
||||
impl<'a> Plan<'a> {
|
||||
@@ -137,12 +142,12 @@ impl<'a> Plan<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_wanted(&mut self, key: PlanKey<'a>) {
|
||||
pub fn add_wanted(&mut self, key: PlanKey) {
|
||||
self.wanted.insert(key);
|
||||
}
|
||||
|
||||
pub fn steps(&self) -> Result<Vec<PlanKey<'a>>, PlanError> {
|
||||
let mut stack: Vec<_> = self.wanted.iter().copied().collect();
|
||||
pub fn steps(&self) -> Result<Vec<PlanKey>, PlanError> {
|
||||
let mut stack: Vec<_> = self.wanted.iter().cloned().collect();
|
||||
let mut graph: DiGraph<_, ()> = DiGraph::new();
|
||||
let mut nodes = HashMap::new();
|
||||
|
||||
@@ -150,18 +155,18 @@ impl<'a> Plan<'a> {
|
||||
let node_idx = match nodes.get(&node) {
|
||||
Some(&idx) => idx,
|
||||
None => {
|
||||
let idx = graph.add_node(node);
|
||||
nodes.insert(node, idx);
|
||||
let idx = graph.add_node(node.clone());
|
||||
nodes.insert(node.clone(), idx);
|
||||
idx
|
||||
}
|
||||
};
|
||||
|
||||
for dep in node.dependencies(self.recipes)?.iter().copied() {
|
||||
for dep in node.dependencies(self.recipes)? {
|
||||
let dep_idx = match nodes.get(&dep) {
|
||||
Some(&idx) => idx,
|
||||
None => {
|
||||
let idx = graph.add_node(dep);
|
||||
nodes.insert(dep, idx);
|
||||
let idx = graph.add_node(dep.clone());
|
||||
nodes.insert(dep.clone(), idx);
|
||||
stack.push(dep);
|
||||
idx
|
||||
}
|
||||
@@ -195,7 +200,7 @@ impl<'a> Plan<'a> {
|
||||
let mut result = Vec::with_capacity(graph.node_count());
|
||||
|
||||
while let Some((_, idx)) = heap.pop() {
|
||||
result.push(graph[idx]);
|
||||
result.push(graph[idx].clone());
|
||||
|
||||
for neighbor in graph.neighbors_directed(idx, Direction::Outgoing) {
|
||||
let d = in_degree.get_mut(&neighbor).unwrap();
|
||||
|
||||
Reference in New Issue
Block a user