| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | /* | 
| 2 |  |  |  |  |  |  | * Copyright (C) the libgit2 contributors. All rights reserved. | 
| 3 |  |  |  |  |  |  | * | 
| 4 |  |  |  |  |  |  | * This file is part of libgit2, distributed under the GNU GPL v2 with | 
| 5 |  |  |  |  |  |  | * a Linking Exception. For full terms see the included COPYING file. | 
| 6 |  |  |  |  |  |  | */ | 
| 7 |  |  |  |  |  |  |  | 
| 8 |  |  |  |  |  |  | #include "common.h" | 
| 9 |  |  |  |  |  |  |  | 
| 10 |  |  |  |  |  |  | #include "str.h" | 
| 11 |  |  |  |  |  |  | #include "repository.h" | 
| 12 |  |  |  |  |  |  | #include "posix.h" | 
| 13 |  |  |  |  |  |  | #include "filebuf.h" | 
| 14 |  |  |  |  |  |  | #include "commit.h" | 
| 15 |  |  |  |  |  |  | #include "merge.h" | 
| 16 |  |  |  |  |  |  | #include "array.h" | 
| 17 |  |  |  |  |  |  | #include "config.h" | 
| 18 |  |  |  |  |  |  | #include "annotated_commit.h" | 
| 19 |  |  |  |  |  |  | #include "index.h" | 
| 20 |  |  |  |  |  |  |  | 
| 21 |  |  |  |  |  |  | #include | 
| 22 |  |  |  |  |  |  | #include | 
| 23 |  |  |  |  |  |  | #include | 
| 24 |  |  |  |  |  |  | #include | 
| 25 |  |  |  |  |  |  | #include | 
| 26 |  |  |  |  |  |  | #include | 
| 27 |  |  |  |  |  |  | #include | 
| 28 |  |  |  |  |  |  |  | 
| 29 |  |  |  |  |  |  | #define REBASE_APPLY_DIR    "rebase-apply" | 
| 30 |  |  |  |  |  |  | #define REBASE_MERGE_DIR    "rebase-merge" | 
| 31 |  |  |  |  |  |  |  | 
| 32 |  |  |  |  |  |  | #define HEAD_NAME_FILE      "head-name" | 
| 33 |  |  |  |  |  |  | #define ORIG_HEAD_FILE      "orig-head" | 
| 34 |  |  |  |  |  |  | #define HEAD_FILE           "head" | 
| 35 |  |  |  |  |  |  | #define ONTO_FILE           "onto" | 
| 36 |  |  |  |  |  |  | #define ONTO_NAME_FILE      "onto_name" | 
| 37 |  |  |  |  |  |  | #define QUIET_FILE          "quiet" | 
| 38 |  |  |  |  |  |  | #define INTERACTIVE_FILE    "interactive" | 
| 39 |  |  |  |  |  |  |  | 
| 40 |  |  |  |  |  |  | #define MSGNUM_FILE         "msgnum" | 
| 41 |  |  |  |  |  |  | #define END_FILE            "end" | 
| 42 |  |  |  |  |  |  | #define CMT_FILE_FMT        "cmt.%" PRIuZ | 
| 43 |  |  |  |  |  |  | #define CURRENT_FILE        "current" | 
| 44 |  |  |  |  |  |  | #define REWRITTEN_FILE      "rewritten" | 
| 45 |  |  |  |  |  |  |  | 
| 46 |  |  |  |  |  |  | #define ORIG_DETACHED_HEAD  "detached HEAD" | 
| 47 |  |  |  |  |  |  |  | 
| 48 |  |  |  |  |  |  | #define NOTES_DEFAULT_REF   NULL | 
| 49 |  |  |  |  |  |  |  | 
| 50 |  |  |  |  |  |  | #define REBASE_DIR_MODE     0777 | 
| 51 |  |  |  |  |  |  | #define REBASE_FILE_MODE    0666 | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | typedef enum { | 
| 54 |  |  |  |  |  |  | GIT_REBASE_NONE = 0, | 
| 55 |  |  |  |  |  |  | GIT_REBASE_APPLY = 1, | 
| 56 |  |  |  |  |  |  | GIT_REBASE_MERGE = 2, | 
| 57 |  |  |  |  |  |  | GIT_REBASE_INTERACTIVE = 3 | 
| 58 |  |  |  |  |  |  | } git_rebase_t; | 
| 59 |  |  |  |  |  |  |  | 
| 60 |  |  |  |  |  |  | struct git_rebase { | 
| 61 |  |  |  |  |  |  | git_repository *repo; | 
| 62 |  |  |  |  |  |  |  | 
| 63 |  |  |  |  |  |  | git_rebase_options options; | 
| 64 |  |  |  |  |  |  |  | 
| 65 |  |  |  |  |  |  | git_rebase_t type; | 
| 66 |  |  |  |  |  |  | char *state_path; | 
| 67 |  |  |  |  |  |  |  | 
| 68 |  |  |  |  |  |  | unsigned int head_detached:1, | 
| 69 |  |  |  |  |  |  | inmemory:1, | 
| 70 |  |  |  |  |  |  | quiet:1, | 
| 71 |  |  |  |  |  |  | started:1; | 
| 72 |  |  |  |  |  |  |  | 
| 73 |  |  |  |  |  |  | git_array_t(git_rebase_operation) operations; | 
| 74 |  |  |  |  |  |  | size_t current; | 
| 75 |  |  |  |  |  |  |  | 
| 76 |  |  |  |  |  |  | /* Used by in-memory rebase */ | 
| 77 |  |  |  |  |  |  | git_index *index; | 
| 78 |  |  |  |  |  |  | git_commit *last_commit; | 
| 79 |  |  |  |  |  |  |  | 
| 80 |  |  |  |  |  |  | /* Used by regular (not in-memory) merge-style rebase */ | 
| 81 |  |  |  |  |  |  | git_oid orig_head_id; | 
| 82 |  |  |  |  |  |  | char *orig_head_name; | 
| 83 |  |  |  |  |  |  |  | 
| 84 |  |  |  |  |  |  | git_oid onto_id; | 
| 85 |  |  |  |  |  |  | char *onto_name; | 
| 86 |  |  |  |  |  |  | }; | 
| 87 |  |  |  |  |  |  |  | 
| 88 |  |  |  |  |  |  | #define GIT_REBASE_STATE_INIT {0} | 
| 89 |  |  |  |  |  |  |  | 
| 90 | 3 |  |  |  |  |  | static int rebase_state_type( | 
| 91 |  |  |  |  |  |  | git_rebase_t *type_out, | 
| 92 |  |  |  |  |  |  | char **path_out, | 
| 93 |  |  |  |  |  |  | git_repository *repo) | 
| 94 |  |  |  |  |  |  | { | 
| 95 | 3 |  |  |  |  |  | git_str path = GIT_STR_INIT; | 
| 96 | 3 |  |  |  |  |  | git_str interactive_path = GIT_STR_INIT; | 
| 97 | 3 |  |  |  |  |  | git_rebase_t type = GIT_REBASE_NONE; | 
| 98 |  |  |  |  |  |  |  | 
| 99 | 3 | 50 |  |  |  |  | if (git_str_joinpath(&path, repo->gitdir, REBASE_APPLY_DIR) < 0) | 
| 100 | 0 |  |  |  |  |  | return -1; | 
| 101 |  |  |  |  |  |  |  | 
| 102 | 3 | 50 |  |  |  |  | if (git_fs_path_isdir(git_str_cstr(&path))) { | 
| 103 | 0 |  |  |  |  |  | type = GIT_REBASE_APPLY; | 
| 104 | 0 |  |  |  |  |  | goto done; | 
| 105 |  |  |  |  |  |  | } | 
| 106 |  |  |  |  |  |  |  | 
| 107 | 3 |  |  |  |  |  | git_str_clear(&path); | 
| 108 | 3 | 50 |  |  |  |  | if (git_str_joinpath(&path, repo->gitdir, REBASE_MERGE_DIR) < 0) | 
| 109 | 0 |  |  |  |  |  | return -1; | 
| 110 |  |  |  |  |  |  |  | 
| 111 | 3 | 100 |  |  |  |  | if (git_fs_path_isdir(git_str_cstr(&path))) { | 
| 112 | 1 | 50 |  |  |  |  | if (git_str_joinpath(&interactive_path, path.ptr, INTERACTIVE_FILE) < 0) | 
| 113 | 0 |  |  |  |  |  | return -1; | 
| 114 |  |  |  |  |  |  |  | 
| 115 | 1 | 50 |  |  |  |  | if (git_fs_path_isfile(interactive_path.ptr)) | 
| 116 | 0 |  |  |  |  |  | type = GIT_REBASE_INTERACTIVE; | 
| 117 |  |  |  |  |  |  | else | 
| 118 | 1 |  |  |  |  |  | type = GIT_REBASE_MERGE; | 
| 119 |  |  |  |  |  |  |  | 
| 120 | 1 |  |  |  |  |  | goto done; | 
| 121 |  |  |  |  |  |  | } | 
| 122 |  |  |  |  |  |  |  | 
| 123 |  |  |  |  |  |  | done: | 
| 124 | 3 |  |  |  |  |  | *type_out = type; | 
| 125 |  |  |  |  |  |  |  | 
| 126 | 3 | 100 |  |  |  |  | if (type != GIT_REBASE_NONE && path_out) | 
|  |  | 50 |  |  |  |  |  | 
| 127 | 1 |  |  |  |  |  | *path_out = git_str_detach(&path); | 
| 128 |  |  |  |  |  |  |  | 
| 129 | 3 |  |  |  |  |  | git_str_dispose(&path); | 
| 130 | 3 |  |  |  |  |  | git_str_dispose(&interactive_path); | 
| 131 |  |  |  |  |  |  |  | 
| 132 | 3 |  |  |  |  |  | return 0; | 
| 133 |  |  |  |  |  |  | } | 
| 134 |  |  |  |  |  |  |  | 
| 135 | 7 |  |  |  |  |  | GIT_INLINE(int) rebase_readfile( | 
| 136 |  |  |  |  |  |  | git_str *out, | 
| 137 |  |  |  |  |  |  | git_str *state_path, | 
| 138 |  |  |  |  |  |  | const char *filename) | 
| 139 |  |  |  |  |  |  | { | 
| 140 | 7 |  |  |  |  |  | size_t state_path_len = state_path->size; | 
| 141 |  |  |  |  |  |  | int error; | 
| 142 |  |  |  |  |  |  |  | 
| 143 | 7 |  |  |  |  |  | git_str_clear(out); | 
| 144 |  |  |  |  |  |  |  | 
| 145 | 7 | 50 |  |  |  |  | if ((error = git_str_joinpath(state_path, state_path->ptr, filename)) < 0 || | 
|  |  | 50 |  |  |  |  |  | 
| 146 | 7 |  |  |  |  |  | (error = git_futils_readbuffer(out, state_path->ptr)) < 0) | 
| 147 |  |  |  |  |  |  | goto done; | 
| 148 |  |  |  |  |  |  |  | 
| 149 | 7 |  |  |  |  |  | git_str_rtrim(out); | 
| 150 |  |  |  |  |  |  |  | 
| 151 |  |  |  |  |  |  | done: | 
| 152 | 7 |  |  |  |  |  | git_str_truncate(state_path, state_path_len); | 
| 153 | 7 |  |  |  |  |  | return error; | 
| 154 |  |  |  |  |  |  | } | 
| 155 |  |  |  |  |  |  |  | 
| 156 | 2 |  |  |  |  |  | GIT_INLINE(int) rebase_readint( | 
| 157 |  |  |  |  |  |  | size_t *out, git_str *asc_out, git_str *state_path, const char *filename) | 
| 158 |  |  |  |  |  |  | { | 
| 159 |  |  |  |  |  |  | int32_t num; | 
| 160 |  |  |  |  |  |  | const char *eol; | 
| 161 | 2 |  |  |  |  |  | int error = 0; | 
| 162 |  |  |  |  |  |  |  | 
| 163 | 2 | 50 |  |  |  |  | if ((error = rebase_readfile(asc_out, state_path, filename)) < 0) | 
| 164 | 0 |  |  |  |  |  | return error; | 
| 165 |  |  |  |  |  |  |  | 
| 166 | 2 | 50 |  |  |  |  | if (git__strntol32(&num, asc_out->ptr, asc_out->size, &eol, 10) < 0 || num < 0 || *eol) { | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 167 | 0 |  |  |  |  |  | git_error_set(GIT_ERROR_REBASE, "the file '%s' contains an invalid numeric value", filename); | 
| 168 | 0 |  |  |  |  |  | return -1; | 
| 169 |  |  |  |  |  |  | } | 
| 170 |  |  |  |  |  |  |  | 
| 171 | 2 |  |  |  |  |  | *out = (size_t) num; | 
| 172 |  |  |  |  |  |  |  | 
| 173 | 2 |  |  |  |  |  | return 0; | 
| 174 |  |  |  |  |  |  | } | 
| 175 |  |  |  |  |  |  |  | 
| 176 | 4 |  |  |  |  |  | GIT_INLINE(int) rebase_readoid( | 
| 177 |  |  |  |  |  |  | git_oid *out, git_str *str_out, git_str *state_path, const char *filename) | 
| 178 |  |  |  |  |  |  | { | 
| 179 |  |  |  |  |  |  | int error; | 
| 180 |  |  |  |  |  |  |  | 
| 181 | 4 | 50 |  |  |  |  | if ((error = rebase_readfile(str_out, state_path, filename)) < 0) | 
| 182 | 0 |  |  |  |  |  | return error; | 
| 183 |  |  |  |  |  |  |  | 
| 184 | 4 | 50 |  |  |  |  | if (str_out->size != GIT_OID_HEXSZ || git_oid_fromstr(out, str_out->ptr) < 0) { | 
|  |  | 50 |  |  |  |  |  | 
| 185 | 0 |  |  |  |  |  | git_error_set(GIT_ERROR_REBASE, "the file '%s' contains an invalid object ID", filename); | 
| 186 | 0 |  |  |  |  |  | return -1; | 
| 187 |  |  |  |  |  |  | } | 
| 188 |  |  |  |  |  |  |  | 
| 189 | 4 |  |  |  |  |  | return 0; | 
| 190 |  |  |  |  |  |  | } | 
| 191 |  |  |  |  |  |  |  | 
| 192 | 9 |  |  |  |  |  | static git_rebase_operation *rebase_operation_alloc( | 
| 193 |  |  |  |  |  |  | git_rebase *rebase, | 
| 194 |  |  |  |  |  |  | git_rebase_operation_t type, | 
| 195 |  |  |  |  |  |  | git_oid *id, | 
| 196 |  |  |  |  |  |  | const char *exec) | 
| 197 |  |  |  |  |  |  | { | 
| 198 |  |  |  |  |  |  | git_rebase_operation *operation; | 
| 199 |  |  |  |  |  |  |  | 
| 200 | 9 | 50 |  |  |  |  | GIT_ASSERT_WITH_RETVAL((type == GIT_REBASE_OPERATION_EXEC) == !id, NULL); | 
| 201 | 9 | 50 |  |  |  |  | GIT_ASSERT_WITH_RETVAL((type == GIT_REBASE_OPERATION_EXEC) == !!exec, NULL); | 
| 202 |  |  |  |  |  |  |  | 
| 203 | 9 | 100 |  |  |  |  | if ((operation = git_array_alloc(rebase->operations)) == NULL) | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 204 | 0 |  |  |  |  |  | return NULL; | 
| 205 |  |  |  |  |  |  |  | 
| 206 | 9 |  |  |  |  |  | operation->type = type; | 
| 207 | 9 |  |  |  |  |  | git_oid_cpy((git_oid *)&operation->id, id); | 
| 208 | 9 |  |  |  |  |  | operation->exec = exec; | 
| 209 |  |  |  |  |  |  |  | 
| 210 | 9 |  |  |  |  |  | return operation; | 
| 211 |  |  |  |  |  |  | } | 
| 212 |  |  |  |  |  |  |  | 
| 213 | 1 |  |  |  |  |  | static int rebase_open_merge(git_rebase *rebase) | 
| 214 |  |  |  |  |  |  | { | 
| 215 | 1 |  |  |  |  |  | git_str state_path = GIT_STR_INIT, buf = GIT_STR_INIT, cmt = GIT_STR_INIT; | 
| 216 |  |  |  |  |  |  | git_oid id; | 
| 217 |  |  |  |  |  |  | git_rebase_operation *operation; | 
| 218 | 1 |  |  |  |  |  | size_t i, msgnum = 0, end; | 
| 219 |  |  |  |  |  |  | int error; | 
| 220 |  |  |  |  |  |  |  | 
| 221 | 1 | 50 |  |  |  |  | if ((error = git_str_puts(&state_path, rebase->state_path)) < 0) | 
| 222 | 0 |  |  |  |  |  | goto done; | 
| 223 |  |  |  |  |  |  |  | 
| 224 |  |  |  |  |  |  | /* Read 'msgnum' if it exists (otherwise, let msgnum = 0) */ | 
| 225 | 1 | 50 |  |  |  |  | if ((error = rebase_readint(&msgnum, &buf, &state_path, MSGNUM_FILE)) < 0 && | 
|  |  | 0 |  |  |  |  |  | 
| 226 |  |  |  |  |  |  | error != GIT_ENOTFOUND) | 
| 227 | 0 |  |  |  |  |  | goto done; | 
| 228 |  |  |  |  |  |  |  | 
| 229 | 1 | 50 |  |  |  |  | if (msgnum) { | 
| 230 | 1 |  |  |  |  |  | rebase->started = 1; | 
| 231 | 1 |  |  |  |  |  | rebase->current = msgnum - 1; | 
| 232 |  |  |  |  |  |  | } | 
| 233 |  |  |  |  |  |  |  | 
| 234 |  |  |  |  |  |  | /* Read 'end' */ | 
| 235 | 1 | 50 |  |  |  |  | if ((error = rebase_readint(&end, &buf, &state_path, END_FILE)) < 0) | 
| 236 | 0 |  |  |  |  |  | goto done; | 
| 237 |  |  |  |  |  |  |  | 
| 238 |  |  |  |  |  |  | /* Read 'current' if it exists */ | 
| 239 | 1 | 50 |  |  |  |  | if ((error = rebase_readoid(&id, &buf, &state_path, CURRENT_FILE)) < 0 && | 
|  |  | 0 |  |  |  |  |  | 
| 240 |  |  |  |  |  |  | error != GIT_ENOTFOUND) | 
| 241 | 0 |  |  |  |  |  | goto done; | 
| 242 |  |  |  |  |  |  |  | 
| 243 |  |  |  |  |  |  | /* Read cmt.* */ | 
| 244 | 1 |  |  |  |  |  | git_array_init_to_size(rebase->operations, end); | 
| 245 | 1 | 50 |  |  |  |  | GIT_ERROR_CHECK_ARRAY(rebase->operations); | 
| 246 |  |  |  |  |  |  |  | 
| 247 | 4 | 100 |  |  |  |  | for (i = 0; i < end; i++) { | 
| 248 | 3 |  |  |  |  |  | git_str_clear(&cmt); | 
| 249 |  |  |  |  |  |  |  | 
| 250 | 3 | 50 |  |  |  |  | if ((error = git_str_printf(&cmt, "cmt.%" PRIuZ, (i+1))) < 0 || | 
|  |  | 50 |  |  |  |  |  | 
| 251 | 3 |  |  |  |  |  | (error = rebase_readoid(&id, &buf, &state_path, cmt.ptr)) < 0) | 
| 252 |  |  |  |  |  |  | goto done; | 
| 253 |  |  |  |  |  |  |  | 
| 254 | 3 |  |  |  |  |  | operation = rebase_operation_alloc(rebase, GIT_REBASE_OPERATION_PICK, &id, NULL); | 
| 255 | 3 | 50 |  |  |  |  | GIT_ERROR_CHECK_ALLOC(operation); | 
| 256 |  |  |  |  |  |  | } | 
| 257 |  |  |  |  |  |  |  | 
| 258 |  |  |  |  |  |  | /* Read 'onto_name' */ | 
| 259 | 1 | 50 |  |  |  |  | if ((error = rebase_readfile(&buf, &state_path, ONTO_NAME_FILE)) < 0) | 
| 260 | 0 |  |  |  |  |  | goto done; | 
| 261 |  |  |  |  |  |  |  | 
| 262 | 1 |  |  |  |  |  | rebase->onto_name = git_str_detach(&buf); | 
| 263 |  |  |  |  |  |  |  | 
| 264 |  |  |  |  |  |  | done: | 
| 265 | 1 |  |  |  |  |  | git_str_dispose(&cmt); | 
| 266 | 1 |  |  |  |  |  | git_str_dispose(&state_path); | 
| 267 | 1 |  |  |  |  |  | git_str_dispose(&buf); | 
| 268 |  |  |  |  |  |  |  | 
| 269 | 1 |  |  |  |  |  | return error; | 
| 270 |  |  |  |  |  |  | } | 
| 271 |  |  |  |  |  |  |  | 
| 272 | 4 |  |  |  |  |  | static int rebase_alloc(git_rebase **out, const git_rebase_options *rebase_opts) | 
| 273 |  |  |  |  |  |  | { | 
| 274 | 4 |  |  |  |  |  | git_rebase *rebase = git__calloc(1, sizeof(git_rebase)); | 
| 275 | 4 | 50 |  |  |  |  | GIT_ERROR_CHECK_ALLOC(rebase); | 
| 276 |  |  |  |  |  |  |  | 
| 277 | 4 |  |  |  |  |  | *out = NULL; | 
| 278 |  |  |  |  |  |  |  | 
| 279 | 4 | 50 |  |  |  |  | if (rebase_opts) | 
| 280 | 4 |  |  |  |  |  | memcpy(&rebase->options, rebase_opts, sizeof(git_rebase_options)); | 
| 281 |  |  |  |  |  |  | else | 
| 282 | 0 |  |  |  |  |  | git_rebase_options_init(&rebase->options, GIT_REBASE_OPTIONS_VERSION); | 
| 283 |  |  |  |  |  |  |  | 
| 284 | 4 | 50 |  |  |  |  | if (rebase_opts && rebase_opts->rewrite_notes_ref) { | 
|  |  | 50 |  |  |  |  |  | 
| 285 | 0 |  |  |  |  |  | rebase->options.rewrite_notes_ref = git__strdup(rebase_opts->rewrite_notes_ref); | 
| 286 | 0 | 0 |  |  |  |  | GIT_ERROR_CHECK_ALLOC(rebase->options.rewrite_notes_ref); | 
| 287 |  |  |  |  |  |  | } | 
| 288 |  |  |  |  |  |  |  | 
| 289 | 4 |  |  |  |  |  | *out = rebase; | 
| 290 |  |  |  |  |  |  |  | 
| 291 | 4 |  |  |  |  |  | return 0; | 
| 292 |  |  |  |  |  |  | } | 
| 293 |  |  |  |  |  |  |  | 
| 294 | 4 |  |  |  |  |  | static int rebase_check_versions(const git_rebase_options *given_opts) | 
| 295 |  |  |  |  |  |  | { | 
| 296 | 4 | 50 |  |  |  |  | GIT_ERROR_CHECK_VERSION(given_opts, GIT_REBASE_OPTIONS_VERSION, "git_rebase_options"); | 
| 297 |  |  |  |  |  |  |  | 
| 298 | 4 | 50 |  |  |  |  | if (given_opts) | 
| 299 | 4 | 50 |  |  |  |  | GIT_ERROR_CHECK_VERSION(&given_opts->checkout_options, GIT_CHECKOUT_OPTIONS_VERSION, "git_checkout_options"); | 
| 300 |  |  |  |  |  |  |  | 
| 301 | 4 |  |  |  |  |  | return 0; | 
| 302 |  |  |  |  |  |  | } | 
| 303 |  |  |  |  |  |  |  | 
| 304 | 1 |  |  |  |  |  | int git_rebase_open( | 
| 305 |  |  |  |  |  |  | git_rebase **out, | 
| 306 |  |  |  |  |  |  | git_repository *repo, | 
| 307 |  |  |  |  |  |  | const git_rebase_options *given_opts) | 
| 308 |  |  |  |  |  |  | { | 
| 309 |  |  |  |  |  |  | git_rebase *rebase; | 
| 310 | 1 |  |  |  |  |  | git_str path = GIT_STR_INIT, orig_head_name = GIT_STR_INIT, | 
| 311 | 1 |  |  |  |  |  | orig_head_id = GIT_STR_INIT, onto_id = GIT_STR_INIT; | 
| 312 |  |  |  |  |  |  | size_t state_path_len; | 
| 313 |  |  |  |  |  |  | int error; | 
| 314 |  |  |  |  |  |  |  | 
| 315 | 1 | 50 |  |  |  |  | GIT_ASSERT_ARG(repo); | 
| 316 |  |  |  |  |  |  |  | 
| 317 | 1 | 50 |  |  |  |  | if ((error = rebase_check_versions(given_opts)) < 0) | 
| 318 | 0 |  |  |  |  |  | return error; | 
| 319 |  |  |  |  |  |  |  | 
| 320 | 1 | 50 |  |  |  |  | if (rebase_alloc(&rebase, given_opts) < 0) | 
| 321 | 0 |  |  |  |  |  | return -1; | 
| 322 |  |  |  |  |  |  |  | 
| 323 | 1 |  |  |  |  |  | rebase->repo = repo; | 
| 324 |  |  |  |  |  |  |  | 
| 325 | 1 | 50 |  |  |  |  | if ((error = rebase_state_type(&rebase->type, &rebase->state_path, repo)) < 0) | 
| 326 | 0 |  |  |  |  |  | goto done; | 
| 327 |  |  |  |  |  |  |  | 
| 328 | 1 | 50 |  |  |  |  | if (rebase->type == GIT_REBASE_NONE) { | 
| 329 | 0 |  |  |  |  |  | git_error_set(GIT_ERROR_REBASE, "there is no rebase in progress"); | 
| 330 | 0 |  |  |  |  |  | error = GIT_ENOTFOUND; | 
| 331 | 0 |  |  |  |  |  | goto done; | 
| 332 |  |  |  |  |  |  | } | 
| 333 |  |  |  |  |  |  |  | 
| 334 | 1 | 50 |  |  |  |  | if ((error = git_str_puts(&path, rebase->state_path)) < 0) | 
| 335 | 0 |  |  |  |  |  | goto done; | 
| 336 |  |  |  |  |  |  |  | 
| 337 | 1 |  |  |  |  |  | state_path_len = git_str_len(&path); | 
| 338 |  |  |  |  |  |  |  | 
| 339 | 1 | 50 |  |  |  |  | if ((error = git_str_joinpath(&path, path.ptr, HEAD_NAME_FILE)) < 0 || | 
|  |  | 50 |  |  |  |  |  | 
| 340 | 1 |  |  |  |  |  | (error = git_futils_readbuffer(&orig_head_name, path.ptr)) < 0) | 
| 341 |  |  |  |  |  |  | goto done; | 
| 342 |  |  |  |  |  |  |  | 
| 343 | 1 |  |  |  |  |  | git_str_rtrim(&orig_head_name); | 
| 344 |  |  |  |  |  |  |  | 
| 345 | 1 | 50 |  |  |  |  | if (strcmp(ORIG_DETACHED_HEAD, orig_head_name.ptr) == 0) | 
| 346 | 1 |  |  |  |  |  | rebase->head_detached = 1; | 
| 347 |  |  |  |  |  |  |  | 
| 348 | 1 |  |  |  |  |  | git_str_truncate(&path, state_path_len); | 
| 349 |  |  |  |  |  |  |  | 
| 350 | 1 | 50 |  |  |  |  | if ((error = git_str_joinpath(&path, path.ptr, ORIG_HEAD_FILE)) < 0) | 
| 351 | 0 |  |  |  |  |  | goto done; | 
| 352 |  |  |  |  |  |  |  | 
| 353 | 1 | 50 |  |  |  |  | if (!git_fs_path_isfile(path.ptr)) { | 
| 354 |  |  |  |  |  |  | /* Previous versions of git.git used 'head' here; support that. */ | 
| 355 | 0 |  |  |  |  |  | git_str_truncate(&path, state_path_len); | 
| 356 |  |  |  |  |  |  |  | 
| 357 | 0 | 0 |  |  |  |  | if ((error = git_str_joinpath(&path, path.ptr, HEAD_FILE)) < 0) | 
| 358 | 0 |  |  |  |  |  | goto done; | 
| 359 |  |  |  |  |  |  | } | 
| 360 |  |  |  |  |  |  |  | 
| 361 | 1 | 50 |  |  |  |  | if ((error = git_futils_readbuffer(&orig_head_id, path.ptr)) < 0) | 
| 362 | 0 |  |  |  |  |  | goto done; | 
| 363 |  |  |  |  |  |  |  | 
| 364 | 1 |  |  |  |  |  | git_str_rtrim(&orig_head_id); | 
| 365 |  |  |  |  |  |  |  | 
| 366 | 1 | 50 |  |  |  |  | if ((error = git_oid_fromstr(&rebase->orig_head_id, orig_head_id.ptr)) < 0) | 
| 367 | 0 |  |  |  |  |  | goto done; | 
| 368 |  |  |  |  |  |  |  | 
| 369 | 1 |  |  |  |  |  | git_str_truncate(&path, state_path_len); | 
| 370 |  |  |  |  |  |  |  | 
| 371 | 1 | 50 |  |  |  |  | if ((error = git_str_joinpath(&path, path.ptr, ONTO_FILE)) < 0 || | 
|  |  | 50 |  |  |  |  |  | 
| 372 | 1 |  |  |  |  |  | (error = git_futils_readbuffer(&onto_id, path.ptr)) < 0) | 
| 373 |  |  |  |  |  |  | goto done; | 
| 374 |  |  |  |  |  |  |  | 
| 375 | 1 |  |  |  |  |  | git_str_rtrim(&onto_id); | 
| 376 |  |  |  |  |  |  |  | 
| 377 | 1 | 50 |  |  |  |  | if ((error = git_oid_fromstr(&rebase->onto_id, onto_id.ptr)) < 0) | 
| 378 | 0 |  |  |  |  |  | goto done; | 
| 379 |  |  |  |  |  |  |  | 
| 380 | 1 | 50 |  |  |  |  | if (!rebase->head_detached) | 
| 381 | 0 |  |  |  |  |  | rebase->orig_head_name = git_str_detach(&orig_head_name); | 
| 382 |  |  |  |  |  |  |  | 
| 383 | 1 |  |  |  |  |  | switch (rebase->type) { | 
| 384 |  |  |  |  |  |  | case GIT_REBASE_INTERACTIVE: | 
| 385 | 0 |  |  |  |  |  | git_error_set(GIT_ERROR_REBASE, "interactive rebase is not supported"); | 
| 386 | 0 |  |  |  |  |  | error = -1; | 
| 387 | 0 |  |  |  |  |  | break; | 
| 388 |  |  |  |  |  |  | case GIT_REBASE_MERGE: | 
| 389 | 1 |  |  |  |  |  | error = rebase_open_merge(rebase); | 
| 390 | 1 |  |  |  |  |  | break; | 
| 391 |  |  |  |  |  |  | case GIT_REBASE_APPLY: | 
| 392 | 0 |  |  |  |  |  | git_error_set(GIT_ERROR_REBASE, "patch application rebase is not supported"); | 
| 393 | 0 |  |  |  |  |  | error = -1; | 
| 394 | 0 |  |  |  |  |  | break; | 
| 395 |  |  |  |  |  |  | default: | 
| 396 | 0 |  |  |  |  |  | abort(); | 
| 397 |  |  |  |  |  |  | } | 
| 398 |  |  |  |  |  |  |  | 
| 399 |  |  |  |  |  |  | done: | 
| 400 | 1 | 50 |  |  |  |  | if (error == 0) | 
| 401 | 1 |  |  |  |  |  | *out = rebase; | 
| 402 |  |  |  |  |  |  | else | 
| 403 | 0 |  |  |  |  |  | git_rebase_free(rebase); | 
| 404 |  |  |  |  |  |  |  | 
| 405 | 1 |  |  |  |  |  | git_str_dispose(&path); | 
| 406 | 1 |  |  |  |  |  | git_str_dispose(&orig_head_name); | 
| 407 | 1 |  |  |  |  |  | git_str_dispose(&orig_head_id); | 
| 408 | 1 |  |  |  |  |  | git_str_dispose(&onto_id); | 
| 409 | 1 |  |  |  |  |  | return error; | 
| 410 |  |  |  |  |  |  | } | 
| 411 |  |  |  |  |  |  |  | 
| 412 | 2 |  |  |  |  |  | static int rebase_cleanup(git_rebase *rebase) | 
| 413 |  |  |  |  |  |  | { | 
| 414 | 2 | 50 |  |  |  |  | if (!rebase || rebase->inmemory) | 
|  |  | 50 |  |  |  |  |  | 
| 415 | 0 |  |  |  |  |  | return 0; | 
| 416 |  |  |  |  |  |  |  | 
| 417 | 4 |  |  |  |  |  | return git_fs_path_isdir(rebase->state_path) ? | 
| 418 | 2 | 100 |  |  |  |  | git_futils_rmdir_r(rebase->state_path, NULL, GIT_RMDIR_REMOVE_FILES) : | 
| 419 |  |  |  |  |  |  | 0; | 
| 420 |  |  |  |  |  |  | } | 
| 421 |  |  |  |  |  |  |  | 
| 422 | 24 |  |  |  |  |  | static int rebase_setupfile(git_rebase *rebase, const char *filename, int flags, const char *fmt, ...) | 
| 423 |  |  |  |  |  |  | { | 
| 424 | 24 |  |  |  |  |  | git_str path = GIT_STR_INIT, | 
| 425 | 24 |  |  |  |  |  | contents = GIT_STR_INIT; | 
| 426 |  |  |  |  |  |  | va_list ap; | 
| 427 |  |  |  |  |  |  | int error; | 
| 428 |  |  |  |  |  |  |  | 
| 429 | 24 |  |  |  |  |  | va_start(ap, fmt); | 
| 430 | 24 |  |  |  |  |  | git_str_vprintf(&contents, fmt, ap); | 
| 431 | 24 |  |  |  |  |  | va_end(ap); | 
| 432 |  |  |  |  |  |  |  | 
| 433 | 24 | 50 |  |  |  |  | if ((error = git_str_joinpath(&path, rebase->state_path, filename)) == 0) | 
| 434 | 24 |  |  |  |  |  | error = git_futils_writebuffer(&contents, path.ptr, flags, REBASE_FILE_MODE); | 
| 435 |  |  |  |  |  |  |  | 
| 436 | 24 |  |  |  |  |  | git_str_dispose(&path); | 
| 437 | 24 |  |  |  |  |  | git_str_dispose(&contents); | 
| 438 |  |  |  |  |  |  |  | 
| 439 | 24 |  |  |  |  |  | return error; | 
| 440 |  |  |  |  |  |  | } | 
| 441 |  |  |  |  |  |  |  | 
| 442 | 4 |  |  |  |  |  | static const char *rebase_onto_name(const git_annotated_commit *onto) | 
| 443 |  |  |  |  |  |  | { | 
| 444 | 4 | 100 |  |  |  |  | if (onto->ref_name && git__strncmp(onto->ref_name, "refs/heads/", 11) == 0) | 
|  |  | 50 |  |  |  |  |  | 
| 445 | 2 |  |  |  |  |  | return onto->ref_name + 11; | 
| 446 | 2 | 50 |  |  |  |  | else if (onto->ref_name) | 
| 447 | 0 |  |  |  |  |  | return onto->ref_name; | 
| 448 |  |  |  |  |  |  | else | 
| 449 | 2 |  |  |  |  |  | return onto->id_str; | 
| 450 |  |  |  |  |  |  | } | 
| 451 |  |  |  |  |  |  |  | 
| 452 | 2 |  |  |  |  |  | static int rebase_setupfiles_merge(git_rebase *rebase) | 
| 453 |  |  |  |  |  |  | { | 
| 454 | 2 |  |  |  |  |  | git_str commit_filename = GIT_STR_INIT; | 
| 455 |  |  |  |  |  |  | char id_str[GIT_OID_HEXSZ]; | 
| 456 |  |  |  |  |  |  | git_rebase_operation *operation; | 
| 457 |  |  |  |  |  |  | size_t i; | 
| 458 | 2 |  |  |  |  |  | int error = 0; | 
| 459 |  |  |  |  |  |  |  | 
| 460 | 2 | 50 |  |  |  |  | if ((error = rebase_setupfile(rebase, END_FILE, 0, "%" PRIuZ "\n", git_array_size(rebase->operations))) < 0 || | 
|  |  | 50 |  |  |  |  |  | 
| 461 | 2 |  |  |  |  |  | (error = rebase_setupfile(rebase, ONTO_NAME_FILE, 0, "%s\n", rebase->onto_name)) < 0) | 
| 462 |  |  |  |  |  |  | goto done; | 
| 463 |  |  |  |  |  |  |  | 
| 464 | 5 | 100 |  |  |  |  | for (i = 0; i < git_array_size(rebase->operations); i++) { | 
| 465 | 3 | 50 |  |  |  |  | operation = git_array_get(rebase->operations, i); | 
| 466 |  |  |  |  |  |  |  | 
| 467 | 3 |  |  |  |  |  | git_str_clear(&commit_filename); | 
| 468 | 3 |  |  |  |  |  | git_str_printf(&commit_filename, CMT_FILE_FMT, i+1); | 
| 469 |  |  |  |  |  |  |  | 
| 470 | 3 |  |  |  |  |  | git_oid_fmt(id_str, &operation->id); | 
| 471 |  |  |  |  |  |  |  | 
| 472 | 3 | 50 |  |  |  |  | if ((error = rebase_setupfile(rebase, commit_filename.ptr, 0, | 
| 473 |  |  |  |  |  |  | "%.*s\n", GIT_OID_HEXSZ, id_str)) < 0) | 
| 474 | 0 |  |  |  |  |  | goto done; | 
| 475 |  |  |  |  |  |  | } | 
| 476 |  |  |  |  |  |  |  | 
| 477 |  |  |  |  |  |  | done: | 
| 478 | 2 |  |  |  |  |  | git_str_dispose(&commit_filename); | 
| 479 | 2 |  |  |  |  |  | return error; | 
| 480 |  |  |  |  |  |  | } | 
| 481 |  |  |  |  |  |  |  | 
| 482 | 2 |  |  |  |  |  | static int rebase_setupfiles(git_rebase *rebase) | 
| 483 |  |  |  |  |  |  | { | 
| 484 |  |  |  |  |  |  | char onto[GIT_OID_HEXSZ], orig_head[GIT_OID_HEXSZ]; | 
| 485 |  |  |  |  |  |  | const char *orig_head_name; | 
| 486 |  |  |  |  |  |  |  | 
| 487 | 2 |  |  |  |  |  | git_oid_fmt(onto, &rebase->onto_id); | 
| 488 | 2 |  |  |  |  |  | git_oid_fmt(orig_head, &rebase->orig_head_id); | 
| 489 |  |  |  |  |  |  |  | 
| 490 | 2 | 50 |  |  |  |  | if (p_mkdir(rebase->state_path, REBASE_DIR_MODE) < 0) { | 
| 491 | 0 |  |  |  |  |  | git_error_set(GIT_ERROR_OS, "failed to create rebase directory '%s'", rebase->state_path); | 
| 492 | 0 |  |  |  |  |  | return -1; | 
| 493 |  |  |  |  |  |  | } | 
| 494 |  |  |  |  |  |  |  | 
| 495 | 2 | 50 |  |  |  |  | orig_head_name = rebase->head_detached ? ORIG_DETACHED_HEAD : | 
| 496 |  |  |  |  |  |  | rebase->orig_head_name; | 
| 497 |  |  |  |  |  |  |  | 
| 498 | 4 |  |  |  |  |  | if (git_repository__set_orig_head(rebase->repo, &rebase->orig_head_id) < 0 || | 
| 499 | 4 | 50 |  |  |  |  | rebase_setupfile(rebase, HEAD_NAME_FILE, 0, "%s\n", orig_head_name) < 0 || | 
| 500 | 4 | 50 |  |  |  |  | rebase_setupfile(rebase, ONTO_FILE, 0, "%.*s\n", GIT_OID_HEXSZ, onto) < 0 || | 
| 501 | 4 | 50 |  |  |  |  | rebase_setupfile(rebase, ORIG_HEAD_FILE, 0, "%.*s\n", GIT_OID_HEXSZ, orig_head) < 0 || | 
| 502 | 2 | 100 |  |  |  |  | rebase_setupfile(rebase, QUIET_FILE, 0, rebase->quiet ? "t\n" : "\n") < 0) | 
| 503 | 0 |  |  |  |  |  | return -1; | 
| 504 |  |  |  |  |  |  |  | 
| 505 | 2 |  |  |  |  |  | return rebase_setupfiles_merge(rebase); | 
| 506 |  |  |  |  |  |  | } | 
| 507 |  |  |  |  |  |  |  | 
| 508 | 0 |  |  |  |  |  | int git_rebase_options_init(git_rebase_options *opts, unsigned int version) | 
| 509 |  |  |  |  |  |  | { | 
| 510 | 0 | 0 |  |  |  |  | GIT_INIT_STRUCTURE_FROM_TEMPLATE( | 
| 511 |  |  |  |  |  |  | opts, version, git_rebase_options, GIT_REBASE_OPTIONS_INIT); | 
| 512 | 0 |  |  |  |  |  | return 0; | 
| 513 |  |  |  |  |  |  | } | 
| 514 |  |  |  |  |  |  |  | 
| 515 |  |  |  |  |  |  | #ifndef GIT_DEPRECATE_HARD | 
| 516 | 0 |  |  |  |  |  | int git_rebase_init_options(git_rebase_options *opts, unsigned int version) | 
| 517 |  |  |  |  |  |  | { | 
| 518 | 0 |  |  |  |  |  | return git_rebase_options_init(opts, version); | 
| 519 |  |  |  |  |  |  | } | 
| 520 |  |  |  |  |  |  | #endif | 
| 521 |  |  |  |  |  |  |  | 
| 522 | 2 |  |  |  |  |  | static int rebase_ensure_not_in_progress(git_repository *repo) | 
| 523 |  |  |  |  |  |  | { | 
| 524 |  |  |  |  |  |  | int error; | 
| 525 |  |  |  |  |  |  | git_rebase_t type; | 
| 526 |  |  |  |  |  |  |  | 
| 527 | 2 | 50 |  |  |  |  | if ((error = rebase_state_type(&type, NULL, repo)) < 0) | 
| 528 | 0 |  |  |  |  |  | return error; | 
| 529 |  |  |  |  |  |  |  | 
| 530 | 2 | 50 |  |  |  |  | if (type != GIT_REBASE_NONE) { | 
| 531 | 0 |  |  |  |  |  | git_error_set(GIT_ERROR_REBASE, "there is an existing rebase in progress"); | 
| 532 | 0 |  |  |  |  |  | return -1; | 
| 533 |  |  |  |  |  |  | } | 
| 534 |  |  |  |  |  |  |  | 
| 535 | 2 |  |  |  |  |  | return 0; | 
| 536 |  |  |  |  |  |  | } | 
| 537 |  |  |  |  |  |  |  | 
| 538 | 5 |  |  |  |  |  | static int rebase_ensure_not_dirty( | 
| 539 |  |  |  |  |  |  | git_repository *repo, | 
| 540 |  |  |  |  |  |  | bool check_index, | 
| 541 |  |  |  |  |  |  | bool check_workdir, | 
| 542 |  |  |  |  |  |  | int fail_with) | 
| 543 |  |  |  |  |  |  | { | 
| 544 | 5 |  |  |  |  |  | git_tree *head = NULL; | 
| 545 | 5 |  |  |  |  |  | git_index *index = NULL; | 
| 546 | 5 |  |  |  |  |  | git_diff *diff = NULL; | 
| 547 | 5 |  |  |  |  |  | int error = 0; | 
| 548 |  |  |  |  |  |  |  | 
| 549 | 5 | 100 |  |  |  |  | if (check_index) { | 
| 550 | 2 | 50 |  |  |  |  | if ((error = git_repository_head_tree(&head, repo)) < 0 || | 
|  |  | 50 |  |  |  |  |  | 
| 551 | 2 | 50 |  |  |  |  | (error = git_repository_index(&index, repo)) < 0 || | 
| 552 | 2 |  |  |  |  |  | (error = git_diff_tree_to_index(&diff, repo, head, index, NULL)) < 0) | 
| 553 |  |  |  |  |  |  | goto done; | 
| 554 |  |  |  |  |  |  |  | 
| 555 | 2 | 50 |  |  |  |  | if (git_diff_num_deltas(diff) > 0) { | 
| 556 | 0 |  |  |  |  |  | git_error_set(GIT_ERROR_REBASE, "uncommitted changes exist in index"); | 
| 557 | 0 |  |  |  |  |  | error = fail_with; | 
| 558 | 0 |  |  |  |  |  | goto done; | 
| 559 |  |  |  |  |  |  | } | 
| 560 |  |  |  |  |  |  |  | 
| 561 | 2 |  |  |  |  |  | git_diff_free(diff); | 
| 562 | 2 |  |  |  |  |  | diff = NULL; | 
| 563 |  |  |  |  |  |  | } | 
| 564 |  |  |  |  |  |  |  | 
| 565 | 5 | 50 |  |  |  |  | if (check_workdir) { | 
| 566 | 5 |  |  |  |  |  | git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT; | 
| 567 | 5 |  |  |  |  |  | diff_opts.ignore_submodules = GIT_SUBMODULE_IGNORE_UNTRACKED; | 
| 568 | 5 | 50 |  |  |  |  | if ((error = git_diff_index_to_workdir(&diff, repo, index, &diff_opts)) < 0) | 
| 569 | 0 |  |  |  |  |  | goto done; | 
| 570 |  |  |  |  |  |  |  | 
| 571 | 5 | 50 |  |  |  |  | if (git_diff_num_deltas(diff) > 0) { | 
| 572 | 0 |  |  |  |  |  | git_error_set(GIT_ERROR_REBASE, "unstaged changes exist in workdir"); | 
| 573 | 0 |  |  |  |  |  | error = fail_with; | 
| 574 | 5 |  |  |  |  |  | goto done; | 
| 575 |  |  |  |  |  |  | } | 
| 576 |  |  |  |  |  |  | } | 
| 577 |  |  |  |  |  |  |  | 
| 578 |  |  |  |  |  |  | done: | 
| 579 | 5 |  |  |  |  |  | git_diff_free(diff); | 
| 580 | 5 |  |  |  |  |  | git_index_free(index); | 
| 581 | 5 |  |  |  |  |  | git_tree_free(head); | 
| 582 |  |  |  |  |  |  |  | 
| 583 | 5 |  |  |  |  |  | return error; | 
| 584 |  |  |  |  |  |  | } | 
| 585 |  |  |  |  |  |  |  | 
| 586 | 3 |  |  |  |  |  | static int rebase_init_operations( | 
| 587 |  |  |  |  |  |  | git_rebase *rebase, | 
| 588 |  |  |  |  |  |  | git_repository *repo, | 
| 589 |  |  |  |  |  |  | const git_annotated_commit *branch, | 
| 590 |  |  |  |  |  |  | const git_annotated_commit *upstream, | 
| 591 |  |  |  |  |  |  | const git_annotated_commit *onto) | 
| 592 |  |  |  |  |  |  | { | 
| 593 | 3 |  |  |  |  |  | git_revwalk *revwalk = NULL; | 
| 594 |  |  |  |  |  |  | git_commit *commit; | 
| 595 |  |  |  |  |  |  | git_oid id; | 
| 596 |  |  |  |  |  |  | bool merge; | 
| 597 |  |  |  |  |  |  | git_rebase_operation *operation; | 
| 598 |  |  |  |  |  |  | int error; | 
| 599 |  |  |  |  |  |  |  | 
| 600 | 3 | 50 |  |  |  |  | if (!upstream) | 
| 601 | 0 |  |  |  |  |  | upstream = onto; | 
| 602 |  |  |  |  |  |  |  | 
| 603 | 6 | 50 |  |  |  |  | if ((error = git_revwalk_new(&revwalk, rebase->repo)) < 0 || | 
|  |  | 50 |  |  |  |  |  | 
| 604 | 6 | 50 |  |  |  |  | (error = git_revwalk_push(revwalk, git_annotated_commit_id(branch))) < 0 || | 
| 605 | 3 |  |  |  |  |  | (error = git_revwalk_hide(revwalk, git_annotated_commit_id(upstream))) < 0) | 
| 606 |  |  |  |  |  |  | goto done; | 
| 607 |  |  |  |  |  |  |  | 
| 608 | 3 |  |  |  |  |  | git_revwalk_sorting(revwalk, GIT_SORT_REVERSE); | 
| 609 |  |  |  |  |  |  |  | 
| 610 | 9 | 100 |  |  |  |  | while ((error = git_revwalk_next(&id, revwalk)) == 0) { | 
| 611 | 6 | 50 |  |  |  |  | if ((error = git_commit_lookup(&commit, repo, &id)) < 0) | 
| 612 | 0 |  |  |  |  |  | goto done; | 
| 613 |  |  |  |  |  |  |  | 
| 614 | 6 |  |  |  |  |  | merge = (git_commit_parentcount(commit) > 1); | 
| 615 | 6 |  |  |  |  |  | git_commit_free(commit); | 
| 616 |  |  |  |  |  |  |  | 
| 617 | 6 | 50 |  |  |  |  | if (merge) | 
| 618 | 0 |  |  |  |  |  | continue; | 
| 619 |  |  |  |  |  |  |  | 
| 620 | 6 |  |  |  |  |  | operation = rebase_operation_alloc(rebase, GIT_REBASE_OPERATION_PICK, &id, NULL); | 
| 621 | 6 | 50 |  |  |  |  | GIT_ERROR_CHECK_ALLOC(operation); | 
| 622 |  |  |  |  |  |  | } | 
| 623 |  |  |  |  |  |  |  | 
| 624 | 3 |  |  |  |  |  | error = 0; | 
| 625 |  |  |  |  |  |  |  | 
| 626 |  |  |  |  |  |  | done: | 
| 627 | 3 |  |  |  |  |  | git_revwalk_free(revwalk); | 
| 628 | 3 |  |  |  |  |  | return error; | 
| 629 |  |  |  |  |  |  | } | 
| 630 |  |  |  |  |  |  |  | 
| 631 | 2 |  |  |  |  |  | static int rebase_init_merge( | 
| 632 |  |  |  |  |  |  | git_rebase *rebase, | 
| 633 |  |  |  |  |  |  | git_repository *repo, | 
| 634 |  |  |  |  |  |  | const git_annotated_commit *branch, | 
| 635 |  |  |  |  |  |  | const git_annotated_commit *upstream, | 
| 636 |  |  |  |  |  |  | const git_annotated_commit *onto) | 
| 637 |  |  |  |  |  |  | { | 
| 638 | 2 |  |  |  |  |  | git_reference *head_ref = NULL; | 
| 639 | 2 |  |  |  |  |  | git_commit *onto_commit = NULL; | 
| 640 | 2 |  |  |  |  |  | git_str reflog = GIT_STR_INIT; | 
| 641 | 2 |  |  |  |  |  | git_str state_path = GIT_STR_INIT; | 
| 642 |  |  |  |  |  |  | int error; | 
| 643 |  |  |  |  |  |  |  | 
| 644 | 2 |  |  |  |  |  | GIT_UNUSED(upstream); | 
| 645 |  |  |  |  |  |  |  | 
| 646 | 2 | 50 |  |  |  |  | if ((error = git_str_joinpath(&state_path, repo->gitdir, REBASE_MERGE_DIR)) < 0) | 
| 647 | 0 |  |  |  |  |  | goto done; | 
| 648 |  |  |  |  |  |  |  | 
| 649 | 2 |  |  |  |  |  | rebase->state_path = git_str_detach(&state_path); | 
| 650 | 2 | 50 |  |  |  |  | GIT_ERROR_CHECK_ALLOC(rebase->state_path); | 
| 651 |  |  |  |  |  |  |  | 
| 652 | 2 | 50 |  |  |  |  | if (branch->ref_name && strcmp(branch->ref_name, "HEAD")) { | 
|  |  | 0 |  |  |  |  |  | 
| 653 | 0 |  |  |  |  |  | rebase->orig_head_name = git__strdup(branch->ref_name); | 
| 654 | 0 | 0 |  |  |  |  | GIT_ERROR_CHECK_ALLOC(rebase->orig_head_name); | 
| 655 |  |  |  |  |  |  | } else { | 
| 656 | 2 |  |  |  |  |  | rebase->head_detached = 1; | 
| 657 |  |  |  |  |  |  | } | 
| 658 |  |  |  |  |  |  |  | 
| 659 | 2 |  |  |  |  |  | rebase->onto_name = git__strdup(rebase_onto_name(onto)); | 
| 660 | 2 | 50 |  |  |  |  | GIT_ERROR_CHECK_ALLOC(rebase->onto_name); | 
| 661 |  |  |  |  |  |  |  | 
| 662 | 2 |  |  |  |  |  | rebase->quiet = rebase->options.quiet; | 
| 663 |  |  |  |  |  |  |  | 
| 664 | 2 |  |  |  |  |  | git_oid_cpy(&rebase->orig_head_id, git_annotated_commit_id(branch)); | 
| 665 | 2 |  |  |  |  |  | git_oid_cpy(&rebase->onto_id, git_annotated_commit_id(onto)); | 
| 666 |  |  |  |  |  |  |  | 
| 667 | 4 | 50 |  |  |  |  | if ((error = rebase_setupfiles(rebase)) < 0 || | 
|  |  | 50 |  |  |  |  |  | 
| 668 | 2 |  |  |  |  |  | (error = git_str_printf(&reflog, | 
| 669 | 2 | 50 |  |  |  |  | "rebase: checkout %s", rebase_onto_name(onto))) < 0 || | 
| 670 | 2 |  |  |  |  |  | (error = git_commit_lookup( | 
| 671 | 2 | 50 |  |  |  |  | &onto_commit, repo, git_annotated_commit_id(onto))) < 0 || | 
| 672 | 2 |  |  |  |  |  | (error = git_checkout_tree(repo, | 
| 673 | 2 |  |  |  |  |  | (git_object *)onto_commit, &rebase->options.checkout_options)) < 0 || | 
| 674 | 2 |  |  |  |  |  | (error = git_reference_create(&head_ref, repo, GIT_HEAD_FILE, | 
| 675 | 2 |  |  |  |  |  | git_annotated_commit_id(onto), 1, reflog.ptr)) < 0) | 
| 676 |  |  |  |  |  |  | goto done; | 
| 677 |  |  |  |  |  |  |  | 
| 678 |  |  |  |  |  |  | done: | 
| 679 | 2 |  |  |  |  |  | git_reference_free(head_ref); | 
| 680 | 2 |  |  |  |  |  | git_commit_free(onto_commit); | 
| 681 | 2 |  |  |  |  |  | git_str_dispose(&reflog); | 
| 682 | 2 |  |  |  |  |  | git_str_dispose(&state_path); | 
| 683 |  |  |  |  |  |  |  | 
| 684 | 2 |  |  |  |  |  | return error; | 
| 685 |  |  |  |  |  |  | } | 
| 686 |  |  |  |  |  |  |  | 
| 687 | 1 |  |  |  |  |  | static int rebase_init_inmemory( | 
| 688 |  |  |  |  |  |  | git_rebase *rebase, | 
| 689 |  |  |  |  |  |  | git_repository *repo, | 
| 690 |  |  |  |  |  |  | const git_annotated_commit *branch, | 
| 691 |  |  |  |  |  |  | const git_annotated_commit *upstream, | 
| 692 |  |  |  |  |  |  | const git_annotated_commit *onto) | 
| 693 |  |  |  |  |  |  | { | 
| 694 | 1 |  |  |  |  |  | GIT_UNUSED(branch); | 
| 695 | 1 |  |  |  |  |  | GIT_UNUSED(upstream); | 
| 696 |  |  |  |  |  |  |  | 
| 697 | 1 |  |  |  |  |  | return git_commit_lookup( | 
| 698 |  |  |  |  |  |  | &rebase->last_commit, repo, git_annotated_commit_id(onto)); | 
| 699 |  |  |  |  |  |  | } | 
| 700 |  |  |  |  |  |  |  | 
| 701 | 3 |  |  |  |  |  | int git_rebase_init( | 
| 702 |  |  |  |  |  |  | git_rebase **out, | 
| 703 |  |  |  |  |  |  | git_repository *repo, | 
| 704 |  |  |  |  |  |  | const git_annotated_commit *branch, | 
| 705 |  |  |  |  |  |  | const git_annotated_commit *upstream, | 
| 706 |  |  |  |  |  |  | const git_annotated_commit *onto, | 
| 707 |  |  |  |  |  |  | const git_rebase_options *given_opts) | 
| 708 |  |  |  |  |  |  | { | 
| 709 | 3 |  |  |  |  |  | git_rebase *rebase = NULL; | 
| 710 | 3 |  |  |  |  |  | git_annotated_commit *head_branch = NULL; | 
| 711 | 3 |  |  |  |  |  | git_reference *head_ref = NULL; | 
| 712 | 3 | 50 |  |  |  |  | bool inmemory = (given_opts && given_opts->inmemory); | 
|  |  | 100 |  |  |  |  |  | 
| 713 |  |  |  |  |  |  | int error; | 
| 714 |  |  |  |  |  |  |  | 
| 715 | 3 | 50 |  |  |  |  | GIT_ASSERT_ARG(repo); | 
| 716 | 3 | 50 |  |  |  |  | GIT_ASSERT_ARG(upstream || onto); | 
|  |  | 0 |  |  |  |  |  | 
| 717 |  |  |  |  |  |  |  | 
| 718 | 3 |  |  |  |  |  | *out = NULL; | 
| 719 |  |  |  |  |  |  |  | 
| 720 | 3 | 50 |  |  |  |  | if (!onto) | 
| 721 | 0 |  |  |  |  |  | onto = upstream; | 
| 722 |  |  |  |  |  |  |  | 
| 723 | 3 | 50 |  |  |  |  | if ((error = rebase_check_versions(given_opts)) < 0) | 
| 724 | 0 |  |  |  |  |  | goto done; | 
| 725 |  |  |  |  |  |  |  | 
| 726 | 3 | 100 |  |  |  |  | if (!inmemory) { | 
| 727 | 2 | 50 |  |  |  |  | if ((error = git_repository__ensure_not_bare(repo, "rebase")) < 0 || | 
|  |  | 50 |  |  |  |  |  | 
| 728 | 2 | 50 |  |  |  |  | (error = rebase_ensure_not_in_progress(repo)) < 0 || | 
| 729 |  |  |  |  |  |  | (error = rebase_ensure_not_dirty(repo, true, true, GIT_ERROR)) < 0) | 
| 730 |  |  |  |  |  |  | goto done; | 
| 731 |  |  |  |  |  |  | } | 
| 732 |  |  |  |  |  |  |  | 
| 733 | 3 | 50 |  |  |  |  | if (!branch) { | 
| 734 | 0 | 0 |  |  |  |  | if ((error = git_repository_head(&head_ref, repo)) < 0 || | 
|  |  | 0 |  |  |  |  |  | 
| 735 | 0 |  |  |  |  |  | (error = git_annotated_commit_from_ref(&head_branch, repo, head_ref)) < 0) | 
| 736 |  |  |  |  |  |  | goto done; | 
| 737 |  |  |  |  |  |  |  | 
| 738 | 0 |  |  |  |  |  | branch = head_branch; | 
| 739 |  |  |  |  |  |  | } | 
| 740 |  |  |  |  |  |  |  | 
| 741 | 3 | 50 |  |  |  |  | if (rebase_alloc(&rebase, given_opts) < 0) | 
| 742 | 0 |  |  |  |  |  | return -1; | 
| 743 |  |  |  |  |  |  |  | 
| 744 | 3 |  |  |  |  |  | rebase->repo = repo; | 
| 745 | 3 |  |  |  |  |  | rebase->inmemory = inmemory; | 
| 746 | 3 |  |  |  |  |  | rebase->type = GIT_REBASE_MERGE; | 
| 747 |  |  |  |  |  |  |  | 
| 748 | 3 | 50 |  |  |  |  | if ((error = rebase_init_operations(rebase, repo, branch, upstream, onto)) < 0) | 
| 749 | 0 |  |  |  |  |  | goto done; | 
| 750 |  |  |  |  |  |  |  | 
| 751 | 3 | 100 |  |  |  |  | if (inmemory) | 
| 752 | 1 |  |  |  |  |  | error = rebase_init_inmemory(rebase, repo, branch, upstream, onto); | 
| 753 |  |  |  |  |  |  | else | 
| 754 | 2 |  |  |  |  |  | error = rebase_init_merge(rebase, repo, branch ,upstream, onto); | 
| 755 |  |  |  |  |  |  |  | 
| 756 | 3 | 50 |  |  |  |  | if (error == 0) | 
| 757 | 3 |  |  |  |  |  | *out = rebase; | 
| 758 |  |  |  |  |  |  |  | 
| 759 |  |  |  |  |  |  | done: | 
| 760 | 3 |  |  |  |  |  | git_reference_free(head_ref); | 
| 761 | 3 |  |  |  |  |  | git_annotated_commit_free(head_branch); | 
| 762 |  |  |  |  |  |  |  | 
| 763 | 3 | 50 |  |  |  |  | if (error < 0) { | 
| 764 | 0 |  |  |  |  |  | rebase_cleanup(rebase); | 
| 765 | 0 |  |  |  |  |  | git_rebase_free(rebase); | 
| 766 |  |  |  |  |  |  | } | 
| 767 |  |  |  |  |  |  |  | 
| 768 | 3 |  |  |  |  |  | return error; | 
| 769 |  |  |  |  |  |  | } | 
| 770 |  |  |  |  |  |  |  | 
| 771 | 3 |  |  |  |  |  | static void normalize_checkout_options_for_apply( | 
| 772 |  |  |  |  |  |  | git_checkout_options *checkout_opts, | 
| 773 |  |  |  |  |  |  | git_rebase *rebase, | 
| 774 |  |  |  |  |  |  | git_commit *current_commit) | 
| 775 |  |  |  |  |  |  | { | 
| 776 | 3 |  |  |  |  |  | memcpy(checkout_opts, &rebase->options.checkout_options, sizeof(git_checkout_options)); | 
| 777 |  |  |  |  |  |  |  | 
| 778 | 3 | 50 |  |  |  |  | if (!checkout_opts->ancestor_label) | 
| 779 | 3 |  |  |  |  |  | checkout_opts->ancestor_label = "ancestor"; | 
| 780 |  |  |  |  |  |  |  | 
| 781 | 3 | 50 |  |  |  |  | if (rebase->type == GIT_REBASE_MERGE) { | 
| 782 | 3 | 50 |  |  |  |  | if (!checkout_opts->our_label) | 
| 783 | 3 |  |  |  |  |  | checkout_opts->our_label = rebase->onto_name; | 
| 784 |  |  |  |  |  |  |  | 
| 785 | 3 | 50 |  |  |  |  | if (!checkout_opts->their_label) | 
| 786 | 3 |  |  |  |  |  | checkout_opts->their_label = git_commit_summary(current_commit); | 
| 787 |  |  |  |  |  |  | } else { | 
| 788 | 0 |  |  |  |  |  | abort(); | 
| 789 |  |  |  |  |  |  | } | 
| 790 | 3 |  |  |  |  |  | } | 
| 791 |  |  |  |  |  |  |  | 
| 792 | 5 |  |  |  |  |  | GIT_INLINE(int) rebase_movenext(git_rebase *rebase) | 
| 793 |  |  |  |  |  |  | { | 
| 794 | 5 | 100 |  |  |  |  | size_t next = rebase->started ? rebase->current + 1 : 0; | 
| 795 |  |  |  |  |  |  |  | 
| 796 | 5 | 100 |  |  |  |  | if (next == git_array_size(rebase->operations)) | 
| 797 | 1 |  |  |  |  |  | return GIT_ITEROVER; | 
| 798 |  |  |  |  |  |  |  | 
| 799 | 4 |  |  |  |  |  | rebase->started = 1; | 
| 800 | 4 |  |  |  |  |  | rebase->current = next; | 
| 801 |  |  |  |  |  |  |  | 
| 802 | 4 |  |  |  |  |  | return 0; | 
| 803 |  |  |  |  |  |  | } | 
| 804 |  |  |  |  |  |  |  | 
| 805 | 3 |  |  |  |  |  | static int rebase_next_merge( | 
| 806 |  |  |  |  |  |  | git_rebase_operation **out, | 
| 807 |  |  |  |  |  |  | git_rebase *rebase) | 
| 808 |  |  |  |  |  |  | { | 
| 809 | 3 |  |  |  |  |  | git_str path = GIT_STR_INIT; | 
| 810 | 3 |  |  |  |  |  | git_commit *current_commit = NULL, *parent_commit = NULL; | 
| 811 | 3 |  |  |  |  |  | git_tree *current_tree = NULL, *head_tree = NULL, *parent_tree = NULL; | 
| 812 | 3 |  |  |  |  |  | git_index *index = NULL; | 
| 813 | 3 |  |  |  |  |  | git_indexwriter indexwriter = GIT_INDEXWRITER_INIT; | 
| 814 |  |  |  |  |  |  | git_rebase_operation *operation; | 
| 815 |  |  |  |  |  |  | git_checkout_options checkout_opts; | 
| 816 |  |  |  |  |  |  | char current_idstr[GIT_OID_HEXSZ]; | 
| 817 |  |  |  |  |  |  | unsigned int parent_count; | 
| 818 |  |  |  |  |  |  | int error; | 
| 819 |  |  |  |  |  |  |  | 
| 820 | 3 |  |  |  |  |  | *out = NULL; | 
| 821 |  |  |  |  |  |  |  | 
| 822 | 3 | 50 |  |  |  |  | operation = git_array_get(rebase->operations, rebase->current); | 
| 823 |  |  |  |  |  |  |  | 
| 824 | 3 | 50 |  |  |  |  | if ((error = git_commit_lookup(¤t_commit, rebase->repo, &operation->id)) < 0 || | 
|  |  | 50 |  |  |  |  |  | 
| 825 | 3 | 50 |  |  |  |  | (error = git_commit_tree(¤t_tree, current_commit)) < 0 || | 
| 826 | 3 |  |  |  |  |  | (error = git_repository_head_tree(&head_tree, rebase->repo)) < 0) | 
| 827 |  |  |  |  |  |  | goto done; | 
| 828 |  |  |  |  |  |  |  | 
| 829 | 3 | 50 |  |  |  |  | if ((parent_count = git_commit_parentcount(current_commit)) > 1) { | 
| 830 | 0 |  |  |  |  |  | git_error_set(GIT_ERROR_REBASE, "cannot rebase a merge commit"); | 
| 831 | 0 |  |  |  |  |  | error = -1; | 
| 832 | 0 |  |  |  |  |  | goto done; | 
| 833 | 3 | 50 |  |  |  |  | } else if (parent_count) { | 
| 834 | 3 | 50 |  |  |  |  | if ((error = git_commit_parent(&parent_commit, current_commit, 0)) < 0 || | 
|  |  | 50 |  |  |  |  |  | 
| 835 | 3 |  |  |  |  |  | (error = git_commit_tree(&parent_tree, parent_commit)) < 0) | 
| 836 |  |  |  |  |  |  | goto done; | 
| 837 |  |  |  |  |  |  | } | 
| 838 |  |  |  |  |  |  |  | 
| 839 | 3 |  |  |  |  |  | git_oid_fmt(current_idstr, &operation->id); | 
| 840 |  |  |  |  |  |  |  | 
| 841 | 3 |  |  |  |  |  | normalize_checkout_options_for_apply(&checkout_opts, rebase, current_commit); | 
| 842 |  |  |  |  |  |  |  | 
| 843 | 3 | 50 |  |  |  |  | if ((error = git_indexwriter_init_for_operation(&indexwriter, rebase->repo, &checkout_opts.checkout_strategy)) < 0 || | 
|  |  | 50 |  |  |  |  |  | 
| 844 | 3 | 50 |  |  |  |  | (error = rebase_setupfile(rebase, MSGNUM_FILE, 0, "%" PRIuZ "\n", rebase->current+1)) < 0 || | 
| 845 | 3 | 50 |  |  |  |  | (error = rebase_setupfile(rebase, CURRENT_FILE, 0, "%.*s\n", GIT_OID_HEXSZ, current_idstr)) < 0 || | 
| 846 | 3 | 50 |  |  |  |  | (error = git_merge_trees(&index, rebase->repo, parent_tree, head_tree, current_tree, &rebase->options.merge_options)) < 0 || | 
| 847 | 3 | 50 |  |  |  |  | (error = git_merge__check_result(rebase->repo, index)) < 0 || | 
| 848 | 3 | 50 |  |  |  |  | (error = git_checkout_index(rebase->repo, index, &checkout_opts)) < 0 || | 
| 849 |  |  |  |  |  |  | (error = git_indexwriter_commit(&indexwriter)) < 0) | 
| 850 |  |  |  |  |  |  | goto done; | 
| 851 |  |  |  |  |  |  |  | 
| 852 | 3 |  |  |  |  |  | *out = operation; | 
| 853 |  |  |  |  |  |  |  | 
| 854 |  |  |  |  |  |  | done: | 
| 855 | 3 |  |  |  |  |  | git_indexwriter_cleanup(&indexwriter); | 
| 856 | 3 |  |  |  |  |  | git_index_free(index); | 
| 857 | 3 |  |  |  |  |  | git_tree_free(current_tree); | 
| 858 | 3 |  |  |  |  |  | git_tree_free(head_tree); | 
| 859 | 3 |  |  |  |  |  | git_tree_free(parent_tree); | 
| 860 | 3 |  |  |  |  |  | git_commit_free(parent_commit); | 
| 861 | 3 |  |  |  |  |  | git_commit_free(current_commit); | 
| 862 | 3 |  |  |  |  |  | git_str_dispose(&path); | 
| 863 |  |  |  |  |  |  |  | 
| 864 | 3 |  |  |  |  |  | return error; | 
| 865 |  |  |  |  |  |  | } | 
| 866 |  |  |  |  |  |  |  | 
| 867 | 1 |  |  |  |  |  | static int rebase_next_inmemory( | 
| 868 |  |  |  |  |  |  | git_rebase_operation **out, | 
| 869 |  |  |  |  |  |  | git_rebase *rebase) | 
| 870 |  |  |  |  |  |  | { | 
| 871 | 1 |  |  |  |  |  | git_commit *current_commit = NULL, *parent_commit = NULL; | 
| 872 | 1 |  |  |  |  |  | git_tree *current_tree = NULL, *head_tree = NULL, *parent_tree = NULL; | 
| 873 |  |  |  |  |  |  | git_rebase_operation *operation; | 
| 874 | 1 |  |  |  |  |  | git_index *index = NULL; | 
| 875 |  |  |  |  |  |  | unsigned int parent_count; | 
| 876 |  |  |  |  |  |  | int error; | 
| 877 |  |  |  |  |  |  |  | 
| 878 | 1 |  |  |  |  |  | *out = NULL; | 
| 879 |  |  |  |  |  |  |  | 
| 880 | 1 | 50 |  |  |  |  | operation = git_array_get(rebase->operations, rebase->current); | 
| 881 |  |  |  |  |  |  |  | 
| 882 | 1 | 50 |  |  |  |  | if ((error = git_commit_lookup(¤t_commit, rebase->repo, &operation->id)) < 0 || | 
|  |  | 50 |  |  |  |  |  | 
| 883 | 1 |  |  |  |  |  | (error = git_commit_tree(¤t_tree, current_commit)) < 0) | 
| 884 |  |  |  |  |  |  | goto done; | 
| 885 |  |  |  |  |  |  |  | 
| 886 | 1 | 50 |  |  |  |  | if ((parent_count = git_commit_parentcount(current_commit)) > 1) { | 
| 887 | 0 |  |  |  |  |  | git_error_set(GIT_ERROR_REBASE, "cannot rebase a merge commit"); | 
| 888 | 0 |  |  |  |  |  | error = -1; | 
| 889 | 0 |  |  |  |  |  | goto done; | 
| 890 | 1 | 50 |  |  |  |  | } else if (parent_count) { | 
| 891 | 1 | 50 |  |  |  |  | if ((error = git_commit_parent(&parent_commit, current_commit, 0)) < 0 || | 
|  |  | 50 |  |  |  |  |  | 
| 892 | 1 |  |  |  |  |  | (error = git_commit_tree(&parent_tree, parent_commit)) < 0) | 
| 893 |  |  |  |  |  |  | goto done; | 
| 894 |  |  |  |  |  |  | } | 
| 895 |  |  |  |  |  |  |  | 
| 896 | 1 | 50 |  |  |  |  | if ((error = git_commit_tree(&head_tree, rebase->last_commit)) < 0 || | 
|  |  | 50 |  |  |  |  |  | 
| 897 | 1 |  |  |  |  |  | (error = git_merge_trees(&index, rebase->repo, parent_tree, head_tree, current_tree, &rebase->options.merge_options)) < 0) | 
| 898 |  |  |  |  |  |  | goto done; | 
| 899 |  |  |  |  |  |  |  | 
| 900 | 1 | 50 |  |  |  |  | if (!rebase->index) { | 
| 901 | 1 |  |  |  |  |  | rebase->index = index; | 
| 902 | 1 |  |  |  |  |  | index = NULL; | 
| 903 |  |  |  |  |  |  | } else { | 
| 904 | 0 | 0 |  |  |  |  | if ((error = git_index_read_index(rebase->index, index)) < 0) | 
| 905 | 0 |  |  |  |  |  | goto done; | 
| 906 |  |  |  |  |  |  | } | 
| 907 |  |  |  |  |  |  |  | 
| 908 | 1 |  |  |  |  |  | *out = operation; | 
| 909 |  |  |  |  |  |  |  | 
| 910 |  |  |  |  |  |  | done: | 
| 911 | 1 |  |  |  |  |  | git_commit_free(current_commit); | 
| 912 | 1 |  |  |  |  |  | git_commit_free(parent_commit); | 
| 913 | 1 |  |  |  |  |  | git_tree_free(current_tree); | 
| 914 | 1 |  |  |  |  |  | git_tree_free(head_tree); | 
| 915 | 1 |  |  |  |  |  | git_tree_free(parent_tree); | 
| 916 | 1 |  |  |  |  |  | git_index_free(index); | 
| 917 |  |  |  |  |  |  |  | 
| 918 | 1 |  |  |  |  |  | return error; | 
| 919 |  |  |  |  |  |  | } | 
| 920 |  |  |  |  |  |  |  | 
| 921 | 5 |  |  |  |  |  | int git_rebase_next( | 
| 922 |  |  |  |  |  |  | git_rebase_operation **out, | 
| 923 |  |  |  |  |  |  | git_rebase *rebase) | 
| 924 |  |  |  |  |  |  | { | 
| 925 |  |  |  |  |  |  | int error; | 
| 926 |  |  |  |  |  |  |  | 
| 927 | 5 | 50 |  |  |  |  | GIT_ASSERT_ARG(out); | 
| 928 | 5 | 50 |  |  |  |  | GIT_ASSERT_ARG(rebase); | 
| 929 |  |  |  |  |  |  |  | 
| 930 | 5 | 100 |  |  |  |  | if ((error = rebase_movenext(rebase)) < 0) | 
| 931 | 1 |  |  |  |  |  | return error; | 
| 932 |  |  |  |  |  |  |  | 
| 933 | 4 | 100 |  |  |  |  | if (rebase->inmemory) | 
| 934 | 1 |  |  |  |  |  | error = rebase_next_inmemory(out, rebase); | 
| 935 | 3 | 50 |  |  |  |  | else if (rebase->type == GIT_REBASE_MERGE) | 
| 936 | 3 |  |  |  |  |  | error = rebase_next_merge(out, rebase); | 
| 937 |  |  |  |  |  |  | else | 
| 938 | 0 |  |  |  |  |  | abort(); | 
| 939 |  |  |  |  |  |  |  | 
| 940 | 4 |  |  |  |  |  | return error; | 
| 941 |  |  |  |  |  |  | } | 
| 942 |  |  |  |  |  |  |  | 
| 943 | 1 |  |  |  |  |  | int git_rebase_inmemory_index( | 
| 944 |  |  |  |  |  |  | git_index **out, | 
| 945 |  |  |  |  |  |  | git_rebase *rebase) | 
| 946 |  |  |  |  |  |  | { | 
| 947 | 1 | 50 |  |  |  |  | GIT_ASSERT_ARG(out); | 
| 948 | 1 | 50 |  |  |  |  | GIT_ASSERT_ARG(rebase); | 
| 949 | 1 | 50 |  |  |  |  | GIT_ASSERT_ARG(rebase->index); | 
| 950 |  |  |  |  |  |  |  | 
| 951 | 1 |  |  |  |  |  | GIT_REFCOUNT_INC(rebase->index); | 
| 952 | 1 |  |  |  |  |  | *out = rebase->index; | 
| 953 |  |  |  |  |  |  |  | 
| 954 | 1 |  |  |  |  |  | return 0; | 
| 955 |  |  |  |  |  |  | } | 
| 956 |  |  |  |  |  |  |  | 
| 957 |  |  |  |  |  |  | #ifndef GIT_DEPRECATE_HARD | 
| 958 | 0 |  |  |  |  |  | static int create_signed( | 
| 959 |  |  |  |  |  |  | git_oid *out, | 
| 960 |  |  |  |  |  |  | git_rebase *rebase, | 
| 961 |  |  |  |  |  |  | const git_signature *author, | 
| 962 |  |  |  |  |  |  | const git_signature *committer, | 
| 963 |  |  |  |  |  |  | const char *message_encoding, | 
| 964 |  |  |  |  |  |  | const char *message, | 
| 965 |  |  |  |  |  |  | git_tree *tree, | 
| 966 |  |  |  |  |  |  | size_t parent_count, | 
| 967 |  |  |  |  |  |  | const git_commit **parents) | 
| 968 |  |  |  |  |  |  | { | 
| 969 | 0 |  |  |  |  |  | git_str commit_content = GIT_STR_INIT; | 
| 970 | 0 |  |  |  |  |  | git_buf commit_signature = { NULL, 0, 0 }, | 
| 971 | 0 |  |  |  |  |  | signature_field = { NULL, 0, 0 }; | 
| 972 |  |  |  |  |  |  | int error; | 
| 973 |  |  |  |  |  |  |  | 
| 974 | 0 |  |  |  |  |  | git_error_clear(); | 
| 975 |  |  |  |  |  |  |  | 
| 976 | 0 | 0 |  |  |  |  | if ((error = git_commit__create_buffer(&commit_content, | 
| 977 |  |  |  |  |  |  | rebase->repo, author, committer, message_encoding, | 
| 978 |  |  |  |  |  |  | message, tree, parent_count, parents)) < 0) | 
| 979 | 0 |  |  |  |  |  | goto done; | 
| 980 |  |  |  |  |  |  |  | 
| 981 | 0 |  |  |  |  |  | error = rebase->options.signing_cb(&commit_signature, | 
| 982 | 0 |  |  |  |  |  | &signature_field, commit_content.ptr, | 
| 983 |  |  |  |  |  |  | rebase->options.payload); | 
| 984 |  |  |  |  |  |  |  | 
| 985 | 0 | 0 |  |  |  |  | if (error) { | 
| 986 | 0 | 0 |  |  |  |  | if (error != GIT_PASSTHROUGH) | 
| 987 | 0 |  |  |  |  |  | git_error_set_after_callback_function(error, "signing_cb"); | 
| 988 |  |  |  |  |  |  |  | 
| 989 | 0 |  |  |  |  |  | goto done; | 
| 990 |  |  |  |  |  |  | } | 
| 991 |  |  |  |  |  |  |  | 
| 992 | 0 | 0 |  |  |  |  | error = git_commit_create_with_signature(out, rebase->repo, | 
|  |  | 0 |  |  |  |  |  | 
| 993 | 0 |  |  |  |  |  | commit_content.ptr, | 
| 994 | 0 |  |  |  |  |  | commit_signature.size > 0 ? commit_signature.ptr : NULL, | 
| 995 | 0 |  |  |  |  |  | signature_field.size > 0 ? signature_field.ptr : NULL); | 
| 996 |  |  |  |  |  |  |  | 
| 997 |  |  |  |  |  |  | done: | 
| 998 | 0 |  |  |  |  |  | git_buf_dispose(&commit_signature); | 
| 999 | 0 |  |  |  |  |  | git_buf_dispose(&signature_field); | 
| 1000 | 0 |  |  |  |  |  | git_str_dispose(&commit_content); | 
| 1001 | 0 |  |  |  |  |  | return error; | 
| 1002 |  |  |  |  |  |  | } | 
| 1003 |  |  |  |  |  |  | #endif | 
| 1004 |  |  |  |  |  |  |  | 
| 1005 | 3 |  |  |  |  |  | static int rebase_commit__create( | 
| 1006 |  |  |  |  |  |  | git_commit **out, | 
| 1007 |  |  |  |  |  |  | git_rebase *rebase, | 
| 1008 |  |  |  |  |  |  | git_index *index, | 
| 1009 |  |  |  |  |  |  | git_commit *parent_commit, | 
| 1010 |  |  |  |  |  |  | const git_signature *author, | 
| 1011 |  |  |  |  |  |  | const git_signature *committer, | 
| 1012 |  |  |  |  |  |  | const char *message_encoding, | 
| 1013 |  |  |  |  |  |  | const char *message) | 
| 1014 |  |  |  |  |  |  | { | 
| 1015 |  |  |  |  |  |  | git_rebase_operation *operation; | 
| 1016 | 3 |  |  |  |  |  | git_commit *current_commit = NULL, *commit = NULL; | 
| 1017 | 3 |  |  |  |  |  | git_tree *parent_tree = NULL, *tree = NULL; | 
| 1018 |  |  |  |  |  |  | git_oid tree_id, commit_id; | 
| 1019 |  |  |  |  |  |  | int error; | 
| 1020 |  |  |  |  |  |  |  | 
| 1021 | 3 | 50 |  |  |  |  | operation = git_array_get(rebase->operations, rebase->current); | 
| 1022 |  |  |  |  |  |  |  | 
| 1023 | 3 | 50 |  |  |  |  | if (git_index_has_conflicts(index)) { | 
| 1024 | 0 |  |  |  |  |  | git_error_set(GIT_ERROR_REBASE, "conflicts have not been resolved"); | 
| 1025 | 0 |  |  |  |  |  | error = GIT_EUNMERGED; | 
| 1026 | 0 |  |  |  |  |  | goto done; | 
| 1027 |  |  |  |  |  |  | } | 
| 1028 |  |  |  |  |  |  |  | 
| 1029 | 3 | 50 |  |  |  |  | if ((error = git_commit_lookup(¤t_commit, rebase->repo, &operation->id)) < 0 || | 
|  |  | 50 |  |  |  |  |  | 
| 1030 | 3 | 50 |  |  |  |  | (error = git_commit_tree(&parent_tree, parent_commit)) < 0 || | 
| 1031 | 3 | 50 |  |  |  |  | (error = git_index_write_tree_to(&tree_id, index, rebase->repo)) < 0 || | 
| 1032 | 3 |  |  |  |  |  | (error = git_tree_lookup(&tree, rebase->repo, &tree_id)) < 0) | 
| 1033 |  |  |  |  |  |  | goto done; | 
| 1034 |  |  |  |  |  |  |  | 
| 1035 | 3 | 50 |  |  |  |  | if (git_oid_equal(&tree_id, git_tree_id(parent_tree))) { | 
| 1036 | 0 |  |  |  |  |  | git_error_set(GIT_ERROR_REBASE, "this patch has already been applied"); | 
| 1037 | 0 |  |  |  |  |  | error = GIT_EAPPLIED; | 
| 1038 | 0 |  |  |  |  |  | goto done; | 
| 1039 |  |  |  |  |  |  | } | 
| 1040 |  |  |  |  |  |  |  | 
| 1041 | 3 | 50 |  |  |  |  | if (!author) | 
| 1042 | 0 |  |  |  |  |  | author = git_commit_author(current_commit); | 
| 1043 |  |  |  |  |  |  |  | 
| 1044 | 3 | 50 |  |  |  |  | if (!message) { | 
| 1045 | 3 |  |  |  |  |  | message_encoding = git_commit_message_encoding(current_commit); | 
| 1046 | 3 |  |  |  |  |  | message = git_commit_message(current_commit); | 
| 1047 |  |  |  |  |  |  | } | 
| 1048 |  |  |  |  |  |  |  | 
| 1049 | 3 |  |  |  |  |  | git_error_clear(); | 
| 1050 | 3 |  |  |  |  |  | error = GIT_PASSTHROUGH; | 
| 1051 |  |  |  |  |  |  |  | 
| 1052 | 3 | 50 |  |  |  |  | if (rebase->options.commit_create_cb) { | 
| 1053 | 0 |  |  |  |  |  | error = rebase->options.commit_create_cb(&commit_id, | 
| 1054 |  |  |  |  |  |  | author, committer, message_encoding, message, | 
| 1055 |  |  |  |  |  |  | tree, 1, (const git_commit **)&parent_commit, | 
| 1056 |  |  |  |  |  |  | rebase->options.payload); | 
| 1057 |  |  |  |  |  |  |  | 
| 1058 | 0 |  |  |  |  |  | git_error_set_after_callback_function(error, | 
| 1059 |  |  |  |  |  |  | "commit_create_cb"); | 
| 1060 |  |  |  |  |  |  | } | 
| 1061 |  |  |  |  |  |  | #ifndef GIT_DEPRECATE_HARD | 
| 1062 | 3 | 50 |  |  |  |  | else if (rebase->options.signing_cb) { | 
| 1063 | 0 |  |  |  |  |  | error = create_signed(&commit_id, rebase, author, | 
| 1064 |  |  |  |  |  |  | committer, message_encoding, message, tree, | 
| 1065 |  |  |  |  |  |  | 1, (const git_commit **)&parent_commit); | 
| 1066 |  |  |  |  |  |  | } | 
| 1067 |  |  |  |  |  |  | #endif | 
| 1068 |  |  |  |  |  |  |  | 
| 1069 | 3 | 50 |  |  |  |  | if (error == GIT_PASSTHROUGH) | 
| 1070 | 3 |  |  |  |  |  | error = git_commit_create(&commit_id, rebase->repo, NULL, | 
| 1071 |  |  |  |  |  |  | author, committer, message_encoding, message, | 
| 1072 |  |  |  |  |  |  | tree, 1, (const git_commit **)&parent_commit); | 
| 1073 |  |  |  |  |  |  |  | 
| 1074 | 3 | 50 |  |  |  |  | if (error) | 
| 1075 | 0 |  |  |  |  |  | goto done; | 
| 1076 |  |  |  |  |  |  |  | 
| 1077 | 3 | 50 |  |  |  |  | if ((error = git_commit_lookup(&commit, rebase->repo, &commit_id)) < 0) | 
| 1078 | 0 |  |  |  |  |  | goto done; | 
| 1079 |  |  |  |  |  |  |  | 
| 1080 | 3 |  |  |  |  |  | *out = commit; | 
| 1081 |  |  |  |  |  |  |  | 
| 1082 |  |  |  |  |  |  | done: | 
| 1083 | 3 | 50 |  |  |  |  | if (error < 0) | 
| 1084 | 0 |  |  |  |  |  | git_commit_free(commit); | 
| 1085 |  |  |  |  |  |  |  | 
| 1086 | 3 |  |  |  |  |  | git_commit_free(current_commit); | 
| 1087 | 3 |  |  |  |  |  | git_tree_free(parent_tree); | 
| 1088 | 3 |  |  |  |  |  | git_tree_free(tree); | 
| 1089 |  |  |  |  |  |  |  | 
| 1090 | 3 |  |  |  |  |  | return error; | 
| 1091 |  |  |  |  |  |  | } | 
| 1092 |  |  |  |  |  |  |  | 
| 1093 | 3 |  |  |  |  |  | static int rebase_commit_merge( | 
| 1094 |  |  |  |  |  |  | git_oid *commit_id, | 
| 1095 |  |  |  |  |  |  | git_rebase *rebase, | 
| 1096 |  |  |  |  |  |  | const git_signature *author, | 
| 1097 |  |  |  |  |  |  | const git_signature *committer, | 
| 1098 |  |  |  |  |  |  | const char *message_encoding, | 
| 1099 |  |  |  |  |  |  | const char *message) | 
| 1100 |  |  |  |  |  |  | { | 
| 1101 |  |  |  |  |  |  | git_rebase_operation *operation; | 
| 1102 | 3 |  |  |  |  |  | git_reference *head = NULL; | 
| 1103 | 3 |  |  |  |  |  | git_commit *head_commit = NULL, *commit = NULL; | 
| 1104 | 3 |  |  |  |  |  | git_index *index = NULL; | 
| 1105 |  |  |  |  |  |  | char old_idstr[GIT_OID_HEXSZ], new_idstr[GIT_OID_HEXSZ]; | 
| 1106 |  |  |  |  |  |  | int error; | 
| 1107 |  |  |  |  |  |  |  | 
| 1108 | 3 | 50 |  |  |  |  | operation = git_array_get(rebase->operations, rebase->current); | 
| 1109 | 3 | 50 |  |  |  |  | GIT_ASSERT(operation); | 
| 1110 |  |  |  |  |  |  |  | 
| 1111 | 3 | 50 |  |  |  |  | if ((error = rebase_ensure_not_dirty(rebase->repo, false, true, GIT_EUNMERGED)) < 0 || | 
|  |  | 50 |  |  |  |  |  | 
| 1112 | 3 | 50 |  |  |  |  | (error = git_repository_head(&head, rebase->repo)) < 0 || | 
| 1113 | 3 | 50 |  |  |  |  | (error = git_reference_peel((git_object **)&head_commit, head, GIT_OBJECT_COMMIT)) < 0 || | 
| 1114 | 3 | 50 |  |  |  |  | (error = git_repository_index(&index, rebase->repo)) < 0 || | 
| 1115 | 3 |  |  |  |  |  | (error = rebase_commit__create(&commit, rebase, index, head_commit, | 
| 1116 | 3 | 50 |  |  |  |  | author, committer, message_encoding, message)) < 0 || | 
| 1117 | 3 |  |  |  |  |  | (error = git_reference__update_for_commit( | 
| 1118 |  |  |  |  |  |  | rebase->repo, NULL, "HEAD", git_commit_id(commit), "rebase")) < 0) | 
| 1119 |  |  |  |  |  |  | goto done; | 
| 1120 |  |  |  |  |  |  |  | 
| 1121 | 3 |  |  |  |  |  | git_oid_fmt(old_idstr, &operation->id); | 
| 1122 | 3 |  |  |  |  |  | git_oid_fmt(new_idstr, git_commit_id(commit)); | 
| 1123 |  |  |  |  |  |  |  | 
| 1124 | 3 | 50 |  |  |  |  | if ((error = rebase_setupfile(rebase, REWRITTEN_FILE, O_CREAT|O_WRONLY|O_APPEND, | 
| 1125 |  |  |  |  |  |  | "%.*s %.*s\n", GIT_OID_HEXSZ, old_idstr, GIT_OID_HEXSZ, new_idstr)) < 0) | 
| 1126 | 0 |  |  |  |  |  | goto done; | 
| 1127 |  |  |  |  |  |  |  | 
| 1128 | 3 |  |  |  |  |  | git_oid_cpy(commit_id, git_commit_id(commit)); | 
| 1129 |  |  |  |  |  |  |  | 
| 1130 |  |  |  |  |  |  | done: | 
| 1131 | 3 |  |  |  |  |  | git_index_free(index); | 
| 1132 | 3 |  |  |  |  |  | git_reference_free(head); | 
| 1133 | 3 |  |  |  |  |  | git_commit_free(head_commit); | 
| 1134 | 3 |  |  |  |  |  | git_commit_free(commit); | 
| 1135 | 3 |  |  |  |  |  | return error; | 
| 1136 |  |  |  |  |  |  | } | 
| 1137 |  |  |  |  |  |  |  | 
| 1138 | 0 |  |  |  |  |  | static int rebase_commit_inmemory( | 
| 1139 |  |  |  |  |  |  | git_oid *commit_id, | 
| 1140 |  |  |  |  |  |  | git_rebase *rebase, | 
| 1141 |  |  |  |  |  |  | const git_signature *author, | 
| 1142 |  |  |  |  |  |  | const git_signature *committer, | 
| 1143 |  |  |  |  |  |  | const char *message_encoding, | 
| 1144 |  |  |  |  |  |  | const char *message) | 
| 1145 |  |  |  |  |  |  | { | 
| 1146 | 0 |  |  |  |  |  | git_commit *commit = NULL; | 
| 1147 | 0 |  |  |  |  |  | int error = 0; | 
| 1148 |  |  |  |  |  |  |  | 
| 1149 | 0 | 0 |  |  |  |  | GIT_ASSERT_ARG(rebase->index); | 
| 1150 | 0 | 0 |  |  |  |  | GIT_ASSERT_ARG(rebase->last_commit); | 
| 1151 | 0 | 0 |  |  |  |  | GIT_ASSERT_ARG(rebase->current < rebase->operations.size); | 
| 1152 |  |  |  |  |  |  |  | 
| 1153 | 0 | 0 |  |  |  |  | if ((error = rebase_commit__create(&commit, rebase, rebase->index, | 
| 1154 |  |  |  |  |  |  | rebase->last_commit, author, committer, message_encoding, message)) < 0) | 
| 1155 | 0 |  |  |  |  |  | goto done; | 
| 1156 |  |  |  |  |  |  |  | 
| 1157 | 0 |  |  |  |  |  | git_commit_free(rebase->last_commit); | 
| 1158 | 0 |  |  |  |  |  | rebase->last_commit = commit; | 
| 1159 |  |  |  |  |  |  |  | 
| 1160 | 0 |  |  |  |  |  | git_oid_cpy(commit_id, git_commit_id(commit)); | 
| 1161 |  |  |  |  |  |  |  | 
| 1162 |  |  |  |  |  |  | done: | 
| 1163 | 0 | 0 |  |  |  |  | if (error < 0) | 
| 1164 | 0 |  |  |  |  |  | git_commit_free(commit); | 
| 1165 |  |  |  |  |  |  |  | 
| 1166 | 0 |  |  |  |  |  | return error; | 
| 1167 |  |  |  |  |  |  | } | 
| 1168 |  |  |  |  |  |  |  | 
| 1169 | 3 |  |  |  |  |  | int git_rebase_commit( | 
| 1170 |  |  |  |  |  |  | git_oid *id, | 
| 1171 |  |  |  |  |  |  | git_rebase *rebase, | 
| 1172 |  |  |  |  |  |  | const git_signature *author, | 
| 1173 |  |  |  |  |  |  | const git_signature *committer, | 
| 1174 |  |  |  |  |  |  | const char *message_encoding, | 
| 1175 |  |  |  |  |  |  | const char *message) | 
| 1176 |  |  |  |  |  |  | { | 
| 1177 |  |  |  |  |  |  | int error; | 
| 1178 |  |  |  |  |  |  |  | 
| 1179 | 3 | 50 |  |  |  |  | GIT_ASSERT_ARG(rebase); | 
| 1180 | 3 | 50 |  |  |  |  | GIT_ASSERT_ARG(committer); | 
| 1181 |  |  |  |  |  |  |  | 
| 1182 | 3 | 50 |  |  |  |  | if (rebase->inmemory) | 
| 1183 | 0 |  |  |  |  |  | error = rebase_commit_inmemory( | 
| 1184 |  |  |  |  |  |  | id, rebase, author, committer, message_encoding, message); | 
| 1185 | 3 | 50 |  |  |  |  | else if (rebase->type == GIT_REBASE_MERGE) | 
| 1186 | 3 |  |  |  |  |  | error = rebase_commit_merge( | 
| 1187 |  |  |  |  |  |  | id, rebase, author, committer, message_encoding, message); | 
| 1188 |  |  |  |  |  |  | else | 
| 1189 | 0 |  |  |  |  |  | abort(); | 
| 1190 |  |  |  |  |  |  |  | 
| 1191 | 3 |  |  |  |  |  | return error; | 
| 1192 |  |  |  |  |  |  | } | 
| 1193 |  |  |  |  |  |  |  | 
| 1194 | 1 |  |  |  |  |  | int git_rebase_abort(git_rebase *rebase) | 
| 1195 |  |  |  |  |  |  | { | 
| 1196 | 1 |  |  |  |  |  | git_reference *orig_head_ref = NULL; | 
| 1197 | 1 |  |  |  |  |  | git_commit *orig_head_commit = NULL; | 
| 1198 |  |  |  |  |  |  | int error; | 
| 1199 |  |  |  |  |  |  |  | 
| 1200 | 1 | 50 |  |  |  |  | GIT_ASSERT_ARG(rebase); | 
| 1201 |  |  |  |  |  |  |  | 
| 1202 | 1 | 50 |  |  |  |  | if (rebase->inmemory) | 
| 1203 | 0 |  |  |  |  |  | return 0; | 
| 1204 |  |  |  |  |  |  |  | 
| 1205 | 2 |  |  |  |  |  | error = rebase->head_detached ? | 
| 1206 | 1 |  |  |  |  |  | git_reference_create(&orig_head_ref, rebase->repo, GIT_HEAD_FILE, | 
| 1207 | 1 | 50 |  |  |  |  | &rebase->orig_head_id, 1, "rebase: aborting") : | 
| 1208 | 0 |  |  |  |  |  | git_reference_symbolic_create( | 
| 1209 | 0 |  |  |  |  |  | &orig_head_ref, rebase->repo, GIT_HEAD_FILE, rebase->orig_head_name, 1, | 
| 1210 |  |  |  |  |  |  | "rebase: aborting"); | 
| 1211 |  |  |  |  |  |  |  | 
| 1212 | 1 | 50 |  |  |  |  | if (error < 0) | 
| 1213 | 0 |  |  |  |  |  | goto done; | 
| 1214 |  |  |  |  |  |  |  | 
| 1215 | 1 | 50 |  |  |  |  | if ((error = git_commit_lookup( | 
| 1216 | 1 | 50 |  |  |  |  | &orig_head_commit, rebase->repo, &rebase->orig_head_id)) < 0 || | 
| 1217 | 1 |  |  |  |  |  | (error = git_reset(rebase->repo, (git_object *)orig_head_commit, | 
| 1218 | 1 |  |  |  |  |  | GIT_RESET_HARD, &rebase->options.checkout_options)) < 0) | 
| 1219 |  |  |  |  |  |  | goto done; | 
| 1220 |  |  |  |  |  |  |  | 
| 1221 | 1 |  |  |  |  |  | error = rebase_cleanup(rebase); | 
| 1222 |  |  |  |  |  |  |  | 
| 1223 |  |  |  |  |  |  | done: | 
| 1224 | 1 |  |  |  |  |  | git_commit_free(orig_head_commit); | 
| 1225 | 1 |  |  |  |  |  | git_reference_free(orig_head_ref); | 
| 1226 |  |  |  |  |  |  |  | 
| 1227 | 1 |  |  |  |  |  | return error; | 
| 1228 |  |  |  |  |  |  | } | 
| 1229 |  |  |  |  |  |  |  | 
| 1230 | 1 |  |  |  |  |  | static int notes_ref_lookup(git_str *out, git_rebase *rebase) | 
| 1231 |  |  |  |  |  |  | { | 
| 1232 | 1 |  |  |  |  |  | git_config *config = NULL; | 
| 1233 |  |  |  |  |  |  | int do_rewrite, error; | 
| 1234 |  |  |  |  |  |  |  | 
| 1235 | 1 | 50 |  |  |  |  | if (rebase->options.rewrite_notes_ref) { | 
| 1236 | 0 |  |  |  |  |  | git_str_attach_notowned(out, | 
| 1237 |  |  |  |  |  |  | rebase->options.rewrite_notes_ref, | 
| 1238 |  |  |  |  |  |  | strlen(rebase->options.rewrite_notes_ref)); | 
| 1239 | 0 |  |  |  |  |  | return 0; | 
| 1240 |  |  |  |  |  |  | } | 
| 1241 |  |  |  |  |  |  |  | 
| 1242 | 1 | 50 |  |  |  |  | if ((error = git_repository_config(&config, rebase->repo)) < 0 || | 
|  |  | 50 |  |  |  |  |  | 
| 1243 | 1 |  |  |  |  |  | (error = git_config_get_bool(&do_rewrite, config, "notes.rewrite.rebase")) < 0) { | 
| 1244 |  |  |  |  |  |  |  | 
| 1245 | 1 | 50 |  |  |  |  | if (error != GIT_ENOTFOUND) | 
| 1246 | 0 |  |  |  |  |  | goto done; | 
| 1247 |  |  |  |  |  |  |  | 
| 1248 | 1 |  |  |  |  |  | git_error_clear(); | 
| 1249 | 1 |  |  |  |  |  | do_rewrite = 1; | 
| 1250 |  |  |  |  |  |  | } | 
| 1251 |  |  |  |  |  |  |  | 
| 1252 | 1 |  |  |  |  |  | error = do_rewrite ? | 
| 1253 | 1 | 50 |  |  |  |  | git_config__get_string_buf(out, config, "notes.rewriteref") : | 
| 1254 |  |  |  |  |  |  | GIT_ENOTFOUND; | 
| 1255 |  |  |  |  |  |  |  | 
| 1256 |  |  |  |  |  |  | done: | 
| 1257 | 1 |  |  |  |  |  | git_config_free(config); | 
| 1258 | 1 |  |  |  |  |  | return error; | 
| 1259 |  |  |  |  |  |  | } | 
| 1260 |  |  |  |  |  |  |  | 
| 1261 | 0 |  |  |  |  |  | static int rebase_copy_note( | 
| 1262 |  |  |  |  |  |  | git_rebase *rebase, | 
| 1263 |  |  |  |  |  |  | const char *notes_ref, | 
| 1264 |  |  |  |  |  |  | git_oid *from, | 
| 1265 |  |  |  |  |  |  | git_oid *to, | 
| 1266 |  |  |  |  |  |  | const git_signature *committer) | 
| 1267 |  |  |  |  |  |  | { | 
| 1268 | 0 |  |  |  |  |  | git_note *note = NULL; | 
| 1269 |  |  |  |  |  |  | git_oid note_id; | 
| 1270 | 0 |  |  |  |  |  | git_signature *who = NULL; | 
| 1271 |  |  |  |  |  |  | int error; | 
| 1272 |  |  |  |  |  |  |  | 
| 1273 | 0 | 0 |  |  |  |  | if ((error = git_note_read(¬e, rebase->repo, notes_ref, from)) < 0) { | 
| 1274 | 0 | 0 |  |  |  |  | if (error == GIT_ENOTFOUND) { | 
| 1275 | 0 |  |  |  |  |  | git_error_clear(); | 
| 1276 | 0 |  |  |  |  |  | error = 0; | 
| 1277 |  |  |  |  |  |  | } | 
| 1278 |  |  |  |  |  |  |  | 
| 1279 | 0 |  |  |  |  |  | goto done; | 
| 1280 |  |  |  |  |  |  | } | 
| 1281 |  |  |  |  |  |  |  | 
| 1282 | 0 | 0 |  |  |  |  | if (!committer) { | 
| 1283 | 0 | 0 |  |  |  |  | if((error = git_signature_default(&who, rebase->repo)) < 0) { | 
| 1284 | 0 | 0 |  |  |  |  | if (error != GIT_ENOTFOUND || | 
|  |  | 0 |  |  |  |  |  | 
| 1285 |  |  |  |  |  |  | (error = git_signature_now(&who, "unknown", "unknown")) < 0) | 
| 1286 |  |  |  |  |  |  | goto done; | 
| 1287 |  |  |  |  |  |  |  | 
| 1288 | 0 |  |  |  |  |  | git_error_clear(); | 
| 1289 |  |  |  |  |  |  | } | 
| 1290 |  |  |  |  |  |  |  | 
| 1291 | 0 |  |  |  |  |  | committer = who; | 
| 1292 |  |  |  |  |  |  | } | 
| 1293 |  |  |  |  |  |  |  | 
| 1294 | 0 |  |  |  |  |  | error = git_note_create(¬e_id, rebase->repo, notes_ref, | 
| 1295 |  |  |  |  |  |  | git_note_author(note), committer, to, git_note_message(note), 0); | 
| 1296 |  |  |  |  |  |  |  | 
| 1297 |  |  |  |  |  |  | done: | 
| 1298 | 0 |  |  |  |  |  | git_note_free(note); | 
| 1299 | 0 |  |  |  |  |  | git_signature_free(who); | 
| 1300 |  |  |  |  |  |  |  | 
| 1301 | 0 |  |  |  |  |  | return error; | 
| 1302 |  |  |  |  |  |  | } | 
| 1303 |  |  |  |  |  |  |  | 
| 1304 | 1 |  |  |  |  |  | static int rebase_copy_notes( | 
| 1305 |  |  |  |  |  |  | git_rebase *rebase, | 
| 1306 |  |  |  |  |  |  | const git_signature *committer) | 
| 1307 |  |  |  |  |  |  | { | 
| 1308 | 1 |  |  |  |  |  | git_str path = GIT_STR_INIT, rewritten = GIT_STR_INIT, notes_ref = GIT_STR_INIT; | 
| 1309 |  |  |  |  |  |  | char *pair_list, *fromstr, *tostr, *end; | 
| 1310 |  |  |  |  |  |  | git_oid from, to; | 
| 1311 | 1 |  |  |  |  |  | unsigned int linenum = 1; | 
| 1312 | 1 |  |  |  |  |  | int error = 0; | 
| 1313 |  |  |  |  |  |  |  | 
| 1314 | 1 | 50 |  |  |  |  | if ((error = notes_ref_lookup(¬es_ref, rebase)) < 0) { | 
| 1315 | 1 | 50 |  |  |  |  | if (error == GIT_ENOTFOUND) { | 
| 1316 | 1 |  |  |  |  |  | git_error_clear(); | 
| 1317 | 1 |  |  |  |  |  | error = 0; | 
| 1318 |  |  |  |  |  |  | } | 
| 1319 |  |  |  |  |  |  |  | 
| 1320 | 1 |  |  |  |  |  | goto done; | 
| 1321 |  |  |  |  |  |  | } | 
| 1322 |  |  |  |  |  |  |  | 
| 1323 | 0 | 0 |  |  |  |  | if ((error = git_str_joinpath(&path, rebase->state_path, REWRITTEN_FILE)) < 0 || | 
|  |  | 0 |  |  |  |  |  | 
| 1324 | 0 |  |  |  |  |  | (error = git_futils_readbuffer(&rewritten, path.ptr)) < 0) | 
| 1325 |  |  |  |  |  |  | goto done; | 
| 1326 |  |  |  |  |  |  |  | 
| 1327 | 0 |  |  |  |  |  | pair_list = rewritten.ptr; | 
| 1328 |  |  |  |  |  |  |  | 
| 1329 | 0 | 0 |  |  |  |  | while (*pair_list) { | 
| 1330 | 0 |  |  |  |  |  | fromstr = pair_list; | 
| 1331 |  |  |  |  |  |  |  | 
| 1332 | 0 | 0 |  |  |  |  | if ((end = strchr(fromstr, '\n')) == NULL) | 
| 1333 | 0 |  |  |  |  |  | goto on_error; | 
| 1334 |  |  |  |  |  |  |  | 
| 1335 | 0 |  |  |  |  |  | pair_list = end+1; | 
| 1336 | 0 |  |  |  |  |  | *end = '\0'; | 
| 1337 |  |  |  |  |  |  |  | 
| 1338 | 0 | 0 |  |  |  |  | if ((end = strchr(fromstr, ' ')) == NULL) | 
| 1339 | 0 |  |  |  |  |  | goto on_error; | 
| 1340 |  |  |  |  |  |  |  | 
| 1341 | 0 |  |  |  |  |  | tostr = end+1; | 
| 1342 | 0 |  |  |  |  |  | *end = '\0'; | 
| 1343 |  |  |  |  |  |  |  | 
| 1344 | 0 | 0 |  |  |  |  | if (strlen(fromstr) != GIT_OID_HEXSZ || | 
|  |  | 0 |  |  |  |  |  | 
| 1345 | 0 | 0 |  |  |  |  | strlen(tostr) != GIT_OID_HEXSZ || | 
| 1346 | 0 | 0 |  |  |  |  | git_oid_fromstr(&from, fromstr) < 0 || | 
| 1347 | 0 |  |  |  |  |  | git_oid_fromstr(&to, tostr) < 0) | 
| 1348 |  |  |  |  |  |  | goto on_error; | 
| 1349 |  |  |  |  |  |  |  | 
| 1350 | 0 | 0 |  |  |  |  | if ((error = rebase_copy_note(rebase, notes_ref.ptr, &from, &to, committer)) < 0) | 
| 1351 | 0 |  |  |  |  |  | goto done; | 
| 1352 |  |  |  |  |  |  |  | 
| 1353 | 0 |  |  |  |  |  | linenum++; | 
| 1354 |  |  |  |  |  |  | } | 
| 1355 |  |  |  |  |  |  |  | 
| 1356 | 0 |  |  |  |  |  | goto done; | 
| 1357 |  |  |  |  |  |  |  | 
| 1358 |  |  |  |  |  |  | on_error: | 
| 1359 | 0 |  |  |  |  |  | git_error_set(GIT_ERROR_REBASE, "invalid rewritten file at line %d", linenum); | 
| 1360 | 0 |  |  |  |  |  | error = -1; | 
| 1361 |  |  |  |  |  |  |  | 
| 1362 |  |  |  |  |  |  | done: | 
| 1363 | 1 |  |  |  |  |  | git_str_dispose(&rewritten); | 
| 1364 | 1 |  |  |  |  |  | git_str_dispose(&path); | 
| 1365 | 1 |  |  |  |  |  | git_str_dispose(¬es_ref); | 
| 1366 |  |  |  |  |  |  |  | 
| 1367 | 1 |  |  |  |  |  | return error; | 
| 1368 |  |  |  |  |  |  | } | 
| 1369 |  |  |  |  |  |  |  | 
| 1370 | 0 |  |  |  |  |  | static int return_to_orig_head(git_rebase *rebase) | 
| 1371 |  |  |  |  |  |  | { | 
| 1372 | 0 |  |  |  |  |  | git_reference *terminal_ref = NULL, *branch_ref = NULL, *head_ref = NULL; | 
| 1373 | 0 |  |  |  |  |  | git_commit *terminal_commit = NULL; | 
| 1374 | 0 |  |  |  |  |  | git_str branch_msg = GIT_STR_INIT, head_msg = GIT_STR_INIT; | 
| 1375 |  |  |  |  |  |  | char onto[GIT_OID_HEXSZ]; | 
| 1376 | 0 |  |  |  |  |  | int error = 0; | 
| 1377 |  |  |  |  |  |  |  | 
| 1378 | 0 |  |  |  |  |  | git_oid_fmt(onto, &rebase->onto_id); | 
| 1379 |  |  |  |  |  |  |  | 
| 1380 | 0 | 0 |  |  |  |  | if ((error = git_str_printf(&branch_msg, | 
| 1381 |  |  |  |  |  |  | "rebase finished: %s onto %.*s", | 
| 1382 | 0 | 0 |  |  |  |  | rebase->orig_head_name, GIT_OID_HEXSZ, onto)) == 0 && | 
| 1383 | 0 |  |  |  |  |  | (error = git_str_printf(&head_msg, | 
| 1384 |  |  |  |  |  |  | "rebase finished: returning to %s", | 
| 1385 | 0 | 0 |  |  |  |  | rebase->orig_head_name)) == 0 && | 
| 1386 | 0 | 0 |  |  |  |  | (error = git_repository_head(&terminal_ref, rebase->repo)) == 0 && | 
| 1387 | 0 |  |  |  |  |  | (error = git_reference_peel((git_object **)&terminal_commit, | 
| 1388 | 0 | 0 |  |  |  |  | terminal_ref, GIT_OBJECT_COMMIT)) == 0 && | 
| 1389 | 0 |  |  |  |  |  | (error = git_reference_create_matching(&branch_ref, | 
| 1390 | 0 |  |  |  |  |  | rebase->repo, rebase->orig_head_name, | 
| 1391 |  |  |  |  |  |  | git_commit_id(terminal_commit), 1, | 
| 1392 | 0 |  |  |  |  |  | &rebase->orig_head_id, branch_msg.ptr)) == 0) | 
| 1393 | 0 |  |  |  |  |  | error = git_reference_symbolic_create(&head_ref, | 
| 1394 | 0 |  |  |  |  |  | rebase->repo, GIT_HEAD_FILE, rebase->orig_head_name, 1, | 
| 1395 | 0 |  |  |  |  |  | head_msg.ptr); | 
| 1396 |  |  |  |  |  |  |  | 
| 1397 | 0 |  |  |  |  |  | git_str_dispose(&head_msg); | 
| 1398 | 0 |  |  |  |  |  | git_str_dispose(&branch_msg); | 
| 1399 | 0 |  |  |  |  |  | git_commit_free(terminal_commit); | 
| 1400 | 0 |  |  |  |  |  | git_reference_free(head_ref); | 
| 1401 | 0 |  |  |  |  |  | git_reference_free(branch_ref); | 
| 1402 | 0 |  |  |  |  |  | git_reference_free(terminal_ref); | 
| 1403 |  |  |  |  |  |  |  | 
| 1404 | 0 |  |  |  |  |  | return error; | 
| 1405 |  |  |  |  |  |  | } | 
| 1406 |  |  |  |  |  |  |  | 
| 1407 | 1 |  |  |  |  |  | int git_rebase_finish( | 
| 1408 |  |  |  |  |  |  | git_rebase *rebase, | 
| 1409 |  |  |  |  |  |  | const git_signature *signature) | 
| 1410 |  |  |  |  |  |  | { | 
| 1411 | 1 |  |  |  |  |  | int error = 0; | 
| 1412 |  |  |  |  |  |  |  | 
| 1413 | 1 | 50 |  |  |  |  | GIT_ASSERT_ARG(rebase); | 
| 1414 |  |  |  |  |  |  |  | 
| 1415 | 1 | 50 |  |  |  |  | if (rebase->inmemory) | 
| 1416 | 0 |  |  |  |  |  | return 0; | 
| 1417 |  |  |  |  |  |  |  | 
| 1418 | 1 | 50 |  |  |  |  | if (!rebase->head_detached) | 
| 1419 | 0 |  |  |  |  |  | error = return_to_orig_head(rebase); | 
| 1420 |  |  |  |  |  |  |  | 
| 1421 | 1 | 50 |  |  |  |  | if (error == 0 && (error = rebase_copy_notes(rebase, signature)) == 0) | 
|  |  | 50 |  |  |  |  |  | 
| 1422 | 1 |  |  |  |  |  | error = rebase_cleanup(rebase); | 
| 1423 |  |  |  |  |  |  |  | 
| 1424 | 1 |  |  |  |  |  | return error; | 
| 1425 |  |  |  |  |  |  | } | 
| 1426 |  |  |  |  |  |  |  | 
| 1427 | 1 |  |  |  |  |  | const char *git_rebase_orig_head_name(git_rebase *rebase) { | 
| 1428 | 1 | 50 |  |  |  |  | GIT_ASSERT_ARG_WITH_RETVAL(rebase, NULL); | 
| 1429 | 1 |  |  |  |  |  | return rebase->orig_head_name; | 
| 1430 |  |  |  |  |  |  | } | 
| 1431 |  |  |  |  |  |  |  | 
| 1432 | 1 |  |  |  |  |  | const git_oid *git_rebase_orig_head_id(git_rebase *rebase) { | 
| 1433 | 1 | 50 |  |  |  |  | GIT_ASSERT_ARG_WITH_RETVAL(rebase, NULL); | 
| 1434 | 1 |  |  |  |  |  | return &rebase->orig_head_id; | 
| 1435 |  |  |  |  |  |  | } | 
| 1436 |  |  |  |  |  |  |  | 
| 1437 | 1 |  |  |  |  |  | const char *git_rebase_onto_name(git_rebase *rebase) { | 
| 1438 | 1 | 50 |  |  |  |  | GIT_ASSERT_ARG_WITH_RETVAL(rebase, NULL); | 
| 1439 | 1 |  |  |  |  |  | return rebase->onto_name; | 
| 1440 |  |  |  |  |  |  | } | 
| 1441 |  |  |  |  |  |  |  | 
| 1442 | 1 |  |  |  |  |  | const git_oid *git_rebase_onto_id(git_rebase *rebase) { | 
| 1443 | 1 |  |  |  |  |  | return &rebase->onto_id; | 
| 1444 |  |  |  |  |  |  | } | 
| 1445 |  |  |  |  |  |  |  | 
| 1446 | 10 |  |  |  |  |  | size_t git_rebase_operation_entrycount(git_rebase *rebase) | 
| 1447 |  |  |  |  |  |  | { | 
| 1448 | 10 | 50 |  |  |  |  | GIT_ASSERT_ARG_WITH_RETVAL(rebase, 0); | 
| 1449 |  |  |  |  |  |  |  | 
| 1450 | 10 |  |  |  |  |  | return git_array_size(rebase->operations); | 
| 1451 |  |  |  |  |  |  | } | 
| 1452 |  |  |  |  |  |  |  | 
| 1453 | 3 |  |  |  |  |  | size_t git_rebase_operation_current(git_rebase *rebase) | 
| 1454 |  |  |  |  |  |  | { | 
| 1455 | 3 | 50 |  |  |  |  | GIT_ASSERT_ARG_WITH_RETVAL(rebase, 0); | 
| 1456 |  |  |  |  |  |  |  | 
| 1457 | 3 | 100 |  |  |  |  | return rebase->started ? rebase->current : GIT_REBASE_NO_OPERATION; | 
| 1458 |  |  |  |  |  |  | } | 
| 1459 |  |  |  |  |  |  |  | 
| 1460 | 6 |  |  |  |  |  | git_rebase_operation *git_rebase_operation_byindex(git_rebase *rebase, size_t idx) | 
| 1461 |  |  |  |  |  |  | { | 
| 1462 | 6 | 50 |  |  |  |  | GIT_ASSERT_ARG_WITH_RETVAL(rebase, NULL); | 
| 1463 |  |  |  |  |  |  |  | 
| 1464 | 6 | 100 |  |  |  |  | return git_array_get(rebase->operations, idx); | 
| 1465 |  |  |  |  |  |  | } | 
| 1466 |  |  |  |  |  |  |  | 
| 1467 | 4 |  |  |  |  |  | void git_rebase_free(git_rebase *rebase) | 
| 1468 |  |  |  |  |  |  | { | 
| 1469 | 4 | 50 |  |  |  |  | if (rebase == NULL) | 
| 1470 | 0 |  |  |  |  |  | return; | 
| 1471 |  |  |  |  |  |  |  | 
| 1472 | 4 |  |  |  |  |  | git_index_free(rebase->index); | 
| 1473 | 4 |  |  |  |  |  | git_commit_free(rebase->last_commit); | 
| 1474 | 4 |  |  |  |  |  | git__free(rebase->onto_name); | 
| 1475 | 4 |  |  |  |  |  | git__free(rebase->orig_head_name); | 
| 1476 | 4 |  |  |  |  |  | git__free(rebase->state_path); | 
| 1477 | 4 |  |  |  |  |  | git_array_clear(rebase->operations); | 
| 1478 | 4 |  |  |  |  |  | git__free((char *)rebase->options.rewrite_notes_ref); | 
| 1479 | 4 |  |  |  |  |  | git__free(rebase); | 
| 1480 |  |  |  |  |  |  | } |