x_core/
lib.rs

1// Copyright (c) The Diem Core Contributors
2// SPDX-License-Identifier: Apache-2.0
3
4#[macro_use]
5extern crate rental;
6
7use guppy::graph::PackageGraph;
8use once_cell::sync::OnceCell;
9use std::path::{Path, PathBuf};
10
11pub mod core_config;
12mod debug_ignore;
13mod errors;
14mod git;
15mod graph;
16mod workspace_subset;
17
18use crate::{core_config::XCoreConfig, git::GitCli};
19pub use debug_ignore::*;
20pub use errors::*;
21use graph::PackageGraphPlus;
22use hakari::{HakariBuilder, TomlOptions};
23pub use workspace_subset::*;
24
25/// Core context shared across all of x.
26#[derive(Debug)]
27pub struct XCoreContext {
28    project_root: &'static Path,
29    config: XCoreConfig,
30    current_dir: PathBuf,
31    current_rel_dir: PathBuf,
32    git_cli: GitCli,
33    package_graph_plus: DebugIgnore<OnceCell<PackageGraphPlus>>,
34}
35
36impl XCoreContext {
37    /// Creates a new XCoreContext.
38    pub fn new(
39        project_root: &'static Path,
40        current_dir: PathBuf,
41        config: XCoreConfig,
42    ) -> Result<Self> {
43        let current_rel_dir = match current_dir.strip_prefix(project_root) {
44            Ok(rel_dir) => rel_dir.to_path_buf(),
45            Err(_) => {
46                return Err(SystemError::CwdNotInProjectRoot {
47                    current_dir,
48                    project_root,
49                })
50            }
51        };
52        // TODO: The project root should be managed by this struct, not by the global project_root
53        // function.
54        Ok(Self {
55            project_root,
56            config,
57            current_dir,
58            current_rel_dir,
59            git_cli: GitCli::new(project_root)?,
60            package_graph_plus: DebugIgnore(OnceCell::new()),
61        })
62    }
63
64    /// Returns the project root for this workspace.
65    pub fn project_root(&self) -> &'static Path {
66        self.project_root
67    }
68
69    /// Returns the core config.
70    pub fn config(&self) -> &XCoreConfig {
71        &self.config
72    }
73
74    /// Returns the current working directory for this process.
75    pub fn current_dir(&self) -> &Path {
76        &self.current_dir
77    }
78
79    /// Returns the current working directory for this process, relative to the project root.
80    pub fn current_rel_dir(&self) -> &Path {
81        &self.current_rel_dir
82    }
83
84    /// Returns true if x has been run from the project root.
85    pub fn current_dir_is_root(&self) -> bool {
86        self.current_rel_dir == Path::new("")
87    }
88
89    /// Returns the Git CLI for this workspace.
90    pub fn git_cli(&self) -> &GitCli {
91        &self.git_cli
92    }
93
94    /// Returns the package graph for this workspace.
95    pub fn package_graph(&self) -> Result<&PackageGraph> {
96        Ok(self.package_graph_plus()?.head())
97    }
98
99    /// Returns information about the subsets for this workspace.
100    pub fn subsets(&self) -> Result<&WorkspaceSubsets> {
101        Ok(self.package_graph_plus()?.suffix())
102    }
103
104    /// Returns a Hakari builder for this workspace.
105    pub fn hakari_builder<'a>(&'a self) -> Result<HakariBuilder<'a, 'static>> {
106        let graph = self.package_graph()?;
107        self.config
108            .hakari
109            .to_hakari_builder(graph)
110            .map_err(|err| SystemError::guppy("while resolving Hakari config", err))
111    }
112
113    /// Returns the default Hakari TOML options for this workspace.
114    pub fn hakari_toml_options(&self) -> TomlOptions {
115        let mut options = TomlOptions::new();
116        options.set_exact_versions(true);
117        options
118    }
119
120    // ---
121    // Helper methods
122    // ---
123
124    fn package_graph_plus(&self) -> Result<&PackageGraphPlus> {
125        self.package_graph_plus
126            .get_or_try_init(|| PackageGraphPlus::create(self))
127    }
128}