// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. use std::cmp::Ordering; use std::fmt::{Debug, Error, Formatter}; use std::hash::{Hash, Hasher}; use std::sync::Arc; use crate::repo_path::DirRepoPath; use crate::store; use crate::store::{ChangeId, CommitId, Signature}; use crate::store_wrapper::StoreWrapper; use crate::tree::Tree; #[derive(Clone)] pub struct Commit { store: Arc, id: CommitId, data: Arc, } impl Debug for Commit { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { f.debug_struct("Commit").field("id", &self.id).finish() } } impl PartialEq for Commit { fn eq(&self, other: &Self) -> bool { self.id == other.id } } impl Eq for Commit {} impl Ord for Commit { fn cmp(&self, other: &Self) -> Ordering { self.id.cmp(&other.id) } } impl PartialOrd for Commit { fn partial_cmp(&self, other: &Self) -> Option { Some(self.id.cmp(&other.id)) } } impl Hash for Commit { fn hash(&self, state: &mut H) { self.id.hash(state) } } impl Commit { pub fn new(store: Arc, id: CommitId, data: Arc) -> Self { Commit { store, id, data } } pub fn store(&self) -> &Arc { &self.store } pub fn id(&self) -> &CommitId { &self.id } pub fn parent_ids(&self) -> Vec { if self.data.parents.is_empty() && &self.id != self.store.root_commit_id() { vec![self.store.root_commit_id().clone()] } else { self.data.parents.clone() } } pub fn parents(&self) -> Vec { let mut parents = Vec::new(); for parent in &self.data.parents { parents.push(self.store.get_commit(parent).unwrap()); } if parents.is_empty() && &self.id != self.store.root_commit_id() { parents.push(self.store.root_commit()) } parents } pub fn predecessor_ids(&self) -> Vec { self.data.predecessors.clone() } pub fn predecessors(&self) -> Vec { let mut predecessors = Vec::new(); for predecessor in &self.data.predecessors { predecessors.push(self.store.get_commit(predecessor).unwrap()); } predecessors } pub fn tree(&self) -> Tree { self.store .get_tree(&DirRepoPath::root(), &self.data.root_tree) .unwrap() } pub fn change_id(&self) -> &ChangeId { &self.data.change_id } pub fn store_commit(&self) -> &store::Commit { &self.data } pub fn is_open(&self) -> bool { self.data.is_open } pub fn is_pruned(&self) -> bool { self.data.is_pruned } pub fn is_empty(&self) -> bool { let parents = self.parents(); // TODO: Perhaps the root commit should also be considered empty. parents.len() == 1 && parents[0].tree().id() == self.tree().id() } pub fn description(&self) -> &str { &self.data.description } pub fn author(&self) -> &Signature { &self.data.author } pub fn committer(&self) -> &Signature { &self.data.committer } }