1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
// Copyright (C) 2018 Jakob L. Kreuze, All Rights Reserved.
//
// This file is part of rebuild.
//
// rebuild is free software: you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the Free Software
// Foundation, either version 3 of the License, or (at your option) any later
// version.
//
// rebuild is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE. See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with
// rebuild. If not, see <http://www.gnu.org/licenses/>.
use std::env;
use std::error::Error;
use std::path::Path;
/// Manager for a list of "search paths" on the filesystem, for the purpose of
/// resolving the absolute path of data files that have several possible
/// locations. See the documentation of 'find' for more information on the
/// default search paths.
#[derive(Debug)]
pub struct PathManager {
search: Vec<String>,
}
impl PathManager {
// TODO: Implement the following additional search paths:
// - The steam paths on GNU/Linux.
// - The "standard" paths for OSX (See G_AddSearchPaths)
// - The "standard" paths for Windows (See G_AddSearchPaths)
// - Those specified on the command-line.
// - See the CommandPaths and CommandGrps globals in common.cpp
// - The "app dir" on OSX.
// - PROPERLY add the CWD.
// - $HOME/apps/rebuild/ (?)
// - $HOME/.config/rebuild/
// - Those specified via DUKE3DGRP environment variable.
// - See JBF 20031220
/// Create a new PathManager and initialize the search path list with
/// acceptable defaults. See the documentation of 'find' for more
/// information on the default search paths.
pub fn new() -> PathManager {
let mut result = PathManager { search: Vec::new() };
let directories = vec![
".",
"/usr/share/games/jfduke3d",
"/usr/local/share/games/jfduke3d",
"/usr/share/games/eduke32",
"/usr/local/share/games/eduke32",
"/usr/share/games/rebuild",
"/usr/local/share/games/rebuild",
];
for directory in directories.iter() {
result.add_path(directory).ok();
}
let directories = vec![
"$HOME/.rebuild",
];
if let Some(home) = env::home_dir() {
if let Some(home) = home.to_str() {
for path in directories.iter() {
let path = String::from(*path).replace("$HOME", home);
result.add_path(&path).ok();
}
}
}
result
}
/// Add an additional path for searching.
///
/// # Errors
///
/// A return value of 'Err' indicates that the given path did not exist.
pub fn add_path(&mut self, path: &str) -> Result<(), Box<Error>> {
if Path::new(&path).exists() {
self.search.push(String::from(path));
} else {
bail!("Path does not exist");
}
Ok(())
}
/// Go through the search path list in order and return the first existing
/// path with the the given name, or None if no such file was found. The
/// default search path order is:
///
/// - ".",
/// - "/usr/local/share/games/rebuild",
/// - "/usr/share/games/rebuild",
/// - "/usr/local/share/games/eduke32",
/// - "/usr/share/games/eduke32",
/// - "/usr/local/share/games/jfduke3d",
/// - "/usr/share/games/jfduke3d",
/// - "$HOME/.rebuild",
///
/// This is followed by any additional paths in the search path list tha`t
/// were added by 'add_path'.
pub fn find(&self, name: &str) -> Option<String> {
for directory in self.search.iter() {
let path = format!("{}/{}", directory, name);
if Path::new(&path).exists() {
return Some(path);
}
}
None
}
}
|