jujube_lib/
commit_builder.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 uuid::Uuid;
16
17use crate::commit::Commit;
18use crate::repo::ReadonlyRepo;
19use crate::settings::UserSettings;
20use crate::store;
21use crate::store::{ChangeId, CommitId, Signature, Timestamp, TreeId};
22use crate::store_wrapper::StoreWrapper;
23use crate::transaction::Transaction;
24use std::sync::Arc;
25
26#[derive(Debug)]
27pub struct CommitBuilder {
28    store: Arc<StoreWrapper>,
29    commit: store::Commit,
30}
31
32pub fn new_change_id() -> ChangeId {
33    ChangeId(Uuid::new_v4().as_bytes().to_vec())
34}
35pub fn signature(settings: &UserSettings) -> Signature {
36    // TODO: check if it's slow to get the timezone etc for every signature
37    let timestamp = Timestamp::now();
38    Signature {
39        name: settings.user_name(),
40        email: settings.user_email(),
41        timestamp,
42    }
43}
44
45impl CommitBuilder {
46    pub fn for_new_commit(
47        settings: &UserSettings,
48        store: &Arc<StoreWrapper>,
49        tree_id: TreeId,
50    ) -> CommitBuilder {
51        let signature = signature(settings);
52        let commit = store::Commit {
53            parents: vec![],
54            predecessors: vec![],
55            root_tree: tree_id,
56            change_id: new_change_id(),
57            description: String::new(),
58            author: signature.clone(),
59            committer: signature,
60            is_open: false,
61            is_pruned: false,
62        };
63        CommitBuilder {
64            store: store.clone(),
65            commit,
66        }
67    }
68
69    pub fn for_rewrite_from(
70        settings: &UserSettings,
71        store: &Arc<StoreWrapper>,
72        predecessor: &Commit,
73    ) -> CommitBuilder {
74        let mut commit = predecessor.store_commit().clone();
75        commit.predecessors = vec![predecessor.id().clone()];
76        commit.committer = signature(settings);
77        CommitBuilder {
78            store: store.clone(),
79            commit,
80        }
81    }
82
83    pub fn for_open_commit(
84        settings: &UserSettings,
85        store: &Arc<StoreWrapper>,
86        parent_id: CommitId,
87        tree_id: TreeId,
88    ) -> CommitBuilder {
89        let signature = signature(settings);
90        let commit = store::Commit {
91            parents: vec![parent_id],
92            predecessors: vec![],
93            root_tree: tree_id,
94            change_id: new_change_id(),
95            description: String::new(),
96            author: signature.clone(),
97            committer: signature,
98            is_open: true,
99            is_pruned: false,
100        };
101        CommitBuilder {
102            store: store.clone(),
103            commit,
104        }
105    }
106
107    pub fn set_parents(mut self, parents: Vec<CommitId>) -> Self {
108        self.commit.parents = parents;
109        self
110    }
111
112    pub fn set_predecessors(mut self, predecessors: Vec<CommitId>) -> Self {
113        self.commit.predecessors = predecessors;
114        self
115    }
116
117    pub fn set_tree(mut self, tree_id: TreeId) -> Self {
118        self.commit.root_tree = tree_id;
119        self
120    }
121
122    pub fn set_change_id(mut self, change_id: ChangeId) -> Self {
123        self.commit.change_id = change_id;
124        self
125    }
126
127    pub fn generate_new_change_id(mut self) -> Self {
128        self.commit.change_id = new_change_id();
129        self
130    }
131
132    pub fn set_description(mut self, description: String) -> Self {
133        self.commit.description = description;
134        self
135    }
136
137    pub fn set_open(mut self, is_open: bool) -> Self {
138        self.commit.is_open = is_open;
139        self
140    }
141
142    pub fn set_pruned(mut self, is_pruned: bool) -> Self {
143        self.commit.is_pruned = is_pruned;
144        self
145    }
146
147    pub fn set_author(mut self, author: Signature) -> Self {
148        self.commit.author = author;
149        self
150    }
151
152    pub fn set_committer(mut self, committer: Signature) -> Self {
153        self.commit.committer = committer;
154        self
155    }
156
157    pub fn write_to_new_transaction(self, repo: &ReadonlyRepo, description: &str) -> Commit {
158        let mut tx = repo.start_transaction(description);
159        let commit = self.write_to_transaction(&mut tx);
160        tx.commit();
161        commit
162    }
163
164    pub fn write_to_transaction(mut self, tx: &mut Transaction) -> Commit {
165        let parents = &mut self.commit.parents;
166        if parents.contains(self.store.root_commit_id()) {
167            assert_eq!(parents.len(), 1);
168            parents.clear();
169        }
170        tx.write_commit(self.commit)
171    }
172}