Merge branch 'pw/gc-during-rebase'
The sequencer machinery does not use the ref API and instead records names of certain objects it needs for its correct operation in temporary files, which makes these objects susceptible to loss by garbage collection. These temporary files have been added as starting points for reachability analysis to fix this. * pw/gc-during-rebase: prune: mark rebase autostash and orig-head as reachable
This commit is contained in:
50
reachable.c
50
reachable.c
@ -17,6 +17,7 @@
|
||||
#include "pack-mtimes.h"
|
||||
#include "config.h"
|
||||
#include "run-command.h"
|
||||
#include "sequencer.h"
|
||||
|
||||
struct connectivity_progress {
|
||||
struct progress *progress;
|
||||
@ -30,6 +31,52 @@ static void update_progress(struct connectivity_progress *cp)
|
||||
display_progress(cp->progress, cp->count);
|
||||
}
|
||||
|
||||
static void add_one_file(const char *path, struct rev_info *revs)
|
||||
{
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
struct object_id oid;
|
||||
struct object *object;
|
||||
|
||||
if (!read_oneliner(&buf, path, READ_ONELINER_SKIP_IF_EMPTY)) {
|
||||
strbuf_release(&buf);
|
||||
return;
|
||||
}
|
||||
strbuf_trim(&buf);
|
||||
if (!get_oid_hex(buf.buf, &oid)) {
|
||||
object = parse_object_or_die(&oid, buf.buf);
|
||||
add_pending_object(revs, object, "");
|
||||
}
|
||||
strbuf_release(&buf);
|
||||
}
|
||||
|
||||
/* Mark objects recorded in rebase state files as reachable. */
|
||||
static void add_rebase_files(struct rev_info *revs)
|
||||
{
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
size_t len;
|
||||
const char *path[] = {
|
||||
"rebase-apply/autostash",
|
||||
"rebase-apply/orig-head",
|
||||
"rebase-merge/autostash",
|
||||
"rebase-merge/orig-head",
|
||||
};
|
||||
struct worktree **worktrees = get_worktrees();
|
||||
|
||||
for (struct worktree **wt = worktrees; *wt; wt++) {
|
||||
strbuf_reset(&buf);
|
||||
strbuf_addstr(&buf, get_worktree_git_dir(*wt));
|
||||
strbuf_complete(&buf, '/');
|
||||
len = buf.len;
|
||||
for (size_t i = 0; i < ARRAY_SIZE(path); i++) {
|
||||
strbuf_setlen(&buf, len);
|
||||
strbuf_addstr(&buf, path[i]);
|
||||
add_one_file(buf.buf, revs);
|
||||
}
|
||||
}
|
||||
strbuf_release(&buf);
|
||||
free_worktrees(worktrees);
|
||||
}
|
||||
|
||||
static int add_one_ref(const char *path, const struct object_id *oid,
|
||||
int flag, void *cb_data)
|
||||
{
|
||||
@ -322,6 +369,9 @@ void mark_reachable_objects(struct rev_info *revs, int mark_reflog,
|
||||
head_ref(add_one_ref, revs);
|
||||
other_head_refs(add_one_ref, revs);
|
||||
|
||||
/* rebase autostash and orig-head */
|
||||
add_rebase_files(revs);
|
||||
|
||||
/* Add all reflog info */
|
||||
if (mark_reflog)
|
||||
add_reflogs_to_pending(revs, 0);
|
||||
|
@ -40,9 +40,24 @@ testrebase() {
|
||||
test_path_is_missing "$state_dir"
|
||||
'
|
||||
|
||||
test_expect_success "pre rebase$type head is marked as reachable" '
|
||||
# Clean up the state from the previous one
|
||||
git checkout -f --detach pre-rebase &&
|
||||
test_tick &&
|
||||
git commit --amend --only -m "reworded" &&
|
||||
orig_head=$(git rev-parse HEAD) &&
|
||||
test_must_fail git rebase$type main &&
|
||||
# Stop ORIG_HEAD marking $state_dir/orig-head as reachable
|
||||
git update-ref -d ORIG_HEAD &&
|
||||
git reflog expire --expire="$GIT_COMMITTER_DATE" --all &&
|
||||
git prune --expire=now &&
|
||||
git rebase --abort &&
|
||||
test_cmp_rev $orig_head HEAD
|
||||
'
|
||||
|
||||
test_expect_success "rebase$type --abort after --skip" '
|
||||
# Clean up the state from the previous one
|
||||
git reset --hard pre-rebase &&
|
||||
git checkout -B to-rebase pre-rebase &&
|
||||
test_must_fail git rebase$type main &&
|
||||
test_path_is_dir "$state_dir" &&
|
||||
test_must_fail git rebase --skip &&
|
||||
|
@ -333,4 +333,14 @@ test_expect_success 'never change active branch' '
|
||||
test_cmp_rev not-the-feature-branch unrelated-onto-branch
|
||||
'
|
||||
|
||||
test_expect_success 'autostash commit is marked as reachable' '
|
||||
echo changed >file0 &&
|
||||
git rebase --autostash --exec "git prune --expire=now" \
|
||||
feature-branch^ feature-branch &&
|
||||
# git rebase succeeds if the stash cannot be applied so we need to check
|
||||
# the contents of file0
|
||||
echo changed >expect &&
|
||||
test_cmp expect file0
|
||||
'
|
||||
|
||||
test_done
|
||||
|
Reference in New Issue
Block a user