Page MenuHomeFreeBSD

D21535.id61697.diff
No OneTemporary

D21535.id61697.diff

Index: usr.bin/patch/patch.c
===================================================================
--- usr.bin/patch/patch.c
+++ usr.bin/patch/patch.c
@@ -103,6 +103,7 @@
static bool patch_match(LINENUM, LINENUM, LINENUM);
static bool similar(const char *, const char *, int);
static void usage(void);
+static bool handle_creation(bool, bool *);
/* true if -E was specified on command line. */
static bool remove_empty_files = false;
@@ -147,8 +148,10 @@
int
main(int argc, char *argv[])
{
+ struct stat statbuf;
int error = 0, hunk, failed, i, fd;
- bool patch_seen, reverse_seen;
+ bool out_creating, out_existed, patch_seen, remove_file;
+ bool reverse_seen;
LINENUM where = 0, newwhere, fuzz, mymaxfuzz;
const char *tmpdir;
char *v;
@@ -219,6 +222,12 @@
reinitialize_almost_everything()) {
/* for each patch in patch file */
+ if (source_file != NULL && (diff_type == CONTEXT_DIFF ||
+ diff_type == NEW_CONTEXT_DIFF ||
+ diff_type == UNI_DIFF))
+ out_creating = strcmp(source_file, _PATH_DEVNULL) == 0;
+ else
+ out_creating = false;
patch_seen = true;
warn_on_invalid_line = true;
@@ -226,6 +235,8 @@
if (outname == NULL)
outname = xstrdup(filearg[0]);
+ out_existed = stat(outname, &statbuf) == 0;
+
/* for ed script just up and do it and exit */
if (diff_type == ED_DIFF) {
do_ed_script();
@@ -252,9 +263,15 @@
failed = 0;
reverse_seen = false;
out_of_mem = false;
+ remove_file = false;
while (another_hunk()) {
hunk++;
fuzz = 0;
+
+ if (out_creating)
+ reverse_seen = handle_creation(out_existed,
+ &remove_file);
+
mymaxfuzz = pch_context();
if (maxfuzz < mymaxfuzz)
mymaxfuzz = maxfuzz;
@@ -372,7 +389,6 @@
/* and put the output where desired */
ignore_signals();
if (!skip_rest_of_patch) {
- struct stat statbuf;
char *realout = outname;
if (!check_only) {
@@ -383,7 +399,7 @@
} else
chmod(outname, filemode);
- if (remove_empty_files &&
+ if ((remove_empty_files || remove_file) &&
stat(realout, &statbuf) == 0 &&
statbuf.st_size == 0) {
if (verbose)
@@ -444,6 +460,9 @@
filearg[0] = NULL;
}
+ free(source_file);
+ source_file = NULL;
+
free(outname);
outname = NULL;
@@ -1084,3 +1103,58 @@
return true; /* actually, this is not reached */
/* since there is always a \n */
}
+
+static bool
+handle_creation(bool out_existed, bool *remove)
+{
+ bool reverse_seen;
+
+ reverse_seen = false;
+ if (reverse && out_existed) {
+ *remove = true;
+ } else if (!reverse && out_existed) {
+ if (force) {
+ skip_rest_of_patch = true;
+ return (false);
+ }
+ if (noreverse) {
+ say("Ignoring previously applied (or reversed) patch.\n");
+ skip_rest_of_patch = true;
+ return (false);
+ }
+
+ /* Unreversed... suspicious if the file existed. */
+ if (!pch_swap())
+ fatal("lost hunk on alloc error!\n");
+
+ reverse = !reverse;
+
+ if (batch) {
+ if (verbose)
+ say("Patch creates file that already exists, %s %seversed",
+ reverse ? "Assuming" : "Ignoring",
+ reverse ? "R" : "Unr");
+ } else {
+ ask("Patch creates file that already exists! %s -R? [y] ",
+ reverse ? "Assume" : "Ignore");
+
+ if (*buf == 'n') {
+ ask("Apply anyway? [n]");
+ if (*buf != 'y')
+ /* Don't apply; error out */
+ skip_rest_of_patch = true;
+ else
+ /* Attempt to apply */
+ reverse_seen = true;
+ reverse = !reverse;
+ if (!pch_swap())
+ fatal("lost hunk on alloc error!\n");
+ } else {
+ /* They've opted to assume -R */
+ *remove = true;
+ }
+ }
+ }
+
+ return (reverse_seen);
+}
Index: usr.bin/patch/pch.h
===================================================================
--- usr.bin/patch/pch.h
+++ usr.bin/patch/pch.h
@@ -37,6 +37,8 @@
bool exists;
};
+extern char *source_file;
+
void re_patch(void);
void open_patch_file(const char *);
void set_hunkmax(void);
Index: usr.bin/patch/pch.c
===================================================================
--- usr.bin/patch/pch.c
+++ usr.bin/patch/pch.c
@@ -70,6 +70,8 @@
static FILE *pfp = NULL; /* patch file pointer */
static char *bestguess = NULL; /* guess at correct filename */
+char *source_file;
+
static void grow_hunkmax(void);
static int intuit_diff_type(void);
static void next_intuit_at(off_t, LINENUM);
@@ -218,7 +220,12 @@
bestguess = xstrdup(buf);
filearg[0] = fetchname(buf, &exists, 0);
}
- if (!exists) {
+ /*
+ * fetchname can now return buf = NULL, exists = true, to
+ * indicate to the caller that /dev/null was specified. Retain
+ * previous behavior for now until this can be better evaluted.
+ */
+ if (filearg[0] == NULL || !exists) {
int def_skip = *bestguess == '\0';
ask("No file found--skip this patch? [%c] ",
def_skip ? 'y' : 'n');
@@ -403,6 +410,23 @@
names[OLD_FILE] = names[NEW_FILE];
names[NEW_FILE] = tmp;
}
+
+ /* Invalidated */
+ free(source_file);
+ source_file = NULL;
+
+ if (retval != 0) {
+ /*
+ * In the case of success, path == NULL means _PATH_DEVNULL if
+ * exists is set. Explicitly specify it here to make it easier
+ * to detect later on that we're actually creating a file and
+ * not that we've just goofed something up.
+ */
+ if (names[OLD_FILE].path != NULL)
+ source_file = xstrdup(names[OLD_FILE].path);
+ else if (names[OLD_FILE].exists)
+ source_file = xstrdup(_PATH_DEVNULL);
+ }
if (filearg[0] == NULL) {
if (posix)
filearg[0] = posix_name(names, ok_to_create_file);
Index: usr.bin/patch/tests/unified_patch_test.sh
===================================================================
--- usr.bin/patch/tests/unified_patch_test.sh
+++ usr.bin/patch/tests/unified_patch_test.sh
@@ -108,22 +108,17 @@
file_nodupe_body()
{
- # WIP
- atf_expect_fail "patch(1) erroneously duplicates created files"
echo "x" > foo
diff -u /dev/null foo > foo.diff
- atf_check -x "patch -s < foo.diff"
- atf_check -s not-exit:0 -x "patch -fs < foo.diff"
+ atf_check -s not-exit:0 -o ignore -x "patch -Ns < foo.diff"
+ atf_check -s not-exit:0 -o ignore -x "patch -fs < foo.diff"
}
atf_test_case file_removal
file_removal_body()
{
- # WIP
- atf_expect_fail "patch(1) does not yet recognize /dev/null as creation"
-
echo "x" > foo
diff -u /dev/null foo > foo.diff
Index: usr.bin/patch/util.c
===================================================================
--- usr.bin/patch/util.c
+++ usr.bin/patch/util.c
@@ -366,8 +366,10 @@
say("fetchname %s %d\n", at, strip_leading);
#endif
/* So files can be created by diffing against /dev/null. */
- if (strnEQ(at, _PATH_DEVNULL, sizeof(_PATH_DEVNULL) - 1))
+ if (strnEQ(at, _PATH_DEVNULL, sizeof(_PATH_DEVNULL) - 1)) {
+ *exists = true;
return NULL;
+ }
name = fullname = t = savestr(at);
tab = strchr(t, '\t') != NULL;

File Metadata

Mime Type
text/plain
Expires
Sat, Feb 28, 11:31 PM (5 h, 35 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29086683
Default Alt Text
D21535.id61697.diff (6 KB)

Event Timeline