jujube_lib/
commit.rs

1// Copyright 2020 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use 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        // TODO: Perhaps the root commit should also be considered empty.
134        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}