0

I am working on a new merge-strategy to be used during rebases, specifically. I have setup the merge-strategy as a separate git builtin and it seems to be working correctly. The merge strategy will only write on the index/worktree if it succeeds (this is done with another subprocess call to git restore and exiting with 0 from the merge strategy) and otherwise it does not do anything with the index or the working tree (exiting with 2). I have set it up temporarily to be run before attempting to run the recursive strategies and, because of having to mess up with index/working tree, I am releasing the lock and getting it back (discarding cache state if the merge succeeds):

    if (!opts->strategy || !strcmp(opts->strategy, "blahblah")) {
        rollback_lock_file(&lock);
        ret = try_blahblah_merge(opts, commit, to_merge->item); // will make a git subprocess call to the new merge strategy
        if (ret) {
             // working tree and index have been modified
            discard_index(r->index);
            if (repo_read_index(r) < 0) {
                ret = error(_("could not read index"));
                goto leave_merge;
            }
            goto ran_merge; // after recursive attempts, no need for them as the merge has been successful
        }
        // working tree and index are the way they were before
        // regain lock to go into recursive
        if (repo_hold_locked_index(r, &lock, LOCK_REPORT_ON_ERROR) < 0) {
            ret = -1;
            goto leave_merge;
        }
    }
    if (!opts->strategy || !strcmp(opts->strategy, "ort")) {
        ret = merge_ort_recursive(&o,
                      head_commit, merge_commit, bases,
                      &i);
    } else {
        ret = merge_recursive(&o, head_commit, merge_commit, bases,
                      &i);
    }
ran_merge:
    // preexisting code
    if (ret <= 0)
        fputs(o.obuf.buf, stdout);
    .
    .
    .

So, I think this is barely working correctly (I think I need a little bit of coaching here in terms of handling of cache/lock) both for successful merges and for failing merges (successful merges skip recursive and create the commit, failed merges just go into recursive as usual) but I would like to have this code after the recursive attempts so that this becomes a Hail Mary attempt instead of being the first attempt to be made. Logic here is that given that the merge strategy will not change the state of working tree or index if the strategy fails to merge (it only changes working tree/index if the merge is successful) then the user will still see stuff as it was when recursive failed to merge. But when I try to do it, I get a coredump:

    if (!opts->strategy || !strcmp(opts->strategy, "ort")) {
        ret = merge_ort_recursive(&o,
                      head_commit, merge_commit, bases,
                      &i);
    } else {
        ret = merge_recursive(&o, head_commit, merge_commit, bases,
                      &i);
    }
    if ((!ret && !opts->strategy) || !strcmp(opts->strategy, "blahblah")) {
        rollback_lock_file(&lock);
        ret = try_blahblah_merge(opts, commit, to_merge->item); // will make a git subprocess call to the new merge strategy
        if (ret) {
             // working tree and index have been modified
            discard_index(r->index);
            if (repo_read_index(r) < 0) {
                ret = error(_("could not read index"));
                goto leave_merge;
            }
            // let's let it continue running because we have a successful merge
        } else {
            // working tree and index are the way they were before
            // regain lock to go into recursive
            if (repo_hold_locked_index(r, &lock, LOCK_REPORT_ON_ERROR) < 0) {
                ret = -1;
                goto leave_merge;
            }
        }
    }
    // preexisting code
    if (ret <= 0)
        fputs(o.obuf.buf, stdout);
    .
    .
    .

What am I doing wrong over here?

eftshift0
  • 26,375
  • 3
  • 36
  • 60

0 Answers0