Skip to content

Commit

Permalink
feat(pbxproj): get full path for a group or file
Browse files Browse the repository at this point in the history
  • Loading branch information
kkharji committed Jun 12, 2022
1 parent c97ca8d commit d1f3678
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 10 deletions.
163 changes: 161 additions & 2 deletions src/pbxproj/object/fs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ use super::*;
use std::{
cell::RefCell,
collections::HashSet,
path::{Path, PathBuf},
rc::{Rc, Weak},
};

use anyhow::Result;
pub use kind::*;
pub use source_tree::*;
use tap::Pipe;

/// Abstraction over `PBXFileReference`, `PBXGroup`, `PBXVariantGroup`, and `XCVersionGroup`
#[derive(Debug, Default)]
Expand Down Expand Up @@ -120,6 +123,95 @@ impl PBXFSReference {
pub fn parent(&self) -> Option<Rc<RefCell<Self>>> {
self.parent.upgrade()
}

/// Returns a file path to current fs reference using source root.
pub fn full_path<P: AsRef<Path>>(&self, source_root: P) -> Result<Option<PathBuf>> {
let source_root = source_root.as_ref();

let path = || {
self.path()
.ok_or_else(|| anyhow::anyhow!("Expected path to be set in file element!!"))
};

fn get_parts(path: &String) -> Vec<&str> {
if path.contains("/") {
path.split("/").collect()
} else {
vec![path]
}
}

match self.source_tree() {
Some(PBXSourceTree::Absolute) => path()?.pipe(PathBuf::from).pipe(Some),
Some(PBXSourceTree::SourceRoot) => {
let mut root = source_root.to_path_buf();
root.extend(get_parts(path()?));
Some(root)
}
Some(PBXSourceTree::Group) => {
let mut group_path: Option<PathBuf>;

if let Some(parent) = self.parent() {
println!("Using parent path");
group_path = parent.borrow().full_path(&source_root)?;
if let Some(ref mut g) = group_path {
if let Some(path) = self.path() {
g.extend(get_parts(path))
}
}
} else {
let objects = self
.objects
.upgrade()
.ok_or_else(|| anyhow::anyhow!("objects is released already!"))?;

let objects = objects.borrow();

if objects
.projects()
.into_iter()
.find(|(_, p)| &*p.borrow().main_group().borrow() == self)
.is_some()
{
if let Some(path) = self.path() {
let mut root = source_root.to_path_buf();
root.extend(get_parts(path));
println!("Joining {source_root:?} with {path:?}");
return Ok(Some(root));
} else {
println!("Self is main group and return source_root as is!");
return Ok(Some(source_root.to_path_buf()));
}
}

println!("Falling back to search through all groups");

// Fallback if parent is nil and it's not root element
let group = objects
.groups()
.into_iter()
.find(|(_, o)| {
o.borrow()
.children()
.into_iter()
.any(|o| &*o.borrow() == self)
})
.map(|(_, o)| o)
.ok_or_else(|| {
anyhow::anyhow!(
"Invalid group path {source_root:?} with {:?}",
self.path()
)
})?;

group_path = group.borrow().full_path(source_root)?;
}
group_path
}
_ => None,
}
.pipe(Ok)
}
}

impl Eq for PBXFSReference {}
Expand Down Expand Up @@ -163,14 +255,81 @@ fn test_parent() {
.main_group();

let main_group = main_group.borrow();

let source_group = main_group.get_subgroup("Source").unwrap();
let source_group = source_group.borrow();
let parent = source_group.parent();
println!("{:#?}", main_group);

assert_eq!(
parent.unwrap().borrow().children_references(),
main_group.children_references()
)
}
#[cfg(test)]
mod tests {
use super::*;

#[test]
fn get_root_full_path() {
use crate::pbxproj::test_demo_file;
let project = test_demo_file!(demo1);
let main_group = project
.objects()
.projects()
.first()
.unwrap()
.1
.borrow()
.main_group();

let root = PathBuf::from("/path/to/project");
let main_group = main_group.borrow();
let main_group_full_path = main_group.full_path(&root);
assert_eq!(main_group_full_path.unwrap().unwrap(), root);
}

#[test]
fn get_subgroup_full_path() {
let root = PathBuf::from("/path/to/project");
let project = crate::pbxproj::test_demo_file!(demo1);

let source_group = project
.objects()
.groups()
.into_iter()
.find(|(_, o)| o.borrow().path().map(|p| p == "Source").unwrap_or_default())
.map(|(_, o)| o.clone())
.unwrap();

let source_group = source_group.borrow();
let source_group_full_path = source_group.full_path(&root);
assert_eq!(
source_group_full_path.unwrap().unwrap(),
root.join("Source")
);
}

#[test]
fn get_file_full_path() {
let root = PathBuf::from("/path/to/project");
let project = crate::pbxproj::test_demo_file!(demo1);

let mut expected_file_path = root.clone();
expected_file_path.extend(&["Source", "Views", "GuessView.swift"]);

let file = project
.objects()
.get_fs_references(|fs_reference| {
fs_reference
.path()
.map(|name| name == "GuessView.swift")
.unwrap_or_default()
})
.first()
.map(|(_, o)| o.clone())
.unwrap();

let file = file.borrow();

assert_eq!(file.full_path(root).unwrap().unwrap(), expected_file_path)
}
}
16 changes: 8 additions & 8 deletions src/pbxproj/object/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ mod tests {
}

#[test]
fn test_packages() {
fn get_packages() {
let (_objects, project) = get_project("demo1");
let project = project.borrow();
let mut packages = project.packages().unwrap();
Expand All @@ -373,7 +373,7 @@ mod tests {
}

#[test]
fn test_targets() {
fn get_targets() {
let (_objects, project) = get_project("demo2");
let project = project.borrow();
let mut targets = project.targets();
Expand All @@ -386,7 +386,7 @@ mod tests {
}

#[test]
fn test_build_configuration_list() {
fn get_build_configuration_list() {
let (_objects, project) = get_project("demo3");
let project = project.borrow();
let build_configuration_list = project.build_configuration_list().unwrap();
Expand All @@ -398,7 +398,7 @@ mod tests {
}

#[test]
fn test_main_group() {
fn get_main_group() {
let (_objects, project) = get_project("demo4");
let project = project.borrow();
let main_group = project.main_group();
Expand All @@ -417,7 +417,7 @@ mod tests {
}

#[test]
fn test_products_group() {
fn get_products_group() {
let (_objects, project) = get_project("demo7");
let project = project.borrow();
let main_group = project.products_group().unwrap();
Expand All @@ -430,7 +430,7 @@ mod tests {
}

#[test]
fn test_add_swift_package_duplication() {
fn add_swift_package_duplication() {
let (_objects, project) = get_project("demo1");
let mut project = project.borrow_mut();
let err = project
Expand All @@ -445,7 +445,7 @@ mod tests {
}

#[test]
fn test_add_swift_package_with_new_version() {
fn add_swift_package_with_new_version() {
let (root, project) = get_project("demo1");
let mut project = project.borrow_mut();
let new_package = project
Expand All @@ -470,7 +470,7 @@ mod tests {
}

#[test]
fn test_add_swift_package_new_package() {
fn add_swift_package_new_package() {
let (root, project) = get_project("demo1");
let mut project = project.borrow_mut();
let new_package = project
Expand Down

0 comments on commit d1f3678

Please sign in to comment.