History

adapt to changes in `gix-status`

Sebastian Thiel committed 3 years ago

Commit 54fb7c21 parent 60c948f4 files · +83 −37Browse files

Unified · Split

4 files
  1. crate-status.md +3 −1
  2. gitoxide-core/src/repository/index/entries.rs +4 −3
  3. gitoxide-core/src/repository/status.rs +74 −31
  4. gix/src/filter.rs +2 −2
crate-status.md+3−1
@@ -456,7 +456,9 @@ Make it the best-performing implementation and the most convenient one. · 455 unmodified lines
456 456
457### gix-status457### gix-status
458* [x] differences between index and worktree to turn index into worktree458* [x] differences between index and worktree to turn index into worktree
459* [ ] differences between tree and index to turn tree into index459 - [ ] rename tracking
460* [ ] differences between index and index to learn what changed
461 - [ ] rename tracking
460* [ ] untracked files462* [ ] untracked files
461* [ ] fast answer to 'is it dirty'.463* [ ] fast answer to 'is it dirty'.
462* 464*
gitoxide-core/src/repository/index/entries.rs+4−3
@@ -404,9 +404,10 @@ pub(crate) mod function { · 403 unmodified lines
404 out,404 out,
405 "{} {}{:?} {} {}{}{}",405 "{} {}{:?} {} {}{}{}",
406 match entry.flags.stage() {406 match entry.flags.stage() {
407 0 => "BASE ",407 0 => " ",
408 1 => "OURS ",408 1 => "BASE ",
409 2 => "THEIRS ",409 2 => "OURS ",
410 3 => "THEIRS ",
410 _ => "UNKNOWN",411 _ => "UNKNOWN",
411 },412 },
412 if entry.flags.is_empty() {413 if entry.flags.is_empty() {
gitoxide-core/src/repository/status.rs+74−31
@@ -5,7 +5,7 @@ use gix::index::Entry; · 4 unmodified lines
5use gix::prelude::FindExt;5use gix::prelude::FindExt;
6use gix::Progress;6use gix::Progress;
7use gix_status::index_as_worktree::traits::FastEq;7use gix_status::index_as_worktree::traits::FastEq;
8use gix_status::index_as_worktree::Change;8use gix_status::index_as_worktree::{Change, Conflict, EntryStatus};
9 9
10pub enum Submodules {10pub enum Submodules {
11 /// display all information about submodules, including ref changes, modifications and untracked files.11 /// display all information about submodules, including ref changes, modifications and untracked files.
@@ -48,23 +48,42 @@ pub fn show( · 36 unmodified lines
48 )?;48 )?;
49 let mut progress = progress.add_child("traverse index");49 let mut progress = progress.add_child("traverse index");
50 let start = std::time::Instant::now();50 let start = std::time::Instant::now();
51 let options = gix_status::index_as_worktree::Options {
52 fs: repo.filesystem_options()?,
53 thread_limit,
54 stat: repo.stat_options()?,
55 attributes: match repo
56 .attributes_only(
57 index,
58 gix::worktree::stack::state::attributes::Source::WorktreeThenIdMapping,
59 )?
60 .detach()
61 .state_mut()
62 {
63 gix::worktree::stack::State::AttributesStack(attrs) => std::mem::take(attrs),
64 // TODO: this should be nicer by creating attributes directly, but it's a private API
65 _ => unreachable!("state must be attributes stack only"),
66 },
67 };
51 gix_status::index_as_worktree(68 gix_status::index_as_worktree(
52 index,69 index,
53 repo.work_dir()70 repo.work_dir()
54 .context("This operation cannot be run on a bare repository")?,71 .context("This operation cannot be run on a bare repository")?,
55 &mut Printer(out),72 &mut Printer(out),
56 FastEq,73 FastEq,
74 Submodule,
57 {75 {
58 let odb = repo.objects.clone().into_arc()?;76 let odb = repo.objects.clone().into_arc()?;
59 move |id, buf| odb.find_blob(id, buf)77 move |id, buf| odb.find_blob(id, buf)
60 },78 },
61 &mut progress,79 &mut progress,
62 pathspec.detach()?,80 pathspec.detach()?,
63 gix_status::index_as_worktree::Options {81 repo.filter_pipeline(Some(gix::hash::ObjectId::empty_tree(repo.object_hash())))?
64 fs: repo.filesystem_options()?,82 .0
65 thread_limit,83 .into_parts()
66 stat: repo.stat_options()?,84 .0,
67 },85 &gix::interrupt::IS_INTERRUPTED,
86 options,
68 )?;87 )?;
69 88
70 writeln!(err, "\nhead -> index and untracked files aren't implemented yet")?;89 writeln!(err, "\nhead -> index and untracked files aren't implemented yet")?;
@@ -72,6 +91,18 @@ pub fn show( · 1 unmodified line
72 Ok(())91 Ok(())
73}92}
74 93
94#[derive(Clone)]
95struct Submodule;
96
97impl gix_status::index_as_worktree::traits::SubmoduleStatus for Submodule {
98 type Output = ();
99 type Error = std::convert::Infallible;
100
101 fn status(&mut self, _entry: &Entry, _rela_path: &BStr) -> Result<Option<Self::Output>, Self::Error> {
102 Ok(None)
103 }
104}
105
75struct Printer<W>(W);106struct Printer<W>(W);
76 107
77impl<'index, W> gix_status::index_as_worktree::VisitEntry<'index> for Printer<W>108impl<'index, W> gix_status::index_as_worktree::VisitEntry<'index> for Printer<W>
@@ -79,42 +110,54 @@ where · 1 unmodified line
79 W: std::io::Write,110 W: std::io::Write,
80{111{
81 type ContentChange = ();112 type ContentChange = ();
113 type SubmoduleStatus = ();
82 114
83 fn visit_entry(115 fn visit_entry(
84 &mut self,116 &mut self,
85 entry: &'index Entry,117 _entries: &'index [Entry],
118 _entry: &'index Entry,
119 _entry_index: usize,
86 rela_path: &'index BStr,120 rela_path: &'index BStr,
87 change: Option<Change<Self::ContentChange>>,121 status: EntryStatus<Self::ContentChange>,
88 conflict: bool,
89 ) {122 ) {
90 self.visit_inner(entry, rela_path, change, conflict).ok();123 self.visit_inner(rela_path, status).ok();
91 }124 }
92}125}
93 126
94impl<W: std::io::Write> Printer<W> {127impl<W: std::io::Write> Printer<W> {
95 fn visit_inner(128 fn visit_inner(&mut self, rela_path: &BStr, status: EntryStatus<()>) -> std::io::Result<()> {
96 &mut self,129 let char_storage;
97 _entry: &Entry,130 let status = match status {
98 rela_path: &BStr,131 EntryStatus::Conflict(conflict) => as_str(conflict),
99 change: Option<Change<()>>,132 EntryStatus::Change(change) => {
100 conflict: bool,133 char_storage = change_to_char(&change);
101 ) -> anyhow::Result<()> {134 std::str::from_utf8(std::slice::from_ref(&char_storage)).expect("valid ASCII")
102 if let Some(change) = conflict135 }
103 .then_some('U')136 EntryStatus::NeedsUpdate(_) => return Ok(()),
104 .or_else(|| change.as_ref().and_then(change_to_char))137 EntryStatus::IntentToAdd => "A",
105 {138 };
106 writeln!(&mut self.0, "{change} {rela_path}")?;139
107 }140 writeln!(&mut self.0, "{status: >3} {rela_path}")
108 Ok(())
109 }141 }
110}142}
111 143
112fn change_to_char(change: &Change<()>) -> Option<char> {144fn as_str(c: Conflict) -> &'static str {
145 match c {
146 Conflict::BothDeleted => "DD",
147 Conflict::AddedByUs => "AU",
148 Conflict::DeletedByThem => "UD",
149 Conflict::AddedByThem => "UA",
150 Conflict::DeletedByUs => "DU",
151 Conflict::BothAdded => "AA",
152 Conflict::BothModified => "UU",
153 }
154}
155
156fn change_to_char(change: &Change<()>) -> u8 {
113 // Known status letters: https://github.com/git/git/blob/6807fcfedab84bc8cd0fbf721bc13c4e68cda9ae/diff.h#L613157 // Known status letters: https://github.com/git/git/blob/6807fcfedab84bc8cd0fbf721bc13c4e68cda9ae/diff.h#L613
114 Some(match change {158 match change {
115 Change::Removed => 'D',159 Change::Removed => b'D',
116 Change::Type => 'T',160 Change::Type => b'T',
117 Change::Modification { .. } => 'M',161 Change::SubmoduleModification(_) | Change::Modification { .. } => b'M',
118 Change::IntentToAdd => return None,162 }
119 })
120}163}
gix/src/filter.rs+2−2
@@ -150,8 +150,8 @@ impl<'repo> Pipeline<'repo> { · 149 unmodified lines
150 &mut |_, attrs| {150 &mut |_, attrs| {
151 entry.matching_attributes(attrs);151 entry.matching_attributes(attrs);
152 },152 },
153 &mut |rela_path, buf| -> Result<_, gix_odb::find::Error> {153 &mut |buf| -> Result<_, gix_odb::find::Error> {
154 let entry = match index.entry_by_path(rela_path) {154 let entry = match index.entry_by_path(gix_path::into_bstr(rela_path).as_ref()) {
155 None => return Ok(None),155 None => return Ok(None),
156 Some(entry) => entry,156 Some(entry) => entry,
157 };157 };