mirror of
https://github.com/martinvonz/jj.git
synced 2025-02-07 13:00:08 +00:00
91 lines
3.5 KiB
Rust
91 lines
3.5 KiB
Rust
// 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 crate::commit::Commit;
|
|
use crate::commit_builder::CommitBuilder;
|
|
use crate::repo::{MutableRepo, RepoRef};
|
|
use crate::repo_path::DirRepoPath;
|
|
use crate::settings::UserSettings;
|
|
use crate::tree::Tree;
|
|
use crate::trees::merge_trees;
|
|
|
|
pub fn merge_commit_trees(repo: RepoRef, commits: &[Commit]) -> Tree {
|
|
let store = repo.store();
|
|
if commits.is_empty() {
|
|
store
|
|
.get_tree(&DirRepoPath::root(), store.empty_tree_id())
|
|
.unwrap()
|
|
} else {
|
|
let index = repo.index();
|
|
let mut new_tree = commits[0].tree();
|
|
let commit_ids: Vec<_> = commits.iter().map(|commit| commit.id().clone()).collect();
|
|
for (i, other_commit) in commits.iter().enumerate().skip(1) {
|
|
let ancestor_ids = index.common_ancestors(&commit_ids[0..i], &[commit_ids[i].clone()]);
|
|
let ancestors: Vec<_> = ancestor_ids
|
|
.iter()
|
|
.map(|id| store.get_commit(id).unwrap())
|
|
.collect();
|
|
let ancestor_tree = merge_commit_trees(repo, &ancestors);
|
|
let new_tree_id = merge_trees(&new_tree, &ancestor_tree, &other_commit.tree()).unwrap();
|
|
new_tree = store.get_tree(&DirRepoPath::root(), &new_tree_id).unwrap();
|
|
}
|
|
new_tree
|
|
}
|
|
}
|
|
|
|
pub fn rebase_commit(
|
|
settings: &UserSettings,
|
|
mut_repo: &mut MutableRepo,
|
|
old_commit: &Commit,
|
|
new_parents: &[Commit],
|
|
) -> Commit {
|
|
let store = mut_repo.store();
|
|
let old_base_tree = merge_commit_trees(mut_repo.as_repo_ref(), &old_commit.parents());
|
|
let new_base_tree = merge_commit_trees(mut_repo.as_repo_ref(), &new_parents);
|
|
// TODO: pass in labels for the merge parts
|
|
let new_tree_id = merge_trees(&new_base_tree, &old_base_tree, &old_commit.tree()).unwrap();
|
|
let new_parent_ids = new_parents
|
|
.iter()
|
|
.map(|commit| commit.id().clone())
|
|
.collect();
|
|
CommitBuilder::for_rewrite_from(settings, store, &old_commit)
|
|
.set_parents(new_parent_ids)
|
|
.set_tree(new_tree_id)
|
|
.write_to_repo(mut_repo)
|
|
}
|
|
|
|
pub fn back_out_commit(
|
|
settings: &UserSettings,
|
|
mut_repo: &mut MutableRepo,
|
|
old_commit: &Commit,
|
|
new_parents: &[Commit],
|
|
) -> Commit {
|
|
let store = mut_repo.store();
|
|
let old_base_tree = merge_commit_trees(mut_repo.as_repo_ref(), &old_commit.parents());
|
|
let new_base_tree = merge_commit_trees(mut_repo.as_repo_ref(), &new_parents);
|
|
// TODO: pass in labels for the merge parts
|
|
let new_tree_id = merge_trees(&new_base_tree, &old_commit.tree(), &old_base_tree).unwrap();
|
|
let new_parent_ids = new_parents
|
|
.iter()
|
|
.map(|commit| commit.id().clone())
|
|
.collect();
|
|
// TODO: i18n the description based on repo language
|
|
CommitBuilder::for_new_commit(settings, store, new_tree_id)
|
|
.set_parents(new_parent_ids)
|
|
.set_description(format!(
|
|
"backout of commit {}",
|
|
hex::encode(&old_commit.id().0)
|
|
))
|
|
.write_to_repo(mut_repo)
|
|
}
|