"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Stefan Sperling <stsp@stsp.name>
Subject:
Re: histedit: How to fold M, D?
To:
Christian Weisgerber <naddy@mips.inka.de>, gameoftrees@openbsd.org
Date:
Tue, 25 Jul 2023 15:49:32 +0200

Download raw body.

Thread
On Tue, Jul 25, 2023 at 03:32:36PM +0200, Stefan Sperling wrote:
> On Tue, Jul 25, 2023 at 03:24:16PM +0200, Stefan Sperling wrote:
> > Below is a relatively simple patch you could try.
> 
> Oh sorry this diff won't work as-is since it assumes that the
> blob ID passed in already matches the file on disk. I will have
> to revisit this, adding an object ID lookup.

Try this one please. Also fixes small leaks in unlikely error paths.

diff /home/stsp/src/got
commit - 48bfa43b34c38fcf5e33c1e63dbe5dbd8c5865ce
path + /home/stsp/src/got
blob - c2e52f2b6af12e7f6d173ad130885b820fa1bd5e
file + lib/worktree.c
--- lib/worktree.c
+++ lib/worktree.c
@@ -2999,6 +2999,7 @@ merge_file_cb(void *arg, struct got_blob_object *blob1
 	int local_changes_subsumed;
 	FILE *f_orig = NULL, *f_deriv = NULL, *f_deriv2 = NULL;
 	char *id_str = NULL, *label_deriv2 = NULL;
+	struct got_object_id *id = NULL;
 
 	if (blob1 && blob2) {
 		ie = got_fileindex_entry_get(a->fileindex, path2,
@@ -3124,19 +3125,37 @@ merge_file_cb(void *arg, struct got_blob_object *blob1
 			if (ie)
 				got_fileindex_entry_mark_deleted_from_disk(ie);
 			break;
+		case GOT_STATUS_MODIFY:
 		case GOT_STATUS_ADD: {
-			struct got_object_id *id;
 			FILE *blob1_f;
 			off_t blob1_size;
+			int blob_found = 0;
 			/*
-			 * Delete the added file only if its content already
+			 * Delete the file only if its content already
 			 * exists in the repository.
 			 */
 			err = got_object_blob_file_create(&id, &blob1_f,
 			    &blob1_size, path1);
 			if (err)
 				goto done;
-			if (got_object_id_cmp(id, id1) == 0) {
+			if (fclose(blob1_f) == EOF) {
+				err = got_error_from_errno("fclose");
+				goto done;
+			}
+			if (status == GOT_STATUS_MODIFY) {
+				int obj_type;
+
+				/* Implied existence check. */
+				err = got_object_get_type(&obj_type, repo, id);
+				if (err) {
+					if (err->code != GOT_ERR_NO_OBJ)
+						goto done;
+					err = NULL;
+				} else if (obj_type == GOT_OBJ_TYPE_BLOB)
+					blob_found = 1;
+			}
+			if ((status == GOT_STATUS_ADD &&
+			    got_object_id_cmp(id, id1) == 0) || blob_found) {
 				err = (*a->progress_cb)(a->progress_arg,
 				    GOT_STATUS_DELETE, path1);
 				if (err)
@@ -3152,14 +3171,10 @@ merge_file_cb(void *arg, struct got_blob_object *blob1
 				err = (*a->progress_cb)(a->progress_arg,
 				    GOT_STATUS_CANNOT_DELETE, path1);
 			}
-			if (fclose(blob1_f) == EOF && err == NULL)
-				err = got_error_from_errno("fclose");
-			free(id);
 			if (err)
 				goto done;
 			break;
 		}
-		case GOT_STATUS_MODIFY:
 		case GOT_STATUS_CONFLICT:
 			err = (*a->progress_cb)(a->progress_arg,
 			    GOT_STATUS_CANNOT_DELETE, path1);
@@ -3243,6 +3258,7 @@ done:
 	if (f_deriv2 && fclose(f_deriv2) == EOF && err == NULL)
 		err = got_error_from_errno("fclose");
 	free(id_str);
+	free(id);
 	free(label_deriv2);
 	free(ondisk_path);
 	return err;