Skip to content

Commit

Permalink
Handle ignoring host guard if entry already exists
Browse files Browse the repository at this point in the history
  • Loading branch information
jacobtread committed Dec 31, 2023
1 parent 25d0247 commit 356984d
Showing 1 changed file with 41 additions and 23 deletions.
64 changes: 41 additions & 23 deletions src/hosts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,23 @@ enum HostsError {

/// Guard structure that applies the host file entry then
/// removes the host entry once the guard is dropped
pub struct HostEntryGuard;
pub struct HostEntryGuard {
/// Whether the entry already existed
/// (We shouldn't remove the guard one drop)
existing: bool,
}

impl HostEntryGuard {
/// Attempts to apply the [`HostEntryGuard`] returning the guard
/// on success
pub fn apply() -> Option<Self> {
match Self::apply_entry() {
Ok(value) => {
debug!("Applied host modificaiton");
if value.existing {
debug!("Host modificaiton already applied");
} else {
debug!("Applied host modificaiton");
}
Some(value)
}
Err(err) => {
Expand All @@ -79,28 +87,35 @@ impl HostEntryGuard {
fn apply_entry() -> Result<Self, HostsError> {
let host_line = format!("{} {}", HOST_VALUE, HOST_KEY);

let output = Self::read_hosts_file()?
.lines()
.filter(Self::filter_not_host_line)
.chain(std::iter::once(host_line.as_str()))
// Collect the lines into a string with new lines appended
.fold(String::new(), |mut a, b| {
a.reserve(b.len() + 1);
a.push_str(b);
a.push('\n');
a
});
let host_file = Self::read_hosts_file()?;

// Find an existing entry if present
let existing = host_file.lines().any(Self::is_host_line);

if !existing {
let output = Self::read_hosts_file()?
.lines()
.chain(std::iter::once(host_line.as_str()))
// Collect the lines into a string with new lines appended
.fold(String::new(), |mut a, b| {
a.reserve(b.len() + 1);
a.push_str(b);
a.push('\n');
a
});

let path = Path::new(HOSTS_PATH);
write(path, output)?;
}

let path = Path::new(HOSTS_PATH);
write(path, output)?;
Ok(Self)
Ok(Self { existing })
}

/// Removes the gosredirector.ea.com entry from the hosts file
fn remove_entry() -> Result<(), HostsError> {
let output = Self::read_hosts_file()?
.lines()
.filter(Self::filter_not_host_line)
.filter(|line| !Self::is_host_line(line))
// Collect the lines into a string with new lines appended
.fold(String::new(), |mut a, b| {
a.reserve(b.len() + 1);
Expand All @@ -114,12 +129,10 @@ impl HostEntryGuard {
Ok(())
}

/// Filters lines based on whether they are a host redirect
/// line entry
fn filter_not_host_line(value: &&str) -> bool {
fn is_host_line(value: &str) -> bool {
let value = value.trim();
if value.is_empty() || value.starts_with('#') || !value.contains(HOST_KEY) {
return true;
return false;
}

let value = value
Expand All @@ -131,20 +144,25 @@ impl HostEntryGuard {

// Check we still have content and contain host
if value.is_empty() || !value.contains(HOST_KEY) {
return true;
return false;
}

// Splits at whitespace and ensures the first part is the host
let is_host_line = value
.split_whitespace()
.nth(1)
.is_some_and(|value| value.eq(HOST_KEY));
!is_host_line
is_host_line
}
}

impl Drop for HostEntryGuard {
fn drop(&mut self) {
// Don't remove the entry if it existed before we started
if self.existing {
return;
}

if let Err(err) = Self::remove_entry() {
error!("Failed to remove host entry: {}", err);
} else {
Expand Down

0 comments on commit 356984d

Please sign in to comment.