faster_path 0.2.5 → 0.2.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Cargo.lock +9 -9
- data/Cargo.toml +1 -1
- data/README.md +2 -1
- data/lib/faster_path/optional/monkeypatches.rb +4 -0
- data/lib/faster_path/optional/refinements.rb +4 -0
- data/lib/faster_path/version.rb +1 -1
- data/src/chop_basename.rs +12 -35
- data/src/cleanpath_aggressive.rs +1 -1
- data/src/cleanpath_conservative.rs +2 -2
- data/src/debug.rs +29 -0
- data/src/helpers.rs +10 -38
- data/src/lib.rs +15 -3
- data/src/pathname.rs +32 -3
- data/src/pathname_sys.rs +13 -9
- data/src/plus.rs +4 -4
- data/src/relative_path_from.rs +90 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 64eada185c9f0597ca475f6f94f77299b5ebf0458fe6de87d5a041d7a6d69dfe
|
4
|
+
data.tar.gz: 5d14a11a8a468eba873da3b6e4d2628e8fdbb5d88150c60575b6266a4df5f726
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c2121f4aa08b8979818480b78980f07563483befa52c2493821f7a562d0f213a762f192ed1b7ec3c67050c9f0a72bccbb65a0dcb1d7258316ffbe0ae7480c2f
|
7
|
+
data.tar.gz: 0c16b9cd5e5ff583717d664228bfac6ac4b6b5e46c7a92c8a3170ae050ae9ec6974dc597a1c9aff8232e77515b3d5cd70bfccd33c5fa67402091af660dd7f502
|
data/Cargo.lock
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
[[package]]
|
2
2
|
name = "array_tool"
|
3
|
-
version = "0.
|
3
|
+
version = "1.0.1"
|
4
4
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
5
5
|
|
6
6
|
[[package]]
|
7
7
|
name = "faster_path"
|
8
8
|
version = "0.0.1"
|
9
9
|
dependencies = [
|
10
|
-
"array_tool 0.
|
10
|
+
"array_tool 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
11
11
|
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
12
12
|
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
13
13
|
"ruby-sys 0.3.0 (git+https://github.com/danielpclark/ruby-sys?branch=playground)",
|
@@ -26,7 +26,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
26
26
|
|
27
27
|
[[package]]
|
28
28
|
name = "libc"
|
29
|
-
version = "0.2.
|
29
|
+
version = "0.2.37"
|
30
30
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
31
31
|
|
32
32
|
[[package]]
|
@@ -34,31 +34,31 @@ name = "memchr"
|
|
34
34
|
version = "2.0.1"
|
35
35
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
36
36
|
dependencies = [
|
37
|
-
"libc 0.2.
|
37
|
+
"libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
38
38
|
]
|
39
39
|
|
40
40
|
[[package]]
|
41
41
|
name = "ruby-sys"
|
42
42
|
version = "0.3.0"
|
43
|
-
source = "git+https://github.com/danielpclark/ruby-sys?branch=playground#
|
43
|
+
source = "git+https://github.com/danielpclark/ruby-sys?branch=playground#184a3cd3bd39b525ff956f7cba1770bbf1522d8b"
|
44
44
|
dependencies = [
|
45
|
-
"libc 0.2.
|
45
|
+
"libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
46
46
|
]
|
47
47
|
|
48
48
|
[[package]]
|
49
49
|
name = "ruru"
|
50
50
|
version = "0.9.3"
|
51
|
-
source = "git+https://github.com/danielpclark/ruru?branch=playground#
|
51
|
+
source = "git+https://github.com/danielpclark/ruru?branch=playground#c9b59118ebcf034874d491a0c1f3b57ef05c183a"
|
52
52
|
dependencies = [
|
53
53
|
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
54
54
|
"ruby-sys 0.3.0 (git+https://github.com/danielpclark/ruby-sys?branch=playground)",
|
55
55
|
]
|
56
56
|
|
57
57
|
[metadata]
|
58
|
-
"checksum array_tool 0.
|
58
|
+
"checksum array_tool 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7894b81e06d8a2376f015b34dd89770c549932ff90bba6427f7cd83243bb629b"
|
59
59
|
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
|
60
60
|
"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
|
61
|
-
"checksum libc 0.2.
|
61
|
+
"checksum libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)" = "56aebce561378d99a0bb578f8cb15b6114d2a1814a6c7949bbe646d968bb4fa9"
|
62
62
|
"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
|
63
63
|
"checksum ruby-sys 0.3.0 (git+https://github.com/danielpclark/ruby-sys?branch=playground)" = "<none>"
|
64
64
|
"checksum ruru 0.9.3 (git+https://github.com/danielpclark/ruru?branch=playground)" = "<none>"
|
data/Cargo.toml
CHANGED
@@ -15,6 +15,6 @@ crate-type = ["dylib"]
|
|
15
15
|
[dependencies]
|
16
16
|
ruby-sys = { git = "https://github.com/danielpclark/ruby-sys", branch = "playground" }
|
17
17
|
ruru = { git = "https://github.com/danielpclark/ruru", branch = "playground" }
|
18
|
-
array_tool = "0
|
18
|
+
array_tool = "1.0"
|
19
19
|
lazy_static = "1.0"
|
20
20
|
memchr = "2.0.1"
|
data/README.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
[![TravisCI Build Status](https://travis-ci.org/danielpclark/faster_path.svg?branch=master)](https://travis-ci.org/danielpclark/faster_path)
|
4
4
|
[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/10ul0gk3cwhlt2lj/branch/master?svg=true)](https://ci.appveyor.com/project/danielpclark/faster-path/branch/master)
|
5
5
|
[![Latest Tag](https://img.shields.io/github/tag/danielpclark/faster_path.svg)](https://github.com/danielpclark/faster_path/tags)
|
6
|
-
[![Commits Since Last Release](https://img.shields.io/github/commits-since/danielpclark/faster_path/v0.2.
|
6
|
+
[![Commits Since Last Release](https://img.shields.io/github/commits-since/danielpclark/faster_path/v0.2.6.svg)](https://github.com/danielpclark/faster_path/pulse)
|
7
7
|
[![Binary Release](https://img.shields.io/github/release/danielpclark/faster_path.svg)](https://github.com/danielpclark/faster_path/releases)
|
8
8
|
[![Coverage Status](https://coveralls.io/repos/github/danielpclark/faster_path/badge.svg)](https://coveralls.io/github/danielpclark/faster_path)
|
9
9
|
[![Inline docs](http://inch-ci.org/github/danielpclark/faster_path.svg?branch=master)](http://inch-ci.org/github/danielpclark/faster_path)
|
@@ -151,6 +151,7 @@ Current methods implemented:
|
|
151
151
|
| `FasterPath.plus` | `Pathname#join` | 66.4% |
|
152
152
|
| `FasterPath.plus` | `Pathname#plus` | 81.4% |
|
153
153
|
| `FasterPath.relative?` | `Pathname#relative?` | 84.1% |
|
154
|
+
| `FasterPath.relative_path_from` | `Pathname#relative_path_from` | 69.8% |
|
154
155
|
|
155
156
|
You may choose to use the methods directly, or scope change to rewrite behavior on the
|
156
157
|
standard library with the included refinements, or even call a method to monkeypatch
|
data/lib/faster_path/version.rb
CHANGED
data/src/chop_basename.rs
CHANGED
@@ -1,54 +1,31 @@
|
|
1
1
|
use std::path::MAIN_SEPARATOR;
|
2
2
|
use std::str;
|
3
3
|
|
4
|
-
pub fn chop_basename(input: &str) -> Option<(
|
4
|
+
pub fn chop_basename<'a>(input: &'a str) -> Option<(&'a str, &'a str)> {
|
5
5
|
if input.is_empty() {
|
6
6
|
return None;
|
7
7
|
}
|
8
8
|
|
9
|
-
let
|
10
|
-
let
|
11
|
-
|
12
|
-
match trailing_slashes.next() {
|
13
|
-
Some(MAIN_SEPARATOR) => { offset = offset + 1 },
|
14
|
-
_ => { break },
|
15
|
-
}
|
16
|
-
}
|
17
|
-
|
18
|
-
let input = &input[0..input.len()-offset];
|
19
|
-
let base = input.rsplit_terminator(MAIN_SEPARATOR).nth(0).unwrap_or("");
|
9
|
+
let input = input.trim_right_matches(MAIN_SEPARATOR);
|
10
|
+
let end = input.rsplitn(2, MAIN_SEPARATOR).nth(0).unwrap().len();
|
11
|
+
let base = &input[input.len()-end..input.len()];
|
20
12
|
let directory = &input[0..input.len()-base.len()];
|
21
13
|
|
22
14
|
if directory.is_empty() && (base.is_empty() || base.chars().next().unwrap() == MAIN_SEPARATOR) {
|
23
15
|
return None
|
24
16
|
};
|
25
17
|
|
26
|
-
Some((directory
|
18
|
+
Some((directory, base))
|
27
19
|
}
|
28
20
|
|
29
21
|
#[test]
|
30
22
|
fn it_chops_the_basename_and_dirname() {
|
31
|
-
assert_eq!(chop_basename(
|
32
|
-
assert_eq!(chop_basename(
|
33
|
-
assert_eq!(
|
34
|
-
|
35
|
-
|
36
|
-
);
|
37
|
-
assert_eq!(
|
38
|
-
chop_basename(&"asdf/asdf"[..]),
|
39
|
-
Some(("asdf/".to_string(), "asdf".to_string()))
|
40
|
-
);
|
41
|
-
assert_eq!(
|
42
|
-
chop_basename(&"asdf.txt"[..]),
|
43
|
-
Some(("".to_string(), "asdf.txt".to_string()))
|
44
|
-
);
|
45
|
-
assert_eq!(
|
46
|
-
chop_basename(&"asdf/"[..]),
|
47
|
-
Some(("".to_string(), "asdf".to_string()))
|
48
|
-
);
|
49
|
-
assert_eq!(
|
50
|
-
chop_basename(&"/asdf/"[..]),
|
51
|
-
Some(("/".to_string(), "asdf".to_string()))
|
52
|
-
);
|
23
|
+
assert_eq!(chop_basename(""), None );
|
24
|
+
assert_eq!(chop_basename("/"), None );
|
25
|
+
assert_eq!(chop_basename("."), Some(("", ".")) );
|
26
|
+
assert_eq!(chop_basename("asdf/asdf"), Some(("asdf/", "asdf")) );
|
27
|
+
assert_eq!(chop_basename("asdf.txt"), Some(("", "asdf.txt")) );
|
28
|
+
assert_eq!(chop_basename("asdf/"), Some(("", "asdf")) );
|
29
|
+
assert_eq!(chop_basename("/asdf/"), Some(("/", "asdf")) );
|
53
30
|
}
|
54
31
|
|
data/src/cleanpath_aggressive.rs
CHANGED
@@ -10,7 +10,7 @@ pub fn cleanpath_aggressive(path: &str) -> String {
|
|
10
10
|
let mut names: Vec<String> = vec![];
|
11
11
|
let mut pre = path.to_string();
|
12
12
|
loop {
|
13
|
-
match chop_basename(&pre) {
|
13
|
+
match chop_basename(&pre.clone()) {
|
14
14
|
Some((ref p, ref base)) => {
|
15
15
|
pre = p.to_string();
|
16
16
|
match base.as_ref() {
|
@@ -11,7 +11,7 @@ pub fn cleanpath_conservative(path: &str) -> String {
|
|
11
11
|
let mut names: Vec<String> = vec![];
|
12
12
|
let mut pre = path.to_string();
|
13
13
|
loop {
|
14
|
-
match chop_basename(&pre) {
|
14
|
+
match chop_basename(&pre.clone()) {
|
15
15
|
Some((ref p, ref base)) => {
|
16
16
|
pre = p.to_string();
|
17
17
|
match base.as_ref() {
|
@@ -90,7 +90,7 @@ fn it_conservatively_cleans_the_path() {
|
|
90
90
|
assert_eq!(cleanpath_conservative("a/../."), "a/..");
|
91
91
|
assert_eq!(cleanpath_conservative("/../.././../a"), "/a");
|
92
92
|
assert_eq!(cleanpath_conservative("a/b/../../../../c/../d"), "a/b/../../../../c/../d");
|
93
|
-
|
93
|
+
|
94
94
|
// Future Windows Support
|
95
95
|
//
|
96
96
|
// DOSISH = File::ALT_SEPARATOR != nil
|
data/src/debug.rs
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
use ruru::{
|
2
|
+
RString,
|
3
|
+
AnyObject,
|
4
|
+
Object,
|
5
|
+
};
|
6
|
+
|
7
|
+
#[derive(Debug)]
|
8
|
+
pub struct RubyDebugInfo {
|
9
|
+
object_id: String,
|
10
|
+
class: String,
|
11
|
+
inspect: String,
|
12
|
+
}
|
13
|
+
|
14
|
+
impl From<AnyObject> for RubyDebugInfo {
|
15
|
+
fn from(ao: AnyObject) -> Self {
|
16
|
+
let object_id = ao.send("object_id", None).send("to_s", None).
|
17
|
+
try_convert_to::<RString>().unwrap_or(RString::new("Failed to get object_id!")).to_string();
|
18
|
+
let class = ao.send("class", None).send("to_s", None).
|
19
|
+
try_convert_to::<RString>().unwrap_or(RString::new("Failed to get class!")).to_string();
|
20
|
+
let inspect = ao.send("inspect", None).
|
21
|
+
try_convert_to::<RString>().unwrap_or(RString::new("Failed to get inspect!")).to_string();
|
22
|
+
|
23
|
+
RubyDebugInfo {
|
24
|
+
object_id: object_id,
|
25
|
+
class: class,
|
26
|
+
inspect: inspect,
|
27
|
+
}
|
28
|
+
}
|
29
|
+
}
|
data/src/helpers.rs
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
use ruru::{RString, Object, Class, AnyObject};
|
2
|
-
use
|
2
|
+
use debug::RubyDebugInfo;
|
3
|
+
|
4
|
+
#[inline]
|
5
|
+
pub fn is_same_path(a: &str, b: &str) -> bool {
|
6
|
+
if cfg!(windows) {
|
7
|
+
a.to_uppercase() == b.to_uppercase()
|
8
|
+
} else {
|
9
|
+
a == b
|
10
|
+
}
|
11
|
+
}
|
3
12
|
|
4
13
|
pub fn anyobject_to_string(item: AnyObject) -> Result<String, RubyDebugInfo> {
|
5
14
|
let result = &item;
|
@@ -24,40 +33,3 @@ pub fn anyobject_to_string(item: AnyObject) -> Result<String, RubyDebugInfo> {
|
|
24
33
|
|
25
34
|
Ok(RString::from(result.send("to_s", None).value()).to_string())
|
26
35
|
}
|
27
|
-
|
28
|
-
#[allow(dead_code)]
|
29
|
-
pub fn into_pathname(itself: AnyObject) -> Result<AnyObject, RubyDebugInfo> {
|
30
|
-
if Class::from_existing("String").case_equals(&itself) {
|
31
|
-
Ok(Pathname::new(
|
32
|
-
&RString::from(itself.value()).to_string()
|
33
|
-
).to_any_object())
|
34
|
-
} else if Class::from_existing("Pathname").case_equals(&itself) {
|
35
|
-
Ok(itself)
|
36
|
-
} else {
|
37
|
-
Err(RubyDebugInfo::from(itself))
|
38
|
-
}
|
39
|
-
}
|
40
|
-
|
41
|
-
#[derive(Debug)]
|
42
|
-
pub struct RubyDebugInfo {
|
43
|
-
object_id: String,
|
44
|
-
class: String,
|
45
|
-
inspect: String,
|
46
|
-
}
|
47
|
-
|
48
|
-
impl From<AnyObject> for RubyDebugInfo {
|
49
|
-
fn from(ao: AnyObject) -> Self {
|
50
|
-
let object_id = ao.send("object_id", None).send("to_s", None).
|
51
|
-
try_convert_to::<RString>().unwrap_or(RString::new("Failed to get object_id!")).to_string();
|
52
|
-
let class = ao.send("class", None).send("to_s", None).
|
53
|
-
try_convert_to::<RString>().unwrap_or(RString::new("Failed to get class!")).to_string();
|
54
|
-
let inspect = ao.send("inspect", None).
|
55
|
-
try_convert_to::<RString>().unwrap_or(RString::new("Failed to get inspect!")).to_string();
|
56
|
-
|
57
|
-
RubyDebugInfo {
|
58
|
-
object_id: object_id,
|
59
|
-
class: class,
|
60
|
-
inspect: inspect,
|
61
|
-
}
|
62
|
-
}
|
63
|
-
}
|
data/src/lib.rs
CHANGED
@@ -4,6 +4,8 @@
|
|
4
4
|
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
5
5
|
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
6
6
|
// copied, modified, or distributed except according to those terms.
|
7
|
+
#![feature(try_from)]
|
8
|
+
|
7
9
|
#[macro_use]
|
8
10
|
extern crate ruru;
|
9
11
|
|
@@ -12,6 +14,7 @@ extern crate lazy_static;
|
|
12
14
|
|
13
15
|
module!(FasterPath);
|
14
16
|
|
17
|
+
mod debug;
|
15
18
|
mod helpers;
|
16
19
|
mod pathname;
|
17
20
|
mod basename;
|
@@ -25,6 +28,10 @@ mod plus;
|
|
25
28
|
mod prepend_prefix;
|
26
29
|
pub mod rust_arch_bits;
|
27
30
|
mod path_parsing;
|
31
|
+
mod relative_path_from;
|
32
|
+
|
33
|
+
use pathname::Pathname;
|
34
|
+
use pathname_sys::raise;
|
28
35
|
|
29
36
|
use ruru::{Module, Object, RString, Boolean, Array, AnyObject};
|
30
37
|
|
@@ -139,8 +146,12 @@ methods!(
|
|
139
146
|
|
140
147
|
// fn r_split_names(pth: RString){}
|
141
148
|
|
142
|
-
|
143
|
-
|
149
|
+
fn pub_relative_path_from(itself: RString, base_directory: AnyObject) -> Pathname {
|
150
|
+
let to_string = |i: AnyObject| { RString::from(i.send("to_s", None).value()) };
|
151
|
+
|
152
|
+
pathname::pn_relative_path_from(itself, base_directory.map(to_string)).
|
153
|
+
map_err(|e| raise(e) ).unwrap()
|
154
|
+
}
|
144
155
|
|
145
156
|
// fn pub_rmtree(pth: RString) -> NilClass {
|
146
157
|
// pathname::pn_rmtree(pth)
|
@@ -149,7 +160,7 @@ methods!(
|
|
149
160
|
|
150
161
|
#[allow(non_snake_case)]
|
151
162
|
#[no_mangle]
|
152
|
-
pub extern "C" fn Init_faster_pathname(){
|
163
|
+
pub extern "C" fn Init_faster_pathname() {
|
153
164
|
Module::from_existing("FasterPath").define(|itself| {
|
154
165
|
itself.def_self("absolute?", pub_is_absolute);
|
155
166
|
itself.def_self("add_trailing_separator", pub_add_trailing_separator);
|
@@ -164,6 +175,7 @@ pub extern "C" fn Init_faster_pathname(){
|
|
164
175
|
pathname_sys::define_singleton_method(itself.value(), "join", pub_join);
|
165
176
|
itself.def_self("plus", pub_plus);
|
166
177
|
itself.def_self("relative?", pub_is_relative);
|
178
|
+
itself.def_self("relative_path_from", pub_relative_path_from);
|
167
179
|
itself.define_nested_class("Public", None);
|
168
180
|
});
|
169
181
|
|
data/src/pathname.rs
CHANGED
@@ -6,9 +6,22 @@ use cleanpath_conservative;
|
|
6
6
|
use dirname;
|
7
7
|
use extname;
|
8
8
|
use plus;
|
9
|
+
use relative_path_from;
|
10
|
+
use debug;
|
11
|
+
use std::convert::TryFrom;
|
9
12
|
|
10
13
|
use ruru;
|
11
|
-
use ruru::{
|
14
|
+
use ruru::{
|
15
|
+
RString,
|
16
|
+
Boolean,
|
17
|
+
Array,
|
18
|
+
AnyObject,
|
19
|
+
NilClass,
|
20
|
+
Object,
|
21
|
+
Class,
|
22
|
+
VerifiedObject,
|
23
|
+
AnyException as Exception
|
24
|
+
};
|
12
25
|
use ruru::types::{Value, ValueType};
|
13
26
|
use std::path::{MAIN_SEPARATOR,Path};
|
14
27
|
use std::fs;
|
@@ -40,6 +53,19 @@ impl From<Value> for Pathname {
|
|
40
53
|
}
|
41
54
|
}
|
42
55
|
|
56
|
+
impl TryFrom<AnyObject> for Pathname {
|
57
|
+
type Error = debug::RubyDebugInfo;
|
58
|
+
fn try_from(obj: AnyObject) -> Result<Pathname, Self::Error> {
|
59
|
+
if Class::from_existing("String").case_equals(&obj) {
|
60
|
+
Ok(Pathname::new(&RString::from(obj.value()).to_string()))
|
61
|
+
} else if Class::from_existing("Pathname").case_equals(&obj) {
|
62
|
+
Ok(Pathname::from(obj.value()))
|
63
|
+
} else {
|
64
|
+
Err(Self::Error::from(obj))
|
65
|
+
}
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
43
69
|
impl Object for Pathname {
|
44
70
|
#[inline]
|
45
71
|
fn value(&self) -> Value {
|
@@ -151,7 +177,8 @@ pub fn pn_children_compat(pth: MaybeString, with_dir: MaybeBoolean) -> AnyObject
|
|
151
177
|
|
152
178
|
pub fn pn_chop_basename(pth: MaybeString) -> Array {
|
153
179
|
let mut arr = Array::with_capacity(2);
|
154
|
-
let
|
180
|
+
let pth = pth.ok().unwrap_or(RString::new(""));
|
181
|
+
let results = chop_basename::chop_basename(pth.to_str());
|
155
182
|
match results {
|
156
183
|
Some((dirname, basename)) => {
|
157
184
|
arr.push(RString::new(&dirname[..]));
|
@@ -341,7 +368,9 @@ pub fn pn_is_relative(pth: MaybeString) -> Boolean {
|
|
341
368
|
|
342
369
|
// pub fn pn_split_names(pth: MaybeString){}
|
343
370
|
|
344
|
-
|
371
|
+
pub fn pn_relative_path_from(itself: MaybeString, base_directory: MaybeString) -> Result<Pathname, Exception> {
|
372
|
+
relative_path_from::relative_path_from(itself, base_directory)
|
373
|
+
}
|
345
374
|
|
346
375
|
// pub fn pn_rmtree(pth: MaybeString) -> NilClass {
|
347
376
|
// NilClass::new()
|
data/src/pathname_sys.rs
CHANGED
@@ -1,22 +1,26 @@
|
|
1
|
-
use ruru::{AnyObject, Array, Object};
|
1
|
+
use ruru::{AnyObject, Array, Object, AnyException};
|
2
2
|
use ruru::types::{Argc, Value, CallbackPtr};
|
3
3
|
use ruru::util::str_to_cstring;
|
4
4
|
extern crate ruby_sys;
|
5
|
-
use self::ruby_sys::{class, util};
|
5
|
+
use self::ruby_sys::{class, util, vm};
|
6
6
|
use ::pathname;
|
7
7
|
|
8
|
+
pub fn raise(exception: AnyException) {
|
9
|
+
unsafe { vm::rb_exc_raise(exception.value()); }
|
10
|
+
}
|
11
|
+
|
8
12
|
pub type ValueCallback<I, O> = extern "C" fn(Argc, *const Value, I) -> O;
|
9
13
|
|
10
14
|
pub fn define_singleton_method<I: Object, O: Object>(
|
11
|
-
|
12
|
-
|
13
|
-
|
15
|
+
klass: Value,
|
16
|
+
name: &str,
|
17
|
+
callback: ValueCallback<I, O>,
|
14
18
|
) {
|
15
|
-
|
19
|
+
let name = str_to_cstring(name);
|
16
20
|
|
17
|
-
|
18
|
-
|
19
|
-
|
21
|
+
unsafe {
|
22
|
+
class::rb_define_singleton_method(klass, name.as_ptr(), callback as CallbackPtr, -1);
|
23
|
+
}
|
20
24
|
}
|
21
25
|
|
22
26
|
// ruru doesn't support splat arguments yet
|
data/src/plus.rs
CHANGED
@@ -13,10 +13,10 @@ pub fn plus_paths(path1: &str, path2: &str) -> String {
|
|
13
13
|
let mut basename_list2: Vec<String> = vec![];
|
14
14
|
|
15
15
|
loop {
|
16
|
-
match chop_basename(&prefix2[..]) {
|
16
|
+
match chop_basename(&prefix2.clone()[..]) {
|
17
17
|
None => { break },
|
18
18
|
Some((pfx2, basename2)) => {
|
19
|
-
prefix2 = pfx2.
|
19
|
+
prefix2 = pfx2.to_string();
|
20
20
|
index_list2.unshift(pfx2.len());
|
21
21
|
basename_list2.unshift(basename2.to_owned());
|
22
22
|
},
|
@@ -33,10 +33,10 @@ pub fn plus_paths(path1: &str, path2: &str) -> String {
|
|
33
33
|
index_list2.shift();
|
34
34
|
basename_list2.shift();
|
35
35
|
}
|
36
|
-
match chop_basename(&prefix1[..]) {
|
36
|
+
match chop_basename(&prefix1.clone()[..]) {
|
37
37
|
None => { break },
|
38
38
|
Some((pfx1, basename1)) => {
|
39
|
-
prefix1 = pfx1.
|
39
|
+
prefix1 = pfx1.to_string();
|
40
40
|
if basename1 == "." { continue };
|
41
41
|
if basename1 == ".." || basename_list2.is_empty() || basename_list2.first().unwrap() != ".." {
|
42
42
|
prefix1.push_str(&basename1);
|
@@ -0,0 +1,90 @@
|
|
1
|
+
use helpers::is_same_path;
|
2
|
+
use path_parsing::SEP_STR;
|
3
|
+
extern crate array_tool;
|
4
|
+
use self::array_tool::vec::{Shift, Join};
|
5
|
+
use self::array_tool::iter::ZipOpt;
|
6
|
+
use pathname;
|
7
|
+
use ruru;
|
8
|
+
use chop_basename;
|
9
|
+
use pathname::Pathname;
|
10
|
+
use ruru::{Exception as Exc, AnyException as Exception};
|
11
|
+
|
12
|
+
type MaybeString = Result<ruru::RString, ruru::result::Error>;
|
13
|
+
|
14
|
+
pub fn relative_path_from(itself: MaybeString, base_directory: MaybeString) -> Result<Pathname, Exception> {
|
15
|
+
let dest_directory = pathname::pn_cleanpath_aggressive(itself).to_string();
|
16
|
+
let base_directory = pathname::pn_cleanpath_aggressive(base_directory).to_string();
|
17
|
+
|
18
|
+
let mut dest_prefix = dest_directory.clone();
|
19
|
+
let mut dest_names: Vec<String> = vec![];
|
20
|
+
loop {
|
21
|
+
match chop_basename::chop_basename(&dest_prefix.clone()) {
|
22
|
+
Some((ref dest, ref basename)) => {
|
23
|
+
dest_prefix = dest.to_string();
|
24
|
+
if basename != &"." {
|
25
|
+
dest_names.unshift(basename.to_string())
|
26
|
+
}
|
27
|
+
},
|
28
|
+
None => break,
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
let mut base_prefix = base_directory.clone();
|
33
|
+
let mut base_names: Vec<String> = vec![];
|
34
|
+
loop {
|
35
|
+
match chop_basename::chop_basename(&base_prefix.clone()) {
|
36
|
+
Some((ref base, ref basename)) => {
|
37
|
+
base_prefix = base.to_string();
|
38
|
+
if basename != &"." {
|
39
|
+
base_names.unshift(basename.to_string())
|
40
|
+
}
|
41
|
+
},
|
42
|
+
None => break,
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
if !is_same_path(&dest_prefix, &base_prefix) {
|
47
|
+
return Err(
|
48
|
+
Exception::new(
|
49
|
+
"ArgumentError",
|
50
|
+
Some(&format!("different prefix: {} and {}", dest_prefix, base_prefix)[..])
|
51
|
+
)
|
52
|
+
);
|
53
|
+
}
|
54
|
+
|
55
|
+
let (dest_names, base_names): (Vec<String>, Vec<String>) = dest_names.
|
56
|
+
iter().
|
57
|
+
zip_option(base_names.iter()).
|
58
|
+
skip_while(|&(a, b)| {
|
59
|
+
match (a, b) {
|
60
|
+
(Some(x), Some(y)) => is_same_path(x,y),
|
61
|
+
_ => false,
|
62
|
+
}
|
63
|
+
}).
|
64
|
+
fold((vec![], vec![]), |mut acc, (a, b)| {
|
65
|
+
if let Some(v) = a {
|
66
|
+
acc.0.push(v.to_string());
|
67
|
+
}
|
68
|
+
if let Some(v) = b {
|
69
|
+
acc.1.push(v.to_string());
|
70
|
+
}
|
71
|
+
acc
|
72
|
+
});
|
73
|
+
|
74
|
+
if base_names.contains(&"..".to_string()) {
|
75
|
+
return Err(
|
76
|
+
Exception::new(
|
77
|
+
"ArgumentError",
|
78
|
+
Some(&format!("base_directory has ..: {}", base_directory)[..])
|
79
|
+
)
|
80
|
+
);
|
81
|
+
}
|
82
|
+
|
83
|
+
let base_names: Vec<String> = base_names.into_iter().map(|_| "..".to_string()).collect();
|
84
|
+
|
85
|
+
if base_names.is_empty() && dest_names.is_empty() {
|
86
|
+
Ok(Pathname::new("."))
|
87
|
+
} else {
|
88
|
+
Ok(Pathname::new(&base_names.iter().chain(dest_names.iter()).collect::<Vec<&String>>().join(&SEP_STR)))
|
89
|
+
}
|
90
|
+
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: faster_path
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel P. Clark
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-03-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -149,6 +149,7 @@ files:
|
|
149
149
|
- src/chop_basename.rs
|
150
150
|
- src/cleanpath_aggressive.rs
|
151
151
|
- src/cleanpath_conservative.rs
|
152
|
+
- src/debug.rs
|
152
153
|
- src/dirname.rs
|
153
154
|
- src/extname.rs
|
154
155
|
- src/helpers.rs
|
@@ -158,6 +159,7 @@ files:
|
|
158
159
|
- src/pathname_sys.rs
|
159
160
|
- src/plus.rs
|
160
161
|
- src/prepend_prefix.rs
|
162
|
+
- src/relative_path_from.rs
|
161
163
|
- src/rust_arch_bits.rs
|
162
164
|
homepage: https://github.com/danielpclark/faster_path
|
163
165
|
licenses:
|