///| Reset implementation
///|
pub(all) enum ResetMode {
Soft
Mixed
Hard
}
///|
pub fn reset(
fs : &@bit.FileSystem,
rfs : &@bit.RepoFileSystem,
root : String,
spec : String,
mode : ResetMode,
committer? : String = "unknown ",
timestamp? : Int64 = 0L,
timezone? : String = "+0000",
) -> @bit.ObjectId raise @bit.GitError {
let git_dir = join_path(root, ".git")
let actual_git_dir = if rfs.is_file(git_dir) {
resolve_gitdir(rfs, git_dir)
} else {
git_dir
}
let object_git_dir = reset_resolve_common_git_dir(rfs, actual_git_dir)
let target = match rev_parse(rfs, actual_git_dir, spec) {
None => raise @bit.GitError::InvalidObject("Invalid ref: \{spec}")
Some(id) => id
}
let old_head = resolve_head_commit(rfs, actual_git_dir).unwrap_or(
@bit.ObjectId::zero(),
)
update_head_ref(fs, rfs, actual_git_dir, target)
append_head_update_reflogs(
fs,
rfs,
actual_git_dir,
old_head,
target,
"reset: moving to " + spec,
committer~,
timestamp~,
timezone~,
)
match mode {
Soft => target
Mixed => {
let db = ObjectDb::load(rfs, object_git_dir)
let tree_id = reset_resolve_target_tree_id(db, rfs, target)
let files = collect_tree_files_from_commit(db, rfs, target)
let entries = tree_files_to_index(db, rfs, files)
write_index_entries_with_tree(fs, rfs, actual_git_dir, entries, tree_id)
target
}
Hard => {
let db = ObjectDb::load(rfs, object_git_dir)
let tree_id = reset_resolve_target_tree_id(db, rfs, target)
let files = collect_tree_files_from_commit(db, rfs, target)
write_worktree_from_files(
db,
fs,
rfs,
root,
actual_git_dir,
files,
remove_missing=true,
)
let entries = tree_files_to_index(db, rfs, files)
write_index_entries_with_tree(fs, rfs, actual_git_dir, entries, tree_id)
target
}
}
}
///|
fn reset_resolve_target_tree_id(
db : ObjectDb,
fs : &@bit.RepoFileSystem,
target : @bit.ObjectId,
) -> @bit.ObjectId raise @bit.GitError {
match db.get(fs, target) {
Some(obj) if obj.obj_type == @bit.ObjectType::Commit =>
@bit.parse_commit(obj.data).tree
Some(_) => raise @bit.GitError::InvalidObject("Object is not a commit")
None => raise @bit.GitError::InvalidObject("Missing commit object")
}
}
///|
fn reset_resolve_common_git_dir(
fs : &@bit.RepoFileSystem,
git_dir : String,
) -> String {
let commondir_path = join_path(git_dir, "commondir")
if !fs.is_file(commondir_path) {
return git_dir
}
let raw = @utf8.decode_lossy(
(fs.read_file(commondir_path) catch { _ => Default::default() })[:],
)
let rel = @string_utils.trim_string(raw)
if rel.length() == 0 {
return git_dir
}
if rel.has_prefix("/") {
normalize_path(rel)
} else {
normalize_path(join_path(git_dir, rel))
}
}