Commit 95d683408adee5188de396567e8e9746b703d7dd

Omar Polo 2022-03-16T18:23:03

got patch: create missing directories when adding files ok stsp@

diff --git a/lib/patch.c b/lib/patch.c
index 8fc9edf..58d4125 100644
--- a/lib/patch.c
+++ b/lib/patch.c
@@ -595,7 +595,7 @@ apply_patch(struct got_worktree *worktree, struct got_repository *repo,
 	const struct got_error *err = NULL;
 	struct got_pathlist_head oldpaths, newpaths;
 	int file_renamed = 0;
-	char *oldpath = NULL, *newpath = NULL;
+	char *oldpath = NULL, *newpath = NULL, *parent = NULL;
 	char *tmppath = NULL, *template = NULL;
 	FILE *tmp = NULL;
 	mode_t mode = GOT_DEFAULT_FILE_MODE;
@@ -650,8 +650,23 @@ apply_patch(struct got_worktree *worktree, struct got_repository *repo,
 	}
 
 	if (rename(tmppath, newpath) == -1) {
-		err = got_error_from_errno3("rename", tmppath, newpath);
-		goto done;
+		if (errno != ENOENT) {
+			err = got_error_from_errno3("rename", tmppath,
+			    newpath);
+			goto done;
+		}
+
+		err = got_path_dirname(&parent, newpath);
+		if (err != NULL)
+			goto done;
+		err = got_path_mkdir(parent);
+		if (err != NULL)
+			goto done;
+		if (rename(tmppath, newpath) == -1) {
+			err = got_error_from_errno3("rename", tmppath,
+			    newpath);
+			goto done;
+		}
 	}
 
 	if (file_renamed) {
@@ -670,6 +685,7 @@ apply_patch(struct got_worktree *worktree, struct got_repository *repo,
 done:
 	if (err != NULL && newpath != NULL && (file_renamed || p->old == NULL))
 		unlink(newpath);
+	free(parent);
 	free(template);
 	if (tmppath != NULL)
 		unlink(tmppath);
diff --git a/regress/cmdline/patch.sh b/regress/cmdline/patch.sh
index 6d468d0..92f950f 100755
--- a/regress/cmdline/patch.sh
+++ b/regress/cmdline/patch.sh
@@ -1008,6 +1008,47 @@ EOF
 	test_done $testroot 0
 }
 
+test_patch_create_dirs() {
+	local testroot=`test_init patch_create_dirs`
+
+	got checkout $testroot/repo $testroot/wt > /dev/null
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		test_done $testroot $ret
+		return 1
+	fi
+
+	cat <<EOF > $testroot/wt/patch
+--- /dev/null
++++ iota/kappa/lambda
+@@ -0,0 +1 @@
++lambda
+EOF
+
+	(cd $testroot/wt && got patch patch) > $testroot/stdout
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		test_done $testroot $ret
+		return 1
+	fi
+
+	echo 'A  iota/kappa/lambda' >> $testroot/stdout.expected
+	cmp -s $testroot/stdout.expected $testroot/stdout
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		diff -u $testroot/stdout.expected $testroot/stdout
+		test_done $testroot $ret
+		return 1
+	fi
+
+	if [ ! -f $testroot/wt/iota/kappa/lambda ]; then
+		echo "file not created!" >&2
+		test_done $testroot $ret
+		return 1
+	fi
+	test_done $testroot 0
+}
+
 test_parseargs "$@"
 run_test test_patch_simple_add_file
 run_test test_patch_simple_rm_file
@@ -1024,3 +1065,4 @@ run_test test_patch_rename
 run_test test_patch_illegal_status
 run_test test_patch_nop
 run_test test_patch_preserve_perm
+run_test test_patch_create_dirs