Rename EtcTree -> FileTree.
This commit is contained in:
parent
a642fe94dd
commit
af853c014c
5 changed files with 85 additions and 79 deletions
|
|
@ -8,7 +8,7 @@ use std::path::{Path, PathBuf};
|
||||||
use std::{fs, io, process};
|
use std::{fs, io, process};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::activate::etc_files::EtcTree;
|
use crate::activate::etc_files::FileTree;
|
||||||
use crate::{StorePath, STATE_FILE_NAME, SYSTEM_MANAGER_STATE_DIR};
|
use crate::{StorePath, STATE_FILE_NAME, SYSTEM_MANAGER_STATE_DIR};
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
|
|
@ -34,7 +34,7 @@ pub type ActivationResult<R> = Result<R, ActivationError<R>>;
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct State {
|
pub struct State {
|
||||||
etc_tree: EtcTree,
|
file_tree: FileTree,
|
||||||
services: services::Services,
|
services: services::Services,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -78,15 +78,18 @@ pub fn activate(store_path: &StorePath, ephemeral: bool) -> Result<()> {
|
||||||
|
|
||||||
log::info!("Activating etc files...");
|
log::info!("Activating etc files...");
|
||||||
|
|
||||||
match etc_files::activate(store_path, old_state.etc_tree, ephemeral) {
|
match etc_files::activate(store_path, old_state.file_tree, ephemeral) {
|
||||||
Ok(etc_tree) => {
|
Ok(etc_tree) => {
|
||||||
log::info!("Activating systemd services...");
|
log::info!("Activating systemd services...");
|
||||||
match services::activate(store_path, old_state.services, ephemeral) {
|
match services::activate(store_path, old_state.services, ephemeral) {
|
||||||
Ok(services) => State { etc_tree, services },
|
Ok(services) => State {
|
||||||
|
file_tree: etc_tree,
|
||||||
|
services,
|
||||||
|
},
|
||||||
Err(ActivationError::WithPartialResult { result, source }) => {
|
Err(ActivationError::WithPartialResult { result, source }) => {
|
||||||
log::error!("Error during activation: {source:?}");
|
log::error!("Error during activation: {source:?}");
|
||||||
State {
|
State {
|
||||||
etc_tree,
|
file_tree: etc_tree,
|
||||||
services: result,
|
services: result,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -95,7 +98,7 @@ pub fn activate(store_path: &StorePath, ephemeral: bool) -> Result<()> {
|
||||||
Err(ActivationError::WithPartialResult { result, source }) => {
|
Err(ActivationError::WithPartialResult { result, source }) => {
|
||||||
log::error!("Error during activation: {source:?}");
|
log::error!("Error during activation: {source:?}");
|
||||||
State {
|
State {
|
||||||
etc_tree: result,
|
file_tree: result,
|
||||||
..old_state
|
..old_state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -111,15 +114,18 @@ pub fn deactivate() -> Result<()> {
|
||||||
let old_state = State::from_file(state_file)?;
|
let old_state = State::from_file(state_file)?;
|
||||||
log::debug!("{old_state:?}");
|
log::debug!("{old_state:?}");
|
||||||
|
|
||||||
match etc_files::deactivate(old_state.etc_tree) {
|
match etc_files::deactivate(old_state.file_tree) {
|
||||||
Ok(etc_tree) => {
|
Ok(etc_tree) => {
|
||||||
log::info!("Deactivating systemd services...");
|
log::info!("Deactivating systemd services...");
|
||||||
match services::deactivate(old_state.services) {
|
match services::deactivate(old_state.services) {
|
||||||
Ok(services) => State { etc_tree, services },
|
Ok(services) => State {
|
||||||
|
file_tree: etc_tree,
|
||||||
|
services,
|
||||||
|
},
|
||||||
Err(ActivationError::WithPartialResult { result, source }) => {
|
Err(ActivationError::WithPartialResult { result, source }) => {
|
||||||
log::error!("Error during deactivation: {source:?}");
|
log::error!("Error during deactivation: {source:?}");
|
||||||
State {
|
State {
|
||||||
etc_tree,
|
file_tree: etc_tree,
|
||||||
services: result,
|
services: result,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -128,7 +134,7 @@ pub fn deactivate() -> Result<()> {
|
||||||
Err(ActivationError::WithPartialResult { result, source }) => {
|
Err(ActivationError::WithPartialResult { result, source }) => {
|
||||||
log::error!("Error during deactivation: {source:?}");
|
log::error!("Error during deactivation: {source:?}");
|
||||||
State {
|
State {
|
||||||
etc_tree: result,
|
file_tree: result,
|
||||||
..old_state
|
..old_state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ use std::path;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::{fs, io};
|
use std::{fs, io};
|
||||||
|
|
||||||
use self::etc_tree::EtcFileStatus;
|
use self::etc_tree::FileStatus;
|
||||||
use super::ActivationResult;
|
use super::ActivationResult;
|
||||||
use crate::activate::ActivationError;
|
use crate::activate::ActivationError;
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
@ -17,9 +17,9 @@ use crate::{
|
||||||
SYSTEM_MANAGER_STATIC_NAME,
|
SYSTEM_MANAGER_STATIC_NAME,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use etc_tree::EtcTree;
|
pub use etc_tree::FileTree;
|
||||||
|
|
||||||
type EtcActivationResult = ActivationResult<EtcTree>;
|
type EtcActivationResult = ActivationResult<FileTree>;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
|
@ -81,7 +81,7 @@ fn read_config(store_path: &StorePath) -> anyhow::Result<EtcFilesConfig> {
|
||||||
|
|
||||||
pub fn activate(
|
pub fn activate(
|
||||||
store_path: &StorePath,
|
store_path: &StorePath,
|
||||||
old_state: EtcTree,
|
old_state: FileTree,
|
||||||
ephemeral: bool,
|
ephemeral: bool,
|
||||||
) -> EtcActivationResult {
|
) -> EtcActivationResult {
|
||||||
let config = read_config(store_path)
|
let config = read_config(store_path)
|
||||||
|
|
@ -90,7 +90,7 @@ pub fn activate(
|
||||||
let etc_dir = etc_dir(ephemeral);
|
let etc_dir = etc_dir(ephemeral);
|
||||||
log::info!("Creating /etc entries in {}", etc_dir.display());
|
log::info!("Creating /etc entries in {}", etc_dir.display());
|
||||||
|
|
||||||
let initial_state = EtcTree::root_node();
|
let initial_state = FileTree::root_node();
|
||||||
|
|
||||||
let state = create_etc_static_link(
|
let state = create_etc_static_link(
|
||||||
SYSTEM_MANAGER_STATIC_NAME,
|
SYSTEM_MANAGER_STATIC_NAME,
|
||||||
|
|
@ -108,15 +108,15 @@ pub fn activate(
|
||||||
Ok(final_state)
|
Ok(final_state)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deactivate(old_state: EtcTree) -> EtcActivationResult {
|
pub fn deactivate(old_state: FileTree) -> EtcActivationResult {
|
||||||
let final_state = old_state.deactivate(&try_delete_path).unwrap_or_default();
|
let final_state = old_state.deactivate(&try_delete_path).unwrap_or_default();
|
||||||
|
|
||||||
log::info!("Done");
|
log::info!("Done");
|
||||||
Ok(final_state)
|
Ok(final_state)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_delete_path(path: &Path, status: &EtcFileStatus) -> bool {
|
fn try_delete_path(path: &Path, status: &FileStatus) -> bool {
|
||||||
fn do_try_delete(path: &Path, status: &EtcFileStatus) -> anyhow::Result<()> {
|
fn do_try_delete(path: &Path, status: &FileStatus) -> anyhow::Result<()> {
|
||||||
// exists() returns false for broken symlinks
|
// exists() returns false for broken symlinks
|
||||||
if path.exists() || path.is_symlink() {
|
if path.exists() || path.is_symlink() {
|
||||||
if path.is_symlink() {
|
if path.is_symlink() {
|
||||||
|
|
@ -127,7 +127,7 @@ fn try_delete_path(path: &Path, status: &EtcFileStatus) -> bool {
|
||||||
if path.read_dir()?.next().is_none() {
|
if path.read_dir()?.next().is_none() {
|
||||||
remove_dir(path)
|
remove_dir(path)
|
||||||
} else {
|
} else {
|
||||||
if let EtcFileStatus::Managed = status {
|
if let FileStatus::Managed = status {
|
||||||
log::warn!("Managed directory not empty, ignoring: {}", path.display());
|
log::warn!("Managed directory not empty, ignoring: {}", path.display());
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -153,9 +153,9 @@ fn try_delete_path(path: &Path, status: &EtcFileStatus) -> bool {
|
||||||
fn create_etc_links<'a, E>(
|
fn create_etc_links<'a, E>(
|
||||||
entries: E,
|
entries: E,
|
||||||
etc_dir: &Path,
|
etc_dir: &Path,
|
||||||
state: EtcTree,
|
state: FileTree,
|
||||||
old_state: &EtcTree,
|
old_state: &FileTree,
|
||||||
) -> EtcTree
|
) -> FileTree
|
||||||
where
|
where
|
||||||
E: Iterator<Item = &'a EtcFile>,
|
E: Iterator<Item = &'a EtcFile>,
|
||||||
{
|
{
|
||||||
|
|
@ -178,7 +178,7 @@ fn create_etc_static_link(
|
||||||
static_dir_name: &str,
|
static_dir_name: &str,
|
||||||
store_path: &StorePath,
|
store_path: &StorePath,
|
||||||
etc_dir: &Path,
|
etc_dir: &Path,
|
||||||
state: EtcTree,
|
state: FileTree,
|
||||||
) -> EtcActivationResult {
|
) -> EtcActivationResult {
|
||||||
let static_path = etc_dir.join(static_dir_name);
|
let static_path = etc_dir.join(static_dir_name);
|
||||||
let new_state = create_dir_recursively(static_path.parent().unwrap(), state);
|
let new_state = create_dir_recursively(static_path.parent().unwrap(), state);
|
||||||
|
|
@ -193,8 +193,8 @@ fn create_etc_static_link(
|
||||||
fn create_etc_link<P>(
|
fn create_etc_link<P>(
|
||||||
link_target: &P,
|
link_target: &P,
|
||||||
etc_dir: &Path,
|
etc_dir: &Path,
|
||||||
state: EtcTree,
|
state: FileTree,
|
||||||
old_state: &EtcTree,
|
old_state: &FileTree,
|
||||||
) -> EtcActivationResult
|
) -> EtcActivationResult
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
|
|
@ -203,13 +203,13 @@ where
|
||||||
link_target: &Path,
|
link_target: &Path,
|
||||||
absolute_target: &Path,
|
absolute_target: &Path,
|
||||||
etc_dir: &Path,
|
etc_dir: &Path,
|
||||||
state: EtcTree,
|
state: FileTree,
|
||||||
old_state: &EtcTree,
|
old_state: &FileTree,
|
||||||
upwards_path: &Path,
|
upwards_path: &Path,
|
||||||
) -> EtcActivationResult {
|
) -> EtcActivationResult {
|
||||||
let link_path = etc_dir.join(link_target);
|
let link_path = etc_dir.join(link_target);
|
||||||
if link_path.is_dir() && absolute_target.is_dir() {
|
if link_path.is_dir() && absolute_target.is_dir() {
|
||||||
log::info!("Entering into directory...");
|
log::debug!("Entering into directory {}...", link_path.display());
|
||||||
Ok(absolute_target
|
Ok(absolute_target
|
||||||
.read_dir()
|
.read_dir()
|
||||||
.expect("Error reading the directory.")
|
.expect("Error reading the directory.")
|
||||||
|
|
@ -250,8 +250,8 @@ where
|
||||||
fn go(
|
fn go(
|
||||||
link_target: &Path,
|
link_target: &Path,
|
||||||
etc_dir: &Path,
|
etc_dir: &Path,
|
||||||
state: EtcTree,
|
state: FileTree,
|
||||||
old_state: &EtcTree,
|
old_state: &FileTree,
|
||||||
upwards_path: &Path,
|
upwards_path: &Path,
|
||||||
) -> EtcActivationResult {
|
) -> EtcActivationResult {
|
||||||
let link_path = etc_dir.join(link_target);
|
let link_path = etc_dir.join(link_target);
|
||||||
|
|
@ -272,6 +272,7 @@ where
|
||||||
} else if link_path.is_symlink()
|
} else if link_path.is_symlink()
|
||||||
&& link_path.read_link().expect("Error reading link.") == target
|
&& link_path.read_link().expect("Error reading link.") == target
|
||||||
{
|
{
|
||||||
|
log::debug!("Link {} up to date.", link_path.display());
|
||||||
Ok(dir_state.register_managed_entry(&link_path))
|
Ok(dir_state.register_managed_entry(&link_path))
|
||||||
} else {
|
} else {
|
||||||
let result = if link_path.exists() {
|
let result = if link_path.exists() {
|
||||||
|
|
@ -304,8 +305,8 @@ where
|
||||||
fn create_etc_entry(
|
fn create_etc_entry(
|
||||||
entry: &EtcFile,
|
entry: &EtcFile,
|
||||||
etc_dir: &Path,
|
etc_dir: &Path,
|
||||||
state: EtcTree,
|
state: FileTree,
|
||||||
old_state: &EtcTree,
|
old_state: &FileTree,
|
||||||
) -> EtcActivationResult {
|
) -> EtcActivationResult {
|
||||||
if entry.mode == "symlink" {
|
if entry.mode == "symlink" {
|
||||||
if let Some(path::Component::Normal(link_target)) = entry.target.components().next() {
|
if let Some(path::Component::Normal(link_target)) = entry.target.components().next() {
|
||||||
|
|
@ -331,7 +332,7 @@ fn create_etc_entry(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_dir_recursively(dir: &Path, state: EtcTree) -> EtcActivationResult {
|
fn create_dir_recursively(dir: &Path, state: FileTree) -> EtcActivationResult {
|
||||||
use itertools::FoldWhile::{Continue, Done};
|
use itertools::FoldWhile::{Continue, Done};
|
||||||
use path::Component;
|
use path::Component;
|
||||||
|
|
||||||
|
|
@ -382,7 +383,7 @@ fn create_dir_recursively(dir: &Path, state: EtcTree) -> EtcActivationResult {
|
||||||
new_state
|
new_state
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copy_file(source: &Path, target: &Path, mode: &str, old_state: &EtcTree) -> anyhow::Result<()> {
|
fn copy_file(source: &Path, target: &Path, mode: &str, old_state: &FileTree) -> anyhow::Result<()> {
|
||||||
let exists = target.try_exists()?;
|
let exists = target.try_exists()?;
|
||||||
if !exists || old_state.is_managed(target) {
|
if !exists || old_state.is_managed(target) {
|
||||||
log::debug!(
|
log::debug!(
|
||||||
|
|
|
||||||
|
|
@ -7,14 +7,14 @@ use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub enum EtcFileStatus {
|
pub enum FileStatus {
|
||||||
Managed,
|
Managed,
|
||||||
Unmanaged,
|
Unmanaged,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EtcFileStatus {
|
impl FileStatus {
|
||||||
fn merge(&self, other: &Self) -> Self {
|
fn merge(&self, other: &Self) -> Self {
|
||||||
use EtcFileStatus::*;
|
use FileStatus::*;
|
||||||
|
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Unmanaged, Unmanaged) => Unmanaged,
|
(Unmanaged, Unmanaged) => Unmanaged,
|
||||||
|
|
@ -25,22 +25,22 @@ impl EtcFileStatus {
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct EtcTree {
|
pub struct FileTree {
|
||||||
status: EtcFileStatus,
|
status: FileStatus,
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
// TODO directories and files are now both represented as a string associated with a nested
|
// TODO directories and files are now both represented as a string associated with a nested
|
||||||
// map. For files the nested map is simple empty.
|
// map. For files the nested map is simple empty.
|
||||||
// We could potentially optimise this.
|
// We could potentially optimise this.
|
||||||
nested: HashMap<String, EtcTree>,
|
nested: HashMap<String, FileTree>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsRef<EtcTree> for EtcTree {
|
impl AsRef<FileTree> for FileTree {
|
||||||
fn as_ref(&self) -> &EtcTree {
|
fn as_ref(&self) -> &FileTree {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for EtcTree {
|
impl Default for FileTree {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::root_node()
|
Self::root_node()
|
||||||
}
|
}
|
||||||
|
|
@ -56,12 +56,12 @@ impl Default for EtcTree {
|
||||||
/// 3. Import from a file
|
/// 3. Import from a file
|
||||||
/// 4. Add a path to the tree, that will from then on be considered as managed
|
/// 4. Add a path to the tree, that will from then on be considered as managed
|
||||||
/// 5.
|
/// 5.
|
||||||
impl EtcTree {
|
impl FileTree {
|
||||||
fn new(path: PathBuf) -> Self {
|
fn new(path: PathBuf) -> Self {
|
||||||
Self::with_status(path, EtcFileStatus::Unmanaged)
|
Self::with_status(path, FileStatus::Unmanaged)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_status(path: PathBuf, status: EtcFileStatus) -> Self {
|
fn with_status(path: PathBuf, status: FileStatus) -> Self {
|
||||||
Self {
|
Self {
|
||||||
status,
|
status,
|
||||||
path,
|
path,
|
||||||
|
|
@ -73,8 +73,8 @@ impl EtcTree {
|
||||||
Self::new(PathBuf::from(path::MAIN_SEPARATOR_STR))
|
Self::new(PathBuf::from(path::MAIN_SEPARATOR_STR))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_status<'a>(&'a self, path: &Path) -> &'a EtcFileStatus {
|
pub fn get_status<'a>(&'a self, path: &Path) -> &'a FileStatus {
|
||||||
fn go<'a, 'b, C>(tree: &'a EtcTree, mut components: C, path: &Path) -> &'a EtcFileStatus
|
fn go<'a, 'b, C>(tree: &'a FileTree, mut components: C, path: &Path) -> &'a FileStatus
|
||||||
where
|
where
|
||||||
C: Iterator<Item = path::Component<'b>>,
|
C: Iterator<Item = path::Component<'b>>,
|
||||||
{
|
{
|
||||||
|
|
@ -84,7 +84,7 @@ impl EtcTree {
|
||||||
.nested
|
.nested
|
||||||
.get(name.to_string_lossy().as_ref())
|
.get(name.to_string_lossy().as_ref())
|
||||||
.map(|subtree| go(subtree, components, path))
|
.map(|subtree| go(subtree, components, path))
|
||||||
.unwrap_or(&EtcFileStatus::Unmanaged),
|
.unwrap_or(&FileStatus::Unmanaged),
|
||||||
path::Component::RootDir => go(tree, components, path),
|
path::Component::RootDir => go(tree, components, path),
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
|
|
@ -97,13 +97,13 @@ impl EtcTree {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_managed(&self, path: &Path) -> bool {
|
pub fn is_managed(&self, path: &Path) -> bool {
|
||||||
*self.get_status(path) == EtcFileStatus::Managed
|
*self.get_status(path) == FileStatus::Managed
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO is recursion OK here?
|
// TODO is recursion OK here?
|
||||||
// Should we convert to CPS and use a crate like tramp to TCO this?
|
// Should we convert to CPS and use a crate like tramp to TCO this?
|
||||||
pub fn register_managed_entry(self, path: &Path) -> Self {
|
pub fn register_managed_entry(self, path: &Path) -> Self {
|
||||||
fn go<'a, C>(mut tree: EtcTree, mut components: Peekable<C>, path: PathBuf) -> EtcTree
|
fn go<'a, C>(mut tree: FileTree, mut components: Peekable<C>, path: PathBuf) -> FileTree
|
||||||
where
|
where
|
||||||
C: Iterator<Item = path::Component<'a>>,
|
C: Iterator<Item = path::Component<'a>>,
|
||||||
{
|
{
|
||||||
|
|
@ -115,15 +115,13 @@ impl EtcTree {
|
||||||
|maybe_subtree| {
|
|maybe_subtree| {
|
||||||
Some(go(
|
Some(go(
|
||||||
maybe_subtree.unwrap_or_else(|| {
|
maybe_subtree.unwrap_or_else(|| {
|
||||||
EtcTree::with_status(
|
FileTree::with_status(
|
||||||
new_path.to_owned(),
|
new_path.to_owned(),
|
||||||
// We only label as managed the final path entry,
|
// We only label as managed the final path entry,
|
||||||
// to label intermediate nodes as managed, we should
|
// to label intermediate nodes as managed, we should
|
||||||
// call this function for every one of them separately.
|
// call this function for every one of them separately.
|
||||||
components
|
components.peek().map_or(FileStatus::Managed, |_| {
|
||||||
.peek()
|
FileStatus::Unmanaged
|
||||||
.map_or(EtcFileStatus::Managed, |_| {
|
|
||||||
EtcFileStatus::Unmanaged
|
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
|
|
@ -151,9 +149,9 @@ impl EtcTree {
|
||||||
go(self, path.components().peekable(), PathBuf::new())
|
go(self, path.components().peekable(), PathBuf::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deactivate<F>(self, delete_action: &F) -> Option<EtcTree>
|
pub fn deactivate<F>(self, delete_action: &F) -> Option<FileTree>
|
||||||
where
|
where
|
||||||
F: Fn(&Path, &EtcFileStatus) -> bool,
|
F: Fn(&Path, &FileStatus) -> bool,
|
||||||
{
|
{
|
||||||
let new_tree = self.nested.keys().fold(self.clone(), |mut new_tree, name| {
|
let new_tree = self.nested.keys().fold(self.clone(), |mut new_tree, name| {
|
||||||
new_tree.nested = new_tree.nested.alter(
|
new_tree.nested = new_tree.nested.alter(
|
||||||
|
|
@ -168,7 +166,7 @@ impl EtcTree {
|
||||||
// are not responsible for cleaning them up (we don't run the delete_action
|
// are not responsible for cleaning them up (we don't run the delete_action
|
||||||
// closure on their paths).
|
// closure on their paths).
|
||||||
if new_tree.nested.is_empty() {
|
if new_tree.nested.is_empty() {
|
||||||
if let EtcFileStatus::Managed = new_tree.status {
|
if let FileStatus::Managed = new_tree.status {
|
||||||
if delete_action(&new_tree.path, &new_tree.status) {
|
if delete_action(&new_tree.path, &new_tree.status) {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -184,7 +182,7 @@ impl EtcTree {
|
||||||
|
|
||||||
pub fn update_state<F>(self, other: Self, delete_action: &F) -> Option<Self>
|
pub fn update_state<F>(self, other: Self, delete_action: &F) -> Option<Self>
|
||||||
where
|
where
|
||||||
F: Fn(&Path, &EtcFileStatus) -> bool,
|
F: Fn(&Path, &FileStatus) -> bool,
|
||||||
{
|
{
|
||||||
let to_deactivate = other
|
let to_deactivate = other
|
||||||
.nested
|
.nested
|
||||||
|
|
@ -225,7 +223,7 @@ impl EtcTree {
|
||||||
|
|
||||||
// If our invariants are properly maintained, then we should never end up
|
// If our invariants are properly maintained, then we should never end up
|
||||||
// here with dangling unmanaged nodes.
|
// here with dangling unmanaged nodes.
|
||||||
debug_assert!(!merged.nested.is_empty() || merged.status == EtcFileStatus::Managed);
|
debug_assert!(!merged.nested.is_empty() || merged.status == FileStatus::Managed);
|
||||||
|
|
||||||
Some(merged)
|
Some(merged)
|
||||||
}
|
}
|
||||||
|
|
@ -236,20 +234,20 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
impl EtcTree {
|
impl FileTree {
|
||||||
pub fn deactivate_managed_entry<F>(self, path: &Path, delete_action: &F) -> Self
|
pub fn deactivate_managed_entry<F>(self, path: &Path, delete_action: &F) -> Self
|
||||||
where
|
where
|
||||||
F: Fn(&Path, &EtcFileStatus) -> bool,
|
F: Fn(&Path, &FileStatus) -> bool,
|
||||||
{
|
{
|
||||||
fn go<'a, C, F>(
|
fn go<'a, C, F>(
|
||||||
mut tree: EtcTree,
|
mut tree: FileTree,
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
mut components: Peekable<C>,
|
mut components: Peekable<C>,
|
||||||
delete_action: &F,
|
delete_action: &F,
|
||||||
) -> EtcTree
|
) -> FileTree
|
||||||
where
|
where
|
||||||
C: Iterator<Item = path::Component<'a>>,
|
C: Iterator<Item = path::Component<'a>>,
|
||||||
F: Fn(&Path, &EtcFileStatus) -> bool,
|
F: Fn(&Path, &FileStatus) -> bool,
|
||||||
{
|
{
|
||||||
log::debug!("Deactivating {}", path.display());
|
log::debug!("Deactivating {}", path.display());
|
||||||
|
|
||||||
|
|
@ -296,8 +294,8 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn etc_tree_get_status() {
|
fn get_status() {
|
||||||
let tree1 = EtcTree::root_node()
|
let tree1 = FileTree::root_node()
|
||||||
.register_managed_entry(&PathBuf::from("/").join("foo").join("bar"))
|
.register_managed_entry(&PathBuf::from("/").join("foo").join("bar"))
|
||||||
.register_managed_entry(&PathBuf::from("/").join("foo2"))
|
.register_managed_entry(&PathBuf::from("/").join("foo2"))
|
||||||
.register_managed_entry(&PathBuf::from("/").join("foo2").join("baz"))
|
.register_managed_entry(&PathBuf::from("/").join("foo2").join("baz"))
|
||||||
|
|
@ -319,8 +317,8 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn etc_tree_register() {
|
fn register() {
|
||||||
let tree = EtcTree::root_node()
|
let tree = FileTree::root_node()
|
||||||
.register_managed_entry(&PathBuf::from("/").join("foo").join("bar"))
|
.register_managed_entry(&PathBuf::from("/").join("foo").join("bar"))
|
||||||
.register_managed_entry(&PathBuf::from("/").join("foo2").join("baz").join("bar"))
|
.register_managed_entry(&PathBuf::from("/").join("foo2").join("baz").join("bar"))
|
||||||
.register_managed_entry(&PathBuf::from("/").join("foo2").join("baz2").join("bar"));
|
.register_managed_entry(&PathBuf::from("/").join("foo2").join("baz2").join("bar"));
|
||||||
|
|
@ -345,8 +343,8 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn etc_tree_deactivate() {
|
fn deactivate() {
|
||||||
let tree1 = EtcTree::root_node()
|
let tree1 = FileTree::root_node()
|
||||||
.register_managed_entry(&PathBuf::from("/").join("foo").join("bar"))
|
.register_managed_entry(&PathBuf::from("/").join("foo").join("bar"))
|
||||||
.register_managed_entry(&PathBuf::from("/").join("foo2"))
|
.register_managed_entry(&PathBuf::from("/").join("foo2"))
|
||||||
.register_managed_entry(&PathBuf::from("/").join("foo2").join("baz"))
|
.register_managed_entry(&PathBuf::from("/").join("foo2").join("baz"))
|
||||||
|
|
@ -406,8 +404,8 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn etc_tree_update_state() {
|
fn update_state() {
|
||||||
let tree1 = EtcTree::root_node()
|
let tree1 = FileTree::root_node()
|
||||||
.register_managed_entry(&PathBuf::from("/").join("foo").join("bar"))
|
.register_managed_entry(&PathBuf::from("/").join("foo").join("bar"))
|
||||||
.register_managed_entry(&PathBuf::from("/").join("foo2"))
|
.register_managed_entry(&PathBuf::from("/").join("foo2"))
|
||||||
.register_managed_entry(&PathBuf::from("/").join("foo2").join("baz"))
|
.register_managed_entry(&PathBuf::from("/").join("foo2").join("baz"))
|
||||||
|
|
@ -415,7 +413,7 @@ mod tests {
|
||||||
.register_managed_entry(&PathBuf::from("/").join("foo2").join("baz2"))
|
.register_managed_entry(&PathBuf::from("/").join("foo2").join("baz2"))
|
||||||
.register_managed_entry(&PathBuf::from("/").join("foo2").join("baz2").join("bar"))
|
.register_managed_entry(&PathBuf::from("/").join("foo2").join("baz2").join("bar"))
|
||||||
.register_managed_entry(&PathBuf::from("/").join("foo3").join("baz2").join("bar"));
|
.register_managed_entry(&PathBuf::from("/").join("foo3").join("baz2").join("bar"));
|
||||||
let tree2 = EtcTree::root_node()
|
let tree2 = FileTree::root_node()
|
||||||
.register_managed_entry(&PathBuf::from("/").join("foo").join("bar"))
|
.register_managed_entry(&PathBuf::from("/").join("foo").join("bar"))
|
||||||
.register_managed_entry(&PathBuf::from("/").join("foo3").join("bar"))
|
.register_managed_entry(&PathBuf::from("/").join("foo3").join("bar"))
|
||||||
.register_managed_entry(&PathBuf::from("/").join("foo4"))
|
.register_managed_entry(&PathBuf::from("/").join("foo4"))
|
||||||
|
|
|
||||||
|
|
@ -295,7 +295,7 @@ where
|
||||||
.iter()
|
.iter()
|
||||||
.fold(HashSet::new(), |mut set, unit| match action(unit) {
|
.fold(HashSet::new(), |mut set, unit| match action(unit) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
log::info!("Unit {}: {}...", unit, log_action);
|
log::debug!("Unit {}: {}...", unit, log_action);
|
||||||
set.insert(JobId {
|
set.insert(JobId {
|
||||||
id: (*unit).to_owned(),
|
id: (*unit).to_owned(),
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,8 @@ impl ServiceManager {
|
||||||
let total_jobs = waiting_for.len();
|
let total_jobs = waiting_for.len();
|
||||||
|
|
||||||
if total_jobs > 0 {
|
if total_jobs > 0 {
|
||||||
log::info!("Waiting for jobs to finish... (0/{})", total_jobs);
|
log::info!("Waiting for jobs to finish...");
|
||||||
|
log::debug!("Waiting for jobs to finish... (0/{})", total_jobs);
|
||||||
}
|
}
|
||||||
|
|
||||||
while !waiting_for.is_empty() {
|
while !waiting_for.is_empty() {
|
||||||
|
|
@ -218,7 +219,7 @@ impl ServiceManager {
|
||||||
waiting_for = waiting_for.relative_complement(job_names.clone());
|
waiting_for = waiting_for.relative_complement(job_names.clone());
|
||||||
*job_names = im::HashSet::new();
|
*job_names = im::HashSet::new();
|
||||||
if !waiting_for.is_empty() {
|
if !waiting_for.is_empty() {
|
||||||
log::info!(
|
log::debug!(
|
||||||
"Waiting for jobs to finish... ({}/{})",
|
"Waiting for jobs to finish... ({}/{})",
|
||||||
total_jobs - waiting_for.len(),
|
total_jobs - waiting_for.len(),
|
||||||
total_jobs
|
total_jobs
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue