Commit Diff


commit - 2be5e1a234aeec2c4e8d6b84f0405034ed8664fa
commit + 95d683408adee5188de396567e8e9746b703d7dd
blob - 8fc9edf2163e5db80ebfc2641f66fd8d288fa8bd
blob + 58d4125553be6fd56d2408805b9c001d9c08c698
--- lib/patch.c
+++ lib/patch.c
@@ -595,7 +595,7 @@ apply_patch(struct got_worktree *worktree, struct got_
 	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_
 	}
 
 	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_
 done:
 	if (err != NULL && newpath != NULL && (file_renamed || p->old == NULL))
 		unlink(newpath);
+	free(parent);
 	free(template);
 	if (tmppath != NULL)
 		unlink(tmppath);
blob - 6d468d0334318dc22a5552f720bf777276c909d8
blob + 92f950fb6b4fb18338a3b9edcd4318445564b3e7
--- regress/cmdline/patch.sh
+++ regress/cmdline/patch.sh
@@ -1003,8 +1003,49 @@ EOF
 	if [ ! -x $testroot/wt/alpha ]; then
 		echo "alpha is no more executable!" >&2
 		test_done $testroot 1
+		return 1
+	fi
+	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
 }
 
@@ -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