Echo Writes Code

git.rs

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
use crate::errors::{ Result, Error };

use std::fs;
use std::path::{ PathBuf };

pub struct GitRoot {
	path: PathBuf,
}

impl GitRoot {
	pub fn open(path: &std::path::Path) -> Result<GitRoot> {
		match fs::read_dir(path) {
			Ok(_) => Ok(GitRoot { path: path.to_path_buf() }),
			Err(e) => Err(Error::InvalidGitRoot(e)),
		}
	}

	pub fn repositories(&self) -> Result<Vec<Repository>> {
		let mut repositories = Vec::new();

		for entry in fs::read_dir(&self.path)? {
			let repo_path = entry?.path();

			if !repo_path.is_dir() {
				tracing::debug!("{} is not a directory", repo_path.display());
				continue;
			}

			if repo_path.extension() != Some(std::ffi::OsStr::new("git")) {
				tracing::debug!("{} is not a git repository", repo_path.display());
				continue;
			}

			let Some(repo_name) = repo_path.file_stem() else {
				tracing::debug!("{} doesn't have a file stem", repo_path.display());
				continue;
			};

			let Some(repo_name) = repo_name.to_str() else {
				tracing::debug!("{} isn't valid UTF-8", repo_path.display());
				continue;
			};

			tracing::debug!("Found git repository {} at {}", repo_name, repo_path.display());
			let repository = Repository::new(repo_name.to_string(), repo_path);
			repositories.push(repository);
		}

		Ok(repositories)
	}
}

pub struct Repository {
	name: String,
	path: PathBuf,
}

impl Repository {
	pub fn new(name: String, path: PathBuf) -> Repository {
		Repository {
			name,
			path,
		}
	}

	pub fn name(&self) -> String {
		self.name.clone()
	}

	pub fn path(&self) -> PathBuf {
		self.path.clone()
	}
}