Skip to content
This repository was archived by the owner on Apr 14, 2025. It is now read-only.

Commit 5d7a92e

Browse files
committed
#7 add list of modified, untracked, renamed, deleted, added
1 parent 5e69e45 commit 5d7a92e

4 files changed

Lines changed: 86 additions & 117 deletions

File tree

Cargo.lock

Lines changed: 0 additions & 93 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ gtmpl_value= "^0.3"
2727
structopt = "0.2"
2828
git2 = { version = "^0.7", features = [], default-features = false }
2929
regex = "1.0.1"
30-
failure = ""
3130

3231
[dev-dependencies]
3332
spectral = "0.6.0"

src/lib.rs

Lines changed: 85 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ extern crate walkdir;
1212
#[macro_use]
1313
extern crate spectral;
1414

15+
use git2::{Remote, Repository, Status, StatusOptions};
1516
use gtmpl::Func;
1617
use gtmpl::Value;
1718
use regex::Regex;
@@ -27,8 +28,9 @@ pub struct Ctx {
2728
#[derive(Clone, Gtmpl)]
2829
pub struct GitRepo {
2930
path: Location,
30-
//repo: git2::Repository
31+
//repo: git2::Repository,
3132
remotes: Func,
33+
working_paths: Func,
3234
}
3335

3436
#[derive(Debug, Clone, Gtmpl)]
@@ -45,7 +47,17 @@ pub struct RemoteData {
4547
url_path: String,
4648
}
4749

48-
fn find_remotes(args: &[Value]) -> Result<Value, String> {
50+
#[derive(Debug, Clone, Gtmpl)]
51+
pub struct WorkingPaths {
52+
untracked: Vec<String>,
53+
modified: Vec<String>,
54+
deleted: Vec<String>,
55+
added: Vec<String>,
56+
renamed: Vec<String>,
57+
conflicted: Vec<String>,
58+
}
59+
60+
fn find_repo(args: &[Value]) -> Result<Repository, String> {
4961
if let Value::Object(ref o) = &args[0] {
5062
let full = o.get("path")
5163
.and_then(|v| {
@@ -56,29 +68,79 @@ fn find_remotes(args: &[Value]) -> Result<Value, String> {
5668
}
5769
})
5870
.ok_or("path.full not empty")?;
59-
let mut remotes = HashMap::new();
60-
let repo = git2::Repository::open(Path::new(&full)).unwrap();
61-
repo.remotes()
62-
.unwrap()
63-
.iter()
64-
.filter_map(|x| {
65-
x.and_then(|name| {
66-
repo.find_remote(name)
67-
.map(|remote| RemoteData::from(remote))
68-
.ok()
69-
})
70-
})
71-
//.collect::<Vec<_>>()
72-
//.into_iter()
73-
.for_each(|rd| {
74-
remotes.insert(rd.name.clone(), rd);
75-
});
76-
Ok(remotes.into())
71+
let repo = Repository::open(Path::new(&full)).unwrap();
72+
Ok(repo)
7773
} else {
7874
Err(format!("GitRepo required, got: {:?}", args))
7975
}
8076
}
8177

78+
fn find_remotes(args: &[Value]) -> Result<Value, String> {
79+
let repo = find_repo(args)?;
80+
let mut remotes = HashMap::new();
81+
repo.remotes()
82+
.unwrap()
83+
.iter()
84+
.filter_map(|x| {
85+
x.and_then(|name| {
86+
repo.find_remote(name)
87+
.map(|remote| RemoteData::from(remote))
88+
.ok()
89+
})
90+
})
91+
//.collect::<Vec<_>>()
92+
//.into_iter()
93+
.for_each(|rd| {
94+
remotes.insert(rd.name.clone(), rd);
95+
});
96+
Ok(remotes.into())
97+
}
98+
99+
fn find_working_paths(args: &[Value]) -> Result<Value, String> {
100+
let repo = find_repo(args)?;
101+
let mut opts = StatusOptions::new();
102+
opts.include_untracked(true);
103+
let statuses = repo.statuses(Some(&mut opts))
104+
.map_err(|e| format!("{}", e))?;
105+
let mut untracked = vec![];
106+
let mut modified = vec![];
107+
let mut added = vec![];
108+
let mut deleted = vec![];
109+
let mut renamed = vec![];
110+
let mut conflicted = vec![];
111+
for entry in statuses.iter() {
112+
if let Some(path) = entry.path() {
113+
//eprintln!("path : {} {:?}", path, entry.status());
114+
let status = entry.status();
115+
if status.intersects(Status::INDEX_MODIFIED) || status.intersects(Status::WT_MODIFIED) {
116+
modified.push(path.to_owned());
117+
}
118+
if status.intersects(Status::INDEX_NEW) {
119+
added.push(path.to_owned())
120+
}
121+
if status.intersects(Status::WT_NEW) {
122+
untracked.push(path.to_owned())
123+
}
124+
if status.intersects(Status::INDEX_DELETED) || status.intersects(Status::WT_DELETED) {
125+
deleted.push(path.to_owned())
126+
}
127+
if status.intersects(Status::INDEX_RENAMED) || status.intersects(Status::WT_RENAMED) {
128+
renamed.push(path.to_owned())
129+
}
130+
if status.intersects(Status::CONFLICTED) {
131+
conflicted.push(path.to_owned())
132+
}
133+
}
134+
}
135+
Ok(WorkingPaths {
136+
untracked,
137+
modified,
138+
added,
139+
deleted,
140+
renamed,
141+
conflicted,
142+
}.into())
143+
}
82144
impl<'a> From<&'a Path> for GitRepo {
83145
//TODO manage result & error
84146
fn from(path: &Path) -> Self {
@@ -91,12 +153,13 @@ impl<'a> From<&'a Path> for GitRepo {
91153
.unwrap(),
92154
},
93155
remotes: find_remotes,
156+
working_paths: find_working_paths,
94157
}
95158
}
96159
}
97160

98-
impl<'b> From<git2::Remote<'b>> for RemoteData {
99-
fn from(v: git2::Remote) -> Self {
161+
impl<'b> From<Remote<'b>> for RemoteData {
162+
fn from(v: Remote) -> Self {
100163
// let host = url_parsed.host_str().unwrap_or("").to_owned();
101164
// let path = url_parsed.path().to_owned();
102165
let (host, path) = v.url()

src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ struct Cmd {
2727
#[structopt(
2828
short = "t",
2929
long = "tmpl",
30-
default_value = "{{ .path.file_name }}\t{{ .path.full }}\t{{with .remotes.origin}} {{ .name }} {{.url_full}} {{end}}"
30+
default_value = "{{with .working_paths}}{{if .conflicted}}C{{else}} {{end}}{{if .modified}}M{{else}}{{if .added}}M{{else}}{{if .deleted}}M{{else}}{{if .renamed}}M{{else}} {{end}}{{end}}{{end}}{{end}}{{if .untracked}}U{{else}} {{end}}{{end}}\t{{ .path.file_name }}\t{{ .path.full }}\t{{with .remotes.origin}} {{ .name }} {{.url_full}} {{end}}"
3131
)]
3232
format: String,
3333

0 commit comments

Comments
 (0)