just playing with tangled
1// Copyright 2020 The Jujutsu Authors
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
15#![allow(missing_docs)]
16
17use std::sync::Arc;
18
19use crate::backend::{self, BackendResult, ChangeId, CommitId, Signature, TreeId};
20use crate::commit::Commit;
21use crate::conflicts::Conflict;
22use crate::repo::{MutableRepo, Repo};
23use crate::settings::{JJRng, UserSettings};
24
25#[must_use]
26pub struct CommitBuilder<'repo> {
27 mut_repo: &'repo mut MutableRepo,
28 rng: Arc<JJRng>,
29 commit: backend::Commit,
30 rewrite_source: Option<Commit>,
31}
32
33impl CommitBuilder<'_> {
34 pub fn for_new_commit<'repo>(
35 mut_repo: &'repo mut MutableRepo,
36 settings: &UserSettings,
37 parents: Vec<CommitId>,
38 tree_id: TreeId,
39 ) -> CommitBuilder<'repo> {
40 let signature = settings.signature();
41 assert!(!parents.is_empty());
42 let rng = settings.get_rng();
43 let change_id = rng.new_change_id(mut_repo.store().change_id_length());
44 let commit = backend::Commit {
45 parents,
46 predecessors: vec![],
47 // TODO(#1624): set this when appropriate
48 root_tree: Conflict::from_legacy_tree_id(tree_id),
49 uses_tree_conflict_format: false,
50 change_id,
51 description: String::new(),
52 author: signature.clone(),
53 committer: signature,
54 };
55 CommitBuilder {
56 mut_repo,
57 rng,
58 commit,
59 rewrite_source: None,
60 }
61 }
62
63 pub fn for_rewrite_from<'repo>(
64 mut_repo: &'repo mut MutableRepo,
65 settings: &UserSettings,
66 predecessor: &Commit,
67 ) -> CommitBuilder<'repo> {
68 let mut commit = predecessor.store_commit().clone();
69 commit.predecessors = vec![predecessor.id().clone()];
70 commit.committer = settings.signature();
71 // If the user had not configured a name and email before but now they have,
72 // update the author fields with the new information.
73 if commit.author.name == UserSettings::user_name_placeholder() {
74 commit.author.name = commit.committer.name.clone();
75 }
76 if commit.author.email == UserSettings::user_email_placeholder() {
77 commit.author.email = commit.committer.email.clone();
78 }
79 CommitBuilder {
80 mut_repo,
81 commit,
82 rng: settings.get_rng(),
83 rewrite_source: Some(predecessor.clone()),
84 }
85 }
86
87 pub fn parents(&self) -> &[CommitId] {
88 &self.commit.parents
89 }
90
91 pub fn set_parents(mut self, parents: Vec<CommitId>) -> Self {
92 assert!(!parents.is_empty());
93 self.commit.parents = parents;
94 self
95 }
96
97 pub fn predecessors(&self) -> &[CommitId] {
98 &self.commit.predecessors
99 }
100
101 pub fn set_predecessors(mut self, predecessors: Vec<CommitId>) -> Self {
102 self.commit.predecessors = predecessors;
103 self
104 }
105
106 pub fn tree(&self) -> &TreeId {
107 self.commit.root_tree.as_legacy_tree_id()
108 }
109
110 pub fn set_tree(mut self, tree_id: TreeId) -> Self {
111 self.commit.root_tree = Conflict::from_legacy_tree_id(tree_id);
112 self
113 }
114
115 pub fn change_id(&self) -> &ChangeId {
116 &self.commit.change_id
117 }
118
119 pub fn set_change_id(mut self, change_id: ChangeId) -> Self {
120 self.commit.change_id = change_id;
121 self
122 }
123
124 pub fn generate_new_change_id(mut self) -> Self {
125 self.commit.change_id = self
126 .rng
127 .new_change_id(self.mut_repo.store().change_id_length());
128 self
129 }
130
131 pub fn description(&self) -> &str {
132 &self.commit.description
133 }
134
135 pub fn set_description(mut self, description: impl Into<String>) -> Self {
136 self.commit.description = description.into();
137 self
138 }
139
140 pub fn author(&self) -> &Signature {
141 &self.commit.author
142 }
143
144 pub fn set_author(mut self, author: Signature) -> Self {
145 self.commit.author = author;
146 self
147 }
148
149 pub fn committer(&self) -> &Signature {
150 &self.commit.committer
151 }
152
153 pub fn set_committer(mut self, committer: Signature) -> Self {
154 self.commit.committer = committer;
155 self
156 }
157
158 pub fn write(self) -> BackendResult<Commit> {
159 let mut rewrite_source_id = None;
160 if let Some(rewrite_source) = self.rewrite_source {
161 if *rewrite_source.change_id() == self.commit.change_id {
162 rewrite_source_id.replace(rewrite_source.id().clone());
163 }
164 }
165 let commit = self.mut_repo.write_commit(self.commit)?;
166 if let Some(rewrite_source_id) = rewrite_source_id {
167 self.mut_repo
168 .record_rewritten_commit(rewrite_source_id, commit.id().clone())
169 }
170 Ok(commit)
171 }
172}