commit fda8017d0d1d1314b68ea9776bb563c2ea127f3e from: Stefan Sperling date: Thu Jul 23 14:22:40 2020 UTC move deeply indented code from unstage_path() to a new unstage_hunks() helper commit - 36bf999ca5297d07cc17f79a154b0875c1574148 commit + fda8017d0d1d1314b68ea9776bb563c2ea127f3e blob - d7c970469aa82014707191e80167f76aa30fb17e blob + 33605c9d4c23c5866ad26029575621e9dfba0237 --- lib/worktree.c +++ lib/worktree.c @@ -7371,7 +7371,7 @@ done: free(*path_unstaged_content); *path_unstaged_content = NULL; } - if (err || !have_rejected_content) { + if (err || !have_content || !have_rejected_content) { if (*path_new_staged_content && unlink(*path_new_staged_content) == -1 && err == NULL) err = got_error_from_errno2("unlink", @@ -7388,6 +7388,97 @@ done: got_diff_free_changes(changes); free(path1); free(path2); + return err; +} + +static const struct got_error * +unstage_hunks(struct got_object_id *staged_blob_id, + struct got_blob_object *blob_base, + struct got_object_id *blob_id, struct got_fileindex_entry *ie, + const char *ondisk_path, const char *label_orig, + struct got_worktree *worktree, struct got_repository *repo, + got_worktree_patch_cb patch_cb, void *patch_arg, + got_worktree_checkout_cb progress_cb, void *progress_arg) +{ + const struct got_error *err = NULL; + char *path_unstaged_content = NULL; + char *path_new_staged_content = NULL; + struct got_object_id *new_staged_blob_id = NULL; + FILE *f = NULL; + struct stat sb; + + err = create_unstaged_content(&path_unstaged_content, + &path_new_staged_content, blob_id, staged_blob_id, + ie->path, repo, patch_cb, patch_arg); + if (err) + return err; + + if (path_unstaged_content == NULL) + return NULL; + + if (path_new_staged_content) { + err = got_object_blob_create(&new_staged_blob_id, + path_new_staged_content, repo); + if (err) + goto done; + } + + f = fopen(path_unstaged_content, "r"); + if (f == NULL) { + err = got_error_from_errno2("fopen", + path_unstaged_content); + goto done; + } + if (fstat(fileno(f), &sb) == -1) { + err = got_error_from_errno2("fstat", path_unstaged_content); + goto done; + } + if (got_fileindex_entry_staged_filetype_get(ie) == + GOT_FILEIDX_MODE_SYMLINK && sb.st_size < PATH_MAX) { + char link_target[PATH_MAX]; + size_t r; + r = fread(link_target, 1, sizeof(link_target), f); + if (r == 0 && ferror(f)) { + err = got_error_from_errno("fread"); + goto done; + } + if (r >= sizeof(link_target)) { /* should not happen */ + err = got_error(GOT_ERR_NO_SPACE); + goto done; + } + link_target[r] = '\0'; + err = merge_symlink(worktree, blob_base, + ondisk_path, ie->path, label_orig, link_target, + worktree->base_commit_id, repo, progress_cb, + progress_arg); + } else { + int local_changes_subsumed; + err = merge_file(&local_changes_subsumed, worktree, + blob_base, ondisk_path, ie->path, + got_fileindex_perms_to_st(ie), + path_unstaged_content, label_orig, "unstaged", + repo, progress_cb, progress_arg); + } + if (err) + goto done; + + if (new_staged_blob_id) { + memcpy(ie->staged_blob_sha1, new_staged_blob_id->sha1, + SHA1_DIGEST_LENGTH); + } else + got_fileindex_entry_stage_set(ie, GOT_FILEIDX_STAGE_NONE); +done: + free(new_staged_blob_id); + if (path_unstaged_content && + unlink(path_unstaged_content) == -1 && err == NULL) + err = got_error_from_errno2("unlink", path_unstaged_content); + if (path_new_staged_content && + unlink(path_new_staged_content) == -1 && err == NULL) + err = got_error_from_errno2("unlink", path_new_staged_content); + if (f && fclose(f) != 0 && err == NULL) + err = got_error_from_errno2("fclose", path_unstaged_content); + free(path_unstaged_content); + free(path_new_staged_content); return err; } @@ -7401,8 +7492,7 @@ unstage_path(void *arg, unsigned char status, struct unstage_path_arg *a = arg; struct got_fileindex_entry *ie; struct got_blob_object *blob_base = NULL, *blob_staged = NULL; - char *ondisk_path = NULL, *path_unstaged_content = NULL; - char *path_new_staged_content = NULL; + char *ondisk_path = NULL; char *id_str = NULL, *label_orig = NULL; int local_changes_subsumed; struct stat sb; @@ -7448,73 +7538,11 @@ unstage_path(void *arg, unsigned char status, if (choice != GOT_PATCH_CHOICE_YES) break; } else { - err = create_unstaged_content( - &path_unstaged_content, - &path_new_staged_content, blob_id, - staged_blob_id, ie->path, a->repo, - a->patch_cb, a->patch_arg); - if (err || path_unstaged_content == NULL) - break; - if (path_new_staged_content) { - err = got_object_blob_create( - &staged_blob_id, - path_new_staged_content, - a->repo); - if (err) - break; - memcpy(ie->staged_blob_sha1, - staged_blob_id->sha1, - SHA1_DIGEST_LENGTH); - } - if (got_fileindex_entry_staged_filetype_get(ie) - == GOT_FILEIDX_MODE_SYMLINK) { - char unstaged_target[PATH_MAX]; - FILE *f; - size_t r; - f = fopen(path_unstaged_content, "r"); - if (f == NULL) { - err = got_error_from_errno2( - "fopen", - path_unstaged_content); - goto done; - } - r = fread(unstaged_target, 1, - sizeof(unstaged_target), f); - if (r == 0 && ferror(f)) { - err = got_error_from_errno( - "fread"); - fclose(f); - break; - } - if (fclose(f) == EOF) { - err = got_error_from_errno2( - "fclose", - path_unstaged_content); - } - if (r >= sizeof(unstaged_target)) { - err = got_error( - GOT_ERR_NO_SPACE); - goto done; - } - unstaged_target[r] = '\0'; - err = merge_symlink(a->worktree, - blob_base, ondisk_path, relpath, - label_orig, unstaged_target, - a->worktree->base_commit_id, - a->repo, a->progress_cb, - a->progress_arg); - } else { - err = merge_file(&local_changes_subsumed, - a->worktree, blob_base, ondisk_path, - relpath, got_fileindex_perms_to_st(ie), - path_unstaged_content, label_orig, - "unstaged", a->repo, a->progress_cb, - a->progress_arg); - } - if (err == NULL && - path_new_staged_content == NULL) - got_fileindex_entry_stage_set(ie, - GOT_FILEIDX_STAGE_NONE); + err = unstage_hunks(staged_blob_id, + blob_base, blob_id, ie, ondisk_path, + label_orig, a->worktree, a->repo, + a->patch_cb, a->patch_arg, + a->progress_cb, a->progress_arg); break; /* Done with this file. */ } } @@ -7587,14 +7615,6 @@ unstage_path(void *arg, unsigned char status, } done: free(ondisk_path); - if (path_unstaged_content && - unlink(path_unstaged_content) == -1 && err == NULL) - err = got_error_from_errno2("unlink", path_unstaged_content); - if (path_new_staged_content && - unlink(path_new_staged_content) == -1 && err == NULL) - err = got_error_from_errno2("unlink", path_new_staged_content); - free(path_unstaged_content); - free(path_new_staged_content); if (blob_base) got_object_blob_close(blob_base); if (blob_staged)