1use std::cmp::Ordering;
16use std::fmt::{Debug, Error, Formatter};
17use std::hash::{Hash, Hasher};
18use std::sync::Arc;
19
20use crate::repo_path::DirRepoPath;
21use crate::store;
22use crate::store::{ChangeId, CommitId, Signature};
23use crate::store_wrapper::StoreWrapper;
24use crate::tree::Tree;
25
26#[derive(Clone)]
27pub struct Commit {
28 store: Arc<StoreWrapper>,
29 id: CommitId,
30 data: Arc<store::Commit>,
31}
32
33impl Debug for Commit {
34 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
35 f.debug_struct("Commit").field("id", &self.id).finish()
36 }
37}
38
39impl PartialEq for Commit {
40 fn eq(&self, other: &Self) -> bool {
41 self.id == other.id
42 }
43}
44
45impl Eq for Commit {}
46
47impl Ord for Commit {
48 fn cmp(&self, other: &Self) -> Ordering {
49 self.id.cmp(&other.id)
50 }
51}
52
53impl PartialOrd for Commit {
54 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
55 Some(self.id.cmp(&other.id))
56 }
57}
58
59impl Hash for Commit {
60 fn hash<H: Hasher>(&self, state: &mut H) {
61 self.id.hash(state)
62 }
63}
64
65impl Commit {
66 pub fn new(store: Arc<StoreWrapper>, id: CommitId, data: Arc<store::Commit>) -> Self {
67 Commit { store, id, data }
68 }
69
70 pub fn store(&self) -> &Arc<StoreWrapper> {
71 &self.store
72 }
73
74 pub fn id(&self) -> &CommitId {
75 &self.id
76 }
77
78 pub fn parent_ids(&self) -> Vec<CommitId> {
79 if self.data.parents.is_empty() && &self.id != self.store.root_commit_id() {
80 vec![self.store.root_commit_id().clone()]
81 } else {
82 self.data.parents.clone()
83 }
84 }
85
86 pub fn parents(&self) -> Vec<Commit> {
87 let mut parents = Vec::new();
88 for parent in &self.data.parents {
89 parents.push(self.store.get_commit(parent).unwrap());
90 }
91 if parents.is_empty() && &self.id != self.store.root_commit_id() {
92 parents.push(self.store.root_commit())
93 }
94 parents
95 }
96
97 pub fn predecessor_ids(&self) -> Vec<CommitId> {
98 self.data.predecessors.clone()
99 }
100
101 pub fn predecessors(&self) -> Vec<Commit> {
102 let mut predecessors = Vec::new();
103 for predecessor in &self.data.predecessors {
104 predecessors.push(self.store.get_commit(predecessor).unwrap());
105 }
106 predecessors
107 }
108
109 pub fn tree(&self) -> Tree {
110 self.store
111 .get_tree(&DirRepoPath::root(), &self.data.root_tree)
112 .unwrap()
113 }
114
115 pub fn change_id(&self) -> &ChangeId {
116 &self.data.change_id
117 }
118
119 pub fn store_commit(&self) -> &store::Commit {
120 &self.data
121 }
122
123 pub fn is_open(&self) -> bool {
124 self.data.is_open
125 }
126
127 pub fn is_pruned(&self) -> bool {
128 self.data.is_pruned
129 }
130
131 pub fn is_empty(&self) -> bool {
132 let parents = self.parents();
133 parents.len() == 1 && parents[0].tree().id() == self.tree().id()
135 }
136
137 pub fn description(&self) -> &str {
138 &self.data.description
139 }
140
141 pub fn author(&self) -> &Signature {
142 &self.data.author
143 }
144
145 pub fn committer(&self) -> &Signature {
146 &self.data.committer
147 }
148}