Skip to content

Commit 8f3f358

Browse files
committed
Merge branch 'gix-submodule'
2 parents c35ddab + fc0529e commit 8f3f358

File tree

87 files changed

+609
-384
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

87 files changed

+609
-384
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,10 @@ members = [
281281

282282
"gix-diff/tests",
283283
"gix-pack/tests",
284+
"gix-odb/tests",
285+
"gix-worktree-state/tests",
286+
"gix-status/tests",
287+
"gix-worktree/tests",
284288
"gix-index/tests",
285289
"gix-ref/tests",
286290
"gix-config/tests",

gitoxide-core/src/repository/index/entries.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,11 @@ pub(crate) mod function {
4848
recurse_submodules,
4949
}: Options,
5050
) -> anyhow::Result<()> {
51-
use crate::OutputFormat::*;
5251
let mut out = BufWriter::with_capacity(64 * 1024, out);
5352
let mut all_attrs = statistics.then(BTreeSet::new);
5453

5554
#[cfg(feature = "serde")]
56-
if let Json = format {
55+
if let OutputFormat::Json = format {
5756
out.write_all(b"[\n")?;
5857
}
5958

@@ -70,13 +69,14 @@ pub(crate) mod function {
7069
)?;
7170

7271
#[cfg(feature = "serde")]
73-
if format == Json {
72+
if format == OutputFormat::Json {
7473
out.write_all(b"]\n")?;
7574
out.flush()?;
7675
if statistics {
7776
serde_json::to_writer_pretty(&mut err, &stats)?;
7877
}
79-
} else if format == Human && statistics {
78+
}
79+
if format == OutputFormat::Human && statistics {
8080
out.flush()?;
8181
writeln!(err, "{stats:#?}")?;
8282
if let Some(attrs) = all_attrs.filter(|a| !a.is_empty()) {
@@ -101,7 +101,9 @@ pub(crate) mod function {
101101
recurse_submodules: bool,
102102
out: &mut impl std::io::Write,
103103
) -> anyhow::Result<Statistics> {
104+
let _span = gix::trace::coarse!("print_entries()", git_dir = ?repo.git_dir());
104105
let (mut pathspec, index, mut cache) = init_cache(repo, attributes, pathspecs.clone())?;
106+
let mut repo_attrs = all_attrs.is_some().then(BTreeSet::default);
105107
let submodules_by_path = recurse_submodules
106108
.then(|| {
107109
repo.submodules()
@@ -142,7 +144,7 @@ pub(crate) mod function {
142144
};
143145
stats.with_attributes += usize::from(!attributes.is_empty());
144146
stats.max_attributes_per_path = stats.max_attributes_per_path.max(attributes.len());
145-
if let Some(attrs) = all_attrs.as_deref_mut() {
147+
if let Some(attrs) = repo_attrs.as_mut() {
146148
attributes.iter().for_each(|attr| {
147149
attrs.insert(attr.clone());
148150
});
@@ -232,6 +234,12 @@ pub(crate) mod function {
232234
}
233235

234236
stats.cache = cache.map(|c| *c.1.statistics());
237+
if let Some((attrs, all_attrs)) = repo_attrs.zip(all_attrs) {
238+
stats
239+
.attributes
240+
.extend(attrs.iter().map(|attr| attr.as_ref().to_string()));
241+
all_attrs.extend(attrs);
242+
}
235243
Ok(stats)
236244
}
237245

@@ -301,6 +309,7 @@ pub(crate) mod function {
301309
pub with_attributes: usize,
302310
pub max_attributes_per_path: usize,
303311
pub cache: Option<gix::worktree::stack::Statistics>,
312+
pub attributes: Vec<String>,
304313
pub submodule: Vec<(BString, Statistics)>,
305314
}
306315

gitoxide-core/src/repository/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,6 @@ pub mod mailmap;
4040
pub mod odb;
4141
pub mod remote;
4242
pub mod revision;
43+
pub mod submodule;
4344
pub mod tree;
4445
pub mod verify;
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
use crate::OutputFormat;
2+
use anyhow::bail;
3+
use gix::commit::describe::SelectRef;
4+
use gix::prelude::ObjectIdExt;
5+
use gix::{Repository, Submodule};
6+
7+
pub fn list(repo: Repository, mut out: impl std::io::Write, format: OutputFormat) -> anyhow::Result<()> {
8+
if format != OutputFormat::Human {
9+
bail!("Only human output is supported for now")
10+
}
11+
12+
let Some(submodules) = repo.submodules()? else { return Ok(()) };
13+
for sm in submodules {
14+
print_sm(sm, &mut out)?;
15+
}
16+
Ok(())
17+
}
18+
19+
fn print_sm(sm: Submodule<'_>, out: &mut impl std::io::Write) -> anyhow::Result<()> {
20+
let _span = gix::trace::coarse!("print_sm", path = ?sm.path());
21+
let state = sm.state()?;
22+
let mut sm_repo = sm.open()?;
23+
if let Some(repo) = sm_repo.as_mut() {
24+
repo.object_cache_size_if_unset(4 * 1024 * 1024);
25+
};
26+
writeln!(
27+
out,
28+
" {is_active} {path} {config} head:{head_id} index:{index_id} ({worktree}) [{url}]",
29+
is_active = if !sm.is_active()? || !state.repository_exists {
30+
"ⅹ"
31+
} else {
32+
"✓"
33+
},
34+
path = sm.path()?,
35+
config = if state.superproject_configuration {
36+
"config:yes"
37+
} else {
38+
"config:no"
39+
},
40+
head_id = submodule_short_hash(sm.head_id()?, sm_repo.as_ref()),
41+
index_id = submodule_short_hash(sm.index_id()?, sm_repo.as_ref()),
42+
worktree = match sm_repo {
43+
Some(repo) => {
44+
// TODO(name-revision): this is the simple version, `git` gives it
45+
// multiple tries https://github.com/git/git/blob/fac96dfbb1c24369ba7d37a5affd8adfe6c650fd/builtin/submodule--helper.c#L161
46+
// and even uses `git name-rev`/`git describe --contains` which we can't do yet.
47+
repo.head_commit()?
48+
.describe()
49+
.names(SelectRef::AllRefs)
50+
.format()?
51+
.to_string()
52+
}
53+
None => {
54+
"no worktree".to_string()
55+
}
56+
},
57+
url = sm.url()?.to_bstring()
58+
)?;
59+
Ok(())
60+
}
61+
62+
fn submodule_short_hash(id: Option<gix::ObjectId>, repo: Option<&Repository>) -> String {
63+
id.map_or_else(
64+
|| "none".to_string(),
65+
|id| repo.map_or_else(|| id.to_string(), |repo| id.attach(repo).shorten_or_id().to_string()),
66+
)
67+
}

0 commit comments

Comments
 (0)