1use crate::git::error::{GitError, git_output};
15use anyhow::{Context, Result};
16use std::fs;
17use std::path::Path;
18
19pub fn has_lfs(repo_root: &Path) -> Result<bool> {
20 let git_lfs_dir = repo_root.join(".git/lfs");
21 if git_lfs_dir.is_dir() {
22 return Ok(true);
23 }
24
25 let gitattributes = repo_root.join(".gitattributes");
26 if gitattributes.is_file() {
27 let content = fs::read_to_string(&gitattributes)
28 .with_context(|| format!("read .gitattributes in {}", repo_root.display()))?;
29 return Ok(content.contains("filter=lfs"));
30 }
31
32 Ok(false)
33}
34
35pub fn list_lfs_files(repo_root: &Path) -> Result<Vec<String>> {
36 let output = git_output(repo_root, &["lfs", "ls-files"])
37 .with_context(|| format!("run git lfs ls-files in {}", repo_root.display()))?;
38
39 if !output.status.success() {
40 let stderr = String::from_utf8_lossy(&output.stderr);
41 if stderr.contains("not a git lfs repository")
42 || stderr.contains("git: lfs is not a git command")
43 {
44 return Ok(Vec::new());
45 }
46 return Err(GitError::CommandFailed {
47 args: "lfs ls-files".to_string(),
48 code: output.status.code(),
49 stderr: stderr.trim().to_string(),
50 }
51 .into());
52 }
53
54 let stdout = String::from_utf8_lossy(&output.stdout);
55 let mut files = Vec::new();
56 for line in stdout.lines() {
57 if let Some((_, path)) = line.rsplit_once(" * ") {
58 files.push(path.to_string());
59 }
60 }
61 Ok(files)
62}