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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1f459170e11712e3d18dc8937e433ea724dd7dd016b3e5cbf5a7e6da722b4dfe
4
- data.tar.gz: a3c27c26aee46ca61237635c42add31fb307a787706af74b87eb62eb74c17dda
3
+ metadata.gz: 64eada185c9f0597ca475f6f94f77299b5ebf0458fe6de87d5a041d7a6d69dfe
4
+ data.tar.gz: 5d14a11a8a468eba873da3b6e4d2628e8fdbb5d88150c60575b6266a4df5f726
5
5
  SHA512:
6
- metadata.gz: c7d6b3a879a2acbfe48eeb96acd9bc53674c6525e0637820c40de7d988a45647a6310dfbbaab96b9d46856a9722ed595d9b957bc8fbc1c04b1a690e2e937f73d
7
- data.tar.gz: e8c3bf596e1a508647a1f21ba3323796e9fa7f29a8145275b7dc8a91aa8c852bf7438216db1f36c3d4c602b36b79a7b1c9e9f01e3e2126db4427f47dd9477809
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.4.1"
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.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
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.36"
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.36 (registry+https://github.com/rust-lang/crates.io-index)",
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#a71d5783e92d9dfd3602f81adc96f640ff377f21"
43
+ source = "git+https://github.com/danielpclark/ruby-sys?branch=playground#184a3cd3bd39b525ff956f7cba1770bbf1522d8b"
44
44
  dependencies = [
45
- "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
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#e35b9dd88d86f3b8bb9cede7a74b04781bd4da89"
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.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a07ccb27c611e5cda99e498e99ba71b3ecdb7db5df02096cef42a3df5b84542"
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.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1e5d97d6708edaa407429faa671b942dc0f2727222fb6b6539bf1db936e4b121"
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.4.1"
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.5.svg)](https://github.com/danielpclark/faster_path/pulse)
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
@@ -87,6 +87,10 @@ module FasterPath
87
87
  def relative?
88
88
  FasterPath.relative?(@path)
89
89
  end
90
+
91
+ def relative_path_from(other)
92
+ FasterPath.relative_path_from(@path, other)
93
+ end
90
94
  end
91
95
  end
92
96
  end
@@ -82,6 +82,10 @@ module FasterPath
82
82
  def relative?
83
83
  FasterPath.relative?(@path)
84
84
  end
85
+
86
+ def relative_path_from(other)
87
+ FasterPath.relative_path_from(@path, other)
88
+ end
85
89
  end
86
90
  end
87
91
  end
@@ -1,3 +1,3 @@
1
1
  module FasterPath
2
- VERSION = "0.2.5"
2
+ VERSION = "0.2.6"
3
3
  end
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<(String,String)> {
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 mut offset = 0;
10
- let mut trailing_slashes = input.chars().rev();
11
- loop {
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.to_string(), base.to_string()))
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(&""[..]), None);
32
- assert_eq!(chop_basename(&"/"[..]), None);
33
- assert_eq!(
34
- chop_basename(&"."[..]),
35
- Some(("".to_string(), ".".to_string()))
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
 
@@ -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 pathname::Pathname;
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
- // fn r_relative_path_from(){}
143
- // fn pub_relative_path_from(){}
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::{RString, Boolean, Array, AnyObject, NilClass, Object, Class, VerifiedObject};
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 results = chop_basename::chop_basename(pth.ok().unwrap_or(RString::new("")).to_str());
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
- // pub fn pn_relative_path_from(){}
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
- klass: Value,
12
- name: &str,
13
- callback: ValueCallback<I, O>,
15
+ klass: Value,
16
+ name: &str,
17
+ callback: ValueCallback<I, O>,
14
18
  ) {
15
- let name = str_to_cstring(name);
19
+ let name = str_to_cstring(name);
16
20
 
17
- unsafe {
18
- class::rb_define_singleton_method(klass, name.as_ptr(), callback as CallbackPtr, -1);
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.clone();
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.clone();
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.5
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-02-28 00:00:00.000000000 Z
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: