Repository: comtrya/comtrya (language: rust)

Issue:
Bug: Tera Function: read_file_contents strips out or doesn't interpret newlines properly.
**Description**

- this manifest: https://github.com/airtonix/dotfiles/blob/master/devtools/git/git.yml
- copying and templating these files: 
  - https://github.com/airtonix/dotfiles/blob/master/devtools/git/files/gitconfig
  - https://github.com/airtonix/dotfiles/blob/master/devtools/git/files/id.gitconfig
  - https://github.com/airtonix/dotfiles/blob/master/devtools/git/files/main.gitconfig
  - https://github.com/airtonix/dotfiles/blob/master/devtools/git/files/aliases.gitconfig

ends up creating this `~/.gitconfig`: 

```ini
[user]	name = Zeno Jiricek	email = airtonix@users.noreply.github.com
[core]	editor = code --wait[pull]	rebase = false[init]	defaultBranch = master[rerere]	enabled = true
[alias]	up = push origin HEAD	sync = "!f() { DEFAULT_BRANCH=$(git config --get core.defaultBranch || echo master); [ \"$(git branch --show-current)\" != \"${DEFAULT_BRANCH}\" ] && git fetch origin "${DEFAULT_BRANCH}:${DEFAULT_BRANCH}" || git pull; }; f"	fix = "!git stash save && git sync && echo fix | git start"	feature = "!git stash save && git sync && echo feature | git start"	feat = "!git stash save && git sync && echo feat | git start"	docs = "!git stash save && git sync && echo docs | git start"	ci = "!git stash save && git sync && echo ci | git start"	chore = "!git stash save && git sync && echo chore | git start"	start = "!read BRANCH && git checkout -b $BRANCH/$1 $(git config --get core.defaultBranch || echo master); git stash pop"	alias = "! git config --get-regexp ^alias\\. | sed -e 's/^alias\\.\\([^ ]*\\)/\\x1B[33m\\1\\x1B[0m =/'"	pivot = "!f() { WORKTREE_ROOT=$(git config --get core.worktreeRoot || {exit 1}); mkdir -p $WORKTREE_ROOT; git worktree add $WORKTREE_ROOT/$1 $2; code $WORKTREE_ROOT/$1;}; f"

```

**Steps to reproduce**
Step by step explanation. Please add the output of with `-vvv` flag enabled (be careful not to include any secrets from your config).

**Expected behaviour**
What the expected behaviour in your opinion.

- that `.gitconfig` ends up being a concatenation of the intput files.

**Environment**
- OS: Windows 11, Powershell 7
- Version: `0.8.0`

**Additional information**
Add more context which didn't fit in the fields above.



Discussion / hints:
I suspect the issue is the use of `flatten` here on all lines when you probably only want to deal with the last line? 

https://github.com/comtrya/comtrya/blob/main/lib/src/tera_functions/mod.rs#L15
This is a bug here:

https://github.com/comtrya/comtrya/blob/79c1214d3ffa20ad621f79e415d9fe87cbbce155/lib/src/tera_functions/mod.rs#L15

We’ll get this fixed. 
I'll fix it

Fix patch:
diff --git a/lib/src/actions/package/providers/homebrew.rs b/lib/src/actions/package/providers/homebrew.rs
index d347e322..fb61a07a 100644
--- a/lib/src/actions/package/providers/homebrew.rs
+++ b/lib/src/actions/package/providers/homebrew.rs
@@ -58,8 +58,7 @@ impl PackageProvider for Homebrew {
                 .stdout,
         )
         .unwrap()
-        .replace('\n', "")
-        .replace('\r', "");
+        .replace(['\n', '\r'], "");
 
         let cellar = Path::new(&prefix).join("Cellar");
         let caskroom = Path::new(&prefix).join("Caskroom");
@@ -68,10 +67,10 @@ impl PackageProvider for Homebrew {
             .packages()
             .into_iter()
             .filter(|p| {
-                if cellar.join(&p).is_dir() {
+                if cellar.join(p).is_dir() {
                     trace!("{}: found in Cellar", p);
                     false
-                } else if caskroom.join(&p).is_dir() {
+                } else if caskroom.join(p).is_dir() {
                     trace!("{}: found in Caskroom", p);
                     false
                 } else {
diff --git a/lib/src/manifests/mod.rs b/lib/src/manifests/mod.rs
index 6f310893..c532b0cf 100644
--- a/lib/src/manifests/mod.rs
+++ b/lib/src/manifests/mod.rs
@@ -61,7 +61,7 @@ pub fn resolve(uri: &String) -> Option<PathBuf> {
 }
 
 pub fn get_manifest_name(manifest_directory: &Path, location: &Path) -> String {
-    let local_name = location.strip_prefix(&manifest_directory).unwrap();
+    let local_name = location.strip_prefix(manifest_directory).unwrap();
     let manifest_name =
         local_name
             .components()
diff --git a/lib/src/manifests/providers/git.rs b/lib/src/manifests/providers/git.rs
index 80ad1fbe..14064bfc 100644
--- a/lib/src/manifests/providers/git.rs
+++ b/lib/src/manifests/providers/git.rs
@@ -95,9 +95,7 @@ impl GitManifestProvider {
         uri.to_string()
             .replace("https", "")
             .replace("http", "")
-            .replace(':', "")
-            .replace('.', "")
-            .replace('/', "")
+            .replace([':', '.', '/'], "")
     }
 }
 
diff --git a/lib/src/tera_functions/mod.rs b/lib/src/tera_functions/mod.rs
index 618ff44a..04ccbd17 100644
--- a/lib/src/tera_functions/mod.rs
+++ b/lib/src/tera_functions/mod.rs
@@ -1,5 +1,3 @@
-use std::io::BufRead;
-use std::io::BufReader;
 use tera::{Function, Result, Tera, Value};
 
 pub struct ReadFileContents;
@@ -8,14 +6,8 @@ impl Function for ReadFileContents {
     fn call(&self, args: &std::collections::HashMap<String, Value>) -> Result<Value> {
         match args.get("path") {
             Some(value) => match value.as_str() {
-                Some(path) => match std::fs::File::open(path) {
-                    Ok(file) => {
-                        // This avoids reading the newline at the end of the file
-                        // https://doc.rust-lang.org/std/fs/fn.read_to_string.html reads the newline
-                        let contents = BufReader::new(file).lines().flatten().collect::<String>();
-
-                        Ok(contents.into())
-                    }
+                Some(path) => match std::fs::read_to_string(path) {
+                    Ok(content) => Ok(content.trim().into()),
                     Err(err) => Err(err.into()),
                 },
 
@@ -48,7 +40,14 @@ mod test {
 
         let mut file = tempfile::NamedTempFile::new()?;
 
-        write!(file.as_file_mut(), "FKBR KUCI SXOE")?;
+        let file_content = r#"
+FKBR
+KUCI
+SXOE
+
+"#;
+
+        write!(file.as_file_mut(), "{}", file_content)?;
 
         let template = format!(
             "{{{{ read_file_contents(path=\"{}\") }}}}",
@@ -57,7 +56,11 @@ mod test {
 
         let content = tera.render_str(&template, &Context::new())?;
 
-        assert_eq!("FKBR KUCI SXOE", content);
+        let expected_file_content = r#"FKBR
+KUCI
+SXOE"#;
+
+        assert_eq!(expected_file_content, content);
 
         Ok(())
     }


Test patch: