Skip to content

Commit

Permalink
Merge pull request #184 from fabricedesre/profile_service
Browse files Browse the repository at this point in the history
Basic profile service. r=ferjm
  • Loading branch information
ferjm committed Mar 11, 2016
2 parents da92056 + 434aec7 commit cfa0d0b
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 4 deletions.
4 changes: 2 additions & 2 deletions src/config_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ describe! config {

describe! config_service {
before_each {
let mut config = ConfigService::new(&config_file_name);
let config = ConfigService::new(&config_file_name);
}

it "should remember properties" {
Expand Down Expand Up @@ -261,7 +261,7 @@ describe! config {
it "ConfigService should remember things over restarts" {
// Block to make `config` go out of scope
{
let mut config = ConfigService::new(&config_file_name);
let config = ConfigService::new(&config_file_name);
config.set("foo", "bar", "baz");
}
// `config` should now be out of scope and dropped
Expand Down
13 changes: 11 additions & 2 deletions src/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use http_server::HttpServer;
use iron::{Request, Response, IronResult};
use iron::headers::{ ContentType, AccessControlAllowOrigin };
use iron::status::Status;
use profile_service::ProfileService;
use self::collections::vec::IntoIter;
use service::{ Service, ServiceAdapter, ServiceProperties };
use std::collections::hash_map::HashMap;
Expand All @@ -35,6 +36,7 @@ pub struct FoxBox {
websockets: Arc<Mutex<HashMap<ws::util::Token, ws::Sender>>>,
pub config: Arc<ConfigService>,
upnp: Arc<UpnpManager>,
profile_service: Arc<ProfileService>
}

const DEFAULT_HOSTNAME: &'static str = "::"; // ipv6 default.
Expand All @@ -59,6 +61,7 @@ pub trait Controller : Send + Sync + Clone + Reflect + 'static {

fn get_config(&self) -> &ConfigService;
fn get_upnp_manager(&self) -> Arc<UpnpManager>;
fn get_profile(&self) -> &ProfileService;
}

impl FoxBox {
Expand All @@ -68,6 +71,7 @@ impl FoxBox {
http_port: u16,
ws_port: u16) -> Self {

let profile_service = ProfileService::new(None);
FoxBox {
services: Arc::new(Mutex::new(HashMap::new())),
websockets: Arc::new(Mutex::new(HashMap::new())),
Expand All @@ -77,8 +81,9 @@ impl FoxBox {
}),
http_port: http_port,
ws_port: ws_port,
config: Arc::new(ConfigService::new("foxbox.conf")),
upnp: Arc::new(UpnpManager::new())
config: Arc::new(ConfigService::new(&profile_service.path_for("foxbox.conf"))),
upnp: Arc::new(UpnpManager::new()),
profile_service: Arc::new(profile_service)
}
}
}
Expand Down Expand Up @@ -203,6 +208,10 @@ impl Controller for FoxBox {
&self.config
}

fn get_profile(&self) -> &ProfileService {
&self.profile_service
}

fn get_upnp_manager(&self) -> Arc<UpnpManager> {
self.upnp.clone()
}
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ mod config_store;
mod controller;
mod http_server;
mod managed_process;
mod profile_service;
mod registration;
mod service;
mod upnp;
Expand Down
93 changes: 93 additions & 0 deletions src/profile_service.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/// Simple service that helps with managing files in a configurable
/// directory.

use std::env;
use std::fs;

pub struct ProfileService {
profile_dir: String
}

fn get_env_var(name: &str) -> Option<String> {
if let Some(value) = env::var_os(name) {
return match value.into_string() {
Ok(s) => Some(s),
Err(_) => None
};
}
None
}

impl ProfileService {
pub fn new(profile_dir: Option<String>) -> Self {
// If no explicit profile directory is set, follow the Freedesktop
// standard: If $XDG_DATA_HOME is either not set or empty, a default
// equal to $HOME/.local/share is used.
let dir = match profile_dir {
Some(path) => path,
None => {
if let Some(xdg) = get_env_var("XDG_DATA_HOME") {
format!("{}/foxbox", xdg)
} else {
if let Some(home) = get_env_var("HOME") {
format!("{}/.local/share/foxbox", home)
} else {
panic!("Unable to get $HOME value");
}
}
}
};

// Create the directory if needed. Panic if we can't or if there is an
// existing file with the same path.
match fs::metadata(dir.clone()) {
Ok(meta) => {
if !meta.is_dir() {
panic!("The path {} is a file, and can't be used as a profile.",
dir);
}
},
Err(_) => {
fs::create_dir_all(dir.clone()).unwrap_or_else(|err| {
panic!("Unable to create directory {} : {}", dir, err);
});
}
}

ProfileService {
profile_dir: dir
}
}

// Returns an absolute path for a file.
// This doesn't try to create the file.
pub fn path_for(&self, relative_path: &str) -> String {
format!("{}/{}", self.profile_dir, relative_path)
}
}

#[test]
#[should_panic]
fn test_bogus_path() {
let _ = ProfileService::new(Some("/cant_create/that/path".to_owned()));
}

#[test]
fn test_default_profile() {
use std::fs::File;
use std::io::Write;

let profile = ProfileService::new(None);
let path = profile.path_for("test.conf");
// We can't assert anything on the path value since it's environment
// dependant, but we should be able to create & delete the file.
// We let the test panic if something goes wrong.
let mut f = File::create(path.clone()).unwrap();
f.write_all(b"Hello, world!").unwrap();
fs::remove_file(path).unwrap();
assert!(true);
}

0 comments on commit cfa0d0b

Please sign in to comment.