Commit Diff


commit - ecfff807e1145877b3360f07915ef8e3af0e2751
commit + 0a22ca1a5a1261bb7e230db211a205b68e1c3044
blob - 899d18ef5efa99dada375165674b485b6bf60311
blob + 67676602467844816045891f0532476d0e14c799
--- lib/got_lib_object_create.h
+++ lib/got_lib_object_create.h
@@ -14,6 +14,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+const struct got_error *got_object_blob_file_create(struct got_object_id **,
+    FILE **, const char *);
 const struct got_error *got_object_blob_create(struct got_object_id **,
     const char *, struct got_repository *);
 
blob - ed77449fe0df86c0f53685f3fd20ccfcb57d314e
blob + 73b108d609463ae2121d561cbfcf7c2bc6924d2b
--- lib/object_create.c
+++ lib/object_create.c
@@ -112,18 +112,18 @@ done:
 }
 
 const struct got_error *
-got_object_blob_create(struct got_object_id **id, const char *ondisk_path,
-    struct got_repository *repo)
+got_object_blob_file_create(struct got_object_id **id, FILE **blobfile,
+    const char *ondisk_path)
 {
 	const struct got_error *err = NULL;
 	char *header = NULL;
-	FILE *blobfile = NULL;
 	int fd = -1;
 	struct stat sb;
 	SHA1_CTX sha1_ctx;
 	size_t headerlen = 0, n;
 
 	*id = NULL;
+	*blobfile = NULL;
 
 	SHA1Init(&sha1_ctx);
 
@@ -149,15 +149,15 @@ got_object_blob_create(struct got_object_id **id, cons
 	headerlen = strlen(header) + 1;
 	SHA1Update(&sha1_ctx, header, headerlen);
 
-	blobfile = got_opentemp();
-	if (blobfile == NULL) {
+	*blobfile = got_opentemp();
+	if (*blobfile == NULL) {
 		err = got_error_from_errno("got_opentemp");
 		goto done;
 	}
 
-	n = fwrite(header, 1, headerlen, blobfile);
+	n = fwrite(header, 1, headerlen, *blobfile);
 	if (n != headerlen) {
-		err = got_ferror(blobfile, GOT_ERR_IO);
+		err = got_ferror(*blobfile, GOT_ERR_IO);
 		goto done;
 	}
 	for (;;) {
@@ -180,9 +180,9 @@ got_object_blob_create(struct got_object_id **id, cons
 		if (inlen == 0)
 			break; /* EOF */
 		SHA1Update(&sha1_ctx, buf, inlen);
-		n = fwrite(buf, 1, inlen, blobfile);
+		n = fwrite(buf, 1, inlen, *blobfile);
 		if (n != inlen) {
-			err = got_ferror(blobfile, GOT_ERR_IO);
+			err = got_ferror(*blobfile, GOT_ERR_IO);
 			goto done;
 		}
 		if (S_ISLNK(sb.st_mode))
@@ -196,18 +196,39 @@ got_object_blob_create(struct got_object_id **id, cons
 	}
 	SHA1Final((*id)->sha1, &sha1_ctx);
 
-	if (fflush(blobfile) != 0) {
+	if (fflush(*blobfile) != 0) {
 		err = got_error_from_errno("fflush");
 		goto done;
 	}
-	rewind(blobfile);
-
-	err = create_object_file(*id, blobfile, repo);
+	rewind(*blobfile);
 done:
 	free(header);
 	if (fd != -1 && close(fd) != 0 && err == NULL)
 		err = got_error_from_errno("close");
-	if (blobfile && fclose(blobfile) != 0 && err == NULL)
+	if (err) {
+		free(*id);
+		*id = NULL;
+		if (*blobfile) {
+			fclose(*blobfile);
+			*blobfile = NULL;
+		}
+	}
+	return err;
+}
+
+const struct got_error *
+got_object_blob_create(struct got_object_id **id, const char *ondisk_path,
+    struct got_repository *repo)
+{
+	const struct got_error *err = NULL;
+	FILE *blobfile = NULL;
+
+	err = got_object_blob_file_create(id, &blobfile, ondisk_path);
+	if (err)
+		return err;
+
+	err = create_object_file(*id, blobfile, repo);
+	if (fclose(blobfile) == EOF && err == NULL)
 		err = got_error_from_errno("fclose");
 	if (err) {
 		free(*id);
blob - cade3cf24e001a4b116276ca9e6b7c97fa64e827
blob + d376968700adbabb24ee439230e26f1477711121
--- lib/worktree.c
+++ lib/worktree.c
@@ -2799,7 +2799,39 @@ merge_file_cb(void *arg, struct got_blob_object *blob1
 			if (ie)
 				got_fileindex_entry_mark_deleted_from_disk(ie);
 			break;
-		case GOT_STATUS_ADD:
+		case GOT_STATUS_ADD: {
+			struct got_object_id *id;
+			FILE *blob1_f;
+			/*
+			 * Delete the added file only if its content already
+			 * exists in the repository.
+			 */
+			err = got_object_blob_file_create(&id, &blob1_f, path1);
+			if (err)
+				goto done;
+			if (got_object_id_cmp(id, id1) == 0) {
+				err = (*a->progress_cb)(a->progress_arg,
+				    GOT_STATUS_DELETE, path1);
+				if (err)
+					goto done;
+				err = remove_ondisk_file(a->worktree->root_path,
+				    path1);
+				if (err)
+					goto done;
+				if (ie)
+					got_fileindex_entry_remove(a->fileindex,
+					    ie);
+			} else {
+				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,
blob - d3da70160eb28b8c3921d05dd3922e30ecc6d609
blob + dc2761fa45cd308f397eaaffefa39b87bcfe6389
--- regress/cmdline/histedit.sh
+++ regress/cmdline/histedit.sh
@@ -1388,8 +1388,8 @@ test_histedit_fold_add_delete() {
 	echo "G  epsilon/psi" >> $testroot/stdout.expected
 	echo "$short_old_commit2 ->  fold commit: editing psi" \
 		>> $testroot/stdout.expected
-	echo "d  epsilon/psi" >> $testroot/stdout.expected
-	echo "$short_old_commit3 -> $short_new_commit1: folded changes" \
+	echo "D  epsilon/psi" >> $testroot/stdout.expected
+	echo "$short_old_commit3 -> no-op change: folded changes" \
 		>> $testroot/stdout.expected
 	echo "Switching work tree to refs/heads/master" \
 		>> $testroot/stdout.expected
@@ -1403,9 +1403,8 @@ test_histedit_fold_add_delete() {
 	fi
 
 	if [ -e $testroot/wt/epsilon/psi ]; then
-		#echo "removed file psi still exists on disk" >&2
-		ret="xfail: removed file psi still exists on disk"
-		test_done "$testroot" "$ret"
+		echo "removed file psi still exists on disk" >&2
+		test_done "$testroot" "1"
 		return 1
 	fi
 
@@ -1422,7 +1421,6 @@ test_histedit_fold_add_delete() {
 
 	(cd $testroot/wt && got log -l3 | grep ^commit > $testroot/stdout)
 	echo "commit $new_commit1 (master)" > $testroot/stdout.expected
-	echo "commit $orig_commit" >> $testroot/stdout.expected
 	cmp -s $testroot/stdout.expected $testroot/stdout
 	ret="$?"
 	if [ "$ret" != "0" ]; then