Skip to content

Commit 2df4572

Browse files
committed
fix: make --all-files work with sl
1 parent 0527cf0 commit 2df4572

File tree

4 files changed

+126
-12
lines changed

4 files changed

+126
-12
lines changed

src/git.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,30 @@ impl version_control::System for Repo {
145145
.collect::<Vec<AbsPath>>();
146146
Ok(filtered_files)
147147
}
148+
149+
fn get_all_files(&self, _under: Option<&AbsPath>) -> Result<Vec<AbsPath>> {
150+
let output = Command::new("git")
151+
.arg("grep")
152+
.arg("-Il")
153+
.arg(".")
154+
.current_dir(&self.root)
155+
.output()?;
156+
157+
ensure_output("git grep -Il", &output)?;
158+
159+
let files =
160+
std::str::from_utf8(&output.stdout).context("failed to parse paths_cmd output")?;
161+
let files = files
162+
.lines()
163+
.map(|s| s.to_string())
164+
.collect::<HashSet<String>>();
165+
let mut files = files.into_iter().collect::<Vec<String>>();
166+
files.sort();
167+
files
168+
.into_iter()
169+
.map(AbsPath::try_from)
170+
.collect::<Result<_>>()
171+
}
148172
}
149173

150174
pub fn get_paths_from_cmd(paths_cmd: &str) -> Result<Vec<AbsPath>> {

src/lib.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,12 @@ pub fn do_lint(
171171
return Ok(0);
172172
}
173173

174+
let config_dir = if only_lint_under_config_dir {
175+
Some(AbsPath::try_from(linters[0].get_config_dir())?)
176+
} else {
177+
None
178+
};
179+
174180
let mut files = match paths_opt {
175181
PathsOpt::Auto => {
176182
let relative_to = match revision_opt {
@@ -186,20 +192,18 @@ pub fn do_lint(
186192
PathsOpt::PathsCmd(paths_cmd) => get_paths_from_cmd(&paths_cmd)?,
187193
PathsOpt::Paths(paths) => get_paths_from_input(paths)?,
188194
PathsOpt::PathsFile(file) => get_paths_from_file(file)?,
189-
PathsOpt::AllFiles => get_paths_from_cmd("git grep -Il .")?,
195+
PathsOpt::AllFiles => repo.get_all_files(config_dir.as_ref())?,
190196
};
191197

192198
// Sort and unique the files so we pass a consistent ordering to linters
193-
files.sort();
194-
files.dedup();
195-
196-
if only_lint_under_config_dir {
197-
let config_dir = linters[0].get_config_dir();
199+
if let Some(config_dir) = config_dir {
198200
files = files
199201
.into_iter()
200-
.filter(|path| path.starts_with(config_dir))
202+
.filter(|path| path.starts_with(&config_dir))
201203
.collect();
202204
}
205+
files.sort();
206+
files.dedup();
203207

204208
let files = Arc::new(files);
205209

src/sapling.rs

Lines changed: 79 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
use crate::{log_utils, path, version_control};
1+
use crate::{
2+
log_utils,
3+
path::{self, AbsPath},
4+
version_control,
5+
};
26

37
use anyhow;
48

@@ -41,6 +45,44 @@ impl version_control::System for Repo {
4145
Ok(merge_base.to_string())
4246
}
4347

48+
fn get_all_files(&self, under: Option<&AbsPath>) -> anyhow::Result<Vec<AbsPath>> {
49+
// Output of sl status looks like:
50+
// D src/lib.rs
51+
// M foo/bar.baz
52+
let re = regex::Regex::new(r"^[A-Z?]\s+")?;
53+
54+
let mut cmd = std::process::Command::new("sl");
55+
cmd.arg("status").arg("--all");
56+
if let Some(under) = under {
57+
cmd.arg(under.as_os_str());
58+
}
59+
cmd.current_dir(&self.root);
60+
let output = cmd.output()?;
61+
log_utils::ensure_output(&format!("{:?}", cmd), &output)?;
62+
let commit_files_str = std::str::from_utf8(&output.stdout)?;
63+
let commit_files: std::collections::HashSet<String> = commit_files_str
64+
.split('\n')
65+
.map(|x| x.to_string())
66+
.map(|line| re.replace(&line, "").to_string())
67+
.filter(|line| !line.is_empty())
68+
.filter(|line| !line.starts_with('I'))
69+
.collect();
70+
71+
let filtered_commit_files = commit_files
72+
.into_iter()
73+
.map(|f| format!("{}", self.root.join(f).display()))
74+
.filter_map(|f| match path::AbsPath::try_from(&f) {
75+
Ok(abs_path) => Some(abs_path),
76+
Err(_) => {
77+
eprintln!("Failed to find file while gathering files to lint: {}", f);
78+
None
79+
}
80+
})
81+
.collect::<Vec<path::AbsPath>>();
82+
83+
Ok(filtered_commit_files)
84+
}
85+
4486
fn get_changed_files(&self, relative_to: Option<&str>) -> anyhow::Result<Vec<path::AbsPath>> {
4587
// Output of sl status looks like:
4688
// D src/lib.rs
@@ -92,7 +134,7 @@ mod tests {
92134
use std::{fs::OpenOptions, io::Write, sync::Mutex}; // 1.4.0
93135

94136
static SL_GLOBAL_MUTEX: Lazy<Mutex<()>> = Lazy::new(Mutex::default);
95-
use crate::testing;
137+
use crate::{testing, version_control::System};
96138

97139
use super::*;
98140
use anyhow::Result;
@@ -175,7 +217,6 @@ mod tests {
175217
fn changed_files(&self, relative_to: Option<&str>) -> Result<Vec<String>> {
176218
let _shared = SL_GLOBAL_MUTEX.lock().unwrap();
177219
std::env::set_current_dir(&self.root)?;
178-
use version_control::System;
179220
let repo = Repo::new()?;
180221
let files = repo.get_changed_files(relative_to)?;
181222
let files = files
@@ -188,10 +229,16 @@ mod tests {
188229
fn merge_base_with(&self, merge_base_with: &str) -> Result<String> {
189230
let _shared = SL_GLOBAL_MUTEX.lock().unwrap();
190231
std::env::set_current_dir(&self.root)?;
191-
use version_control::System;
192232
let repo = Repo::new()?;
193233
repo.get_merge_base_with(merge_base_with)
194234
}
235+
236+
fn get_all_files(&self) -> Result<Vec<AbsPath>> {
237+
let _shared = SL_GLOBAL_MUTEX.lock().unwrap();
238+
std::env::set_current_dir(&self.root)?;
239+
let repo = Repo::new()?;
240+
repo.get_all_files(None)
241+
}
195242
}
196243

197244
// Should properly detect changes in the commit (and not check other files)
@@ -374,6 +421,34 @@ mod tests {
374421
Ok(())
375422
}
376423

424+
#[test]
425+
#[cfg_attr(target_os = "windows", ignore)] // remove when sapling installation is better
426+
#[cfg_attr(target_os = "linux", ignore)] // remove when sapling installation is better
427+
fn get_all_files() -> Result<()> {
428+
let git = testing::GitCheckout::new()?;
429+
git.write_file("test_1.txt", "Initial commit")?;
430+
git.write_file("test_2.txt", "Initial commit")?;
431+
git.write_file("test_3.txt", "Initial commit")?;
432+
git.write_file("test_4.txt", "Initial commit")?;
433+
434+
git.add(".")?;
435+
git.commit("I am main")?;
436+
let sl = SaplingClone::new(&git)?;
437+
let mut all_files = sl.get_all_files()?;
438+
all_files.sort();
439+
assert_eq!(
440+
all_files,
441+
vec!(
442+
AbsPath::try_from("README")?,
443+
AbsPath::try_from("test_1.txt")?,
444+
AbsPath::try_from("test_2.txt")?,
445+
AbsPath::try_from("test_3.txt")?,
446+
AbsPath::try_from("test_4.txt")?
447+
)
448+
);
449+
Ok(())
450+
}
451+
377452
#[test]
378453
#[cfg_attr(target_os = "windows", ignore)] // remove when sapling installation is better
379454
#[cfg_attr(target_os = "linux", ignore)] // remove when sapling installation is better

src/version_control.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
use crate::{git, path, sapling};
1+
use crate::{
2+
git,
3+
path::{self, AbsPath},
4+
sapling,
5+
};
26

37
use anyhow;
48

@@ -27,6 +31,9 @@ pub trait System {
2731

2832
// Gets the files that have changed relative to the given commit.
2933
fn get_changed_files(&self, relative_to: Option<&str>) -> anyhow::Result<Vec<path::AbsPath>>;
34+
35+
// Get all files in the repo.
36+
fn get_all_files(&self, under: Option<&AbsPath>) -> anyhow::Result<Vec<AbsPath>>;
3037
}
3138

3239
impl Repo {
@@ -57,4 +64,8 @@ impl Repo {
5764
RepoImpl::Sapling(sapling) => Box::new(sapling as &dyn System),
5865
}
5966
}
67+
68+
pub fn get_all_files(&self, under: Option<&AbsPath>) -> anyhow::Result<Vec<AbsPath>> {
69+
self.get_system().get_all_files(under)
70+
}
6071
}

0 commit comments

Comments
 (0)