New Upstream Release - wiggle

Ready changes

Summary

Merged new upstream version: 1.2 (was: 1.1).

Resulting package

Built on 2023-06-17T16:20 (took 4m37s)

The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:

apt install -t fresh-releases wiggle-dbgsymapt install -t fresh-releases wiggle

Lintian Result

Diff

diff --git a/ChangeLog b/ChangeLog
deleted file mode 100644
index 8337da0..0000000
--- a/ChangeLog
+++ /dev/null
@@ -1,4 +0,0 @@
-
-	- Don't use --quiet in dotest as it is a Debian specific extension
-	  to /usr/bin/time
-
diff --git a/DOC/Algorithm b/DOC/Algorithm
index 515ba07..cb2ec48 100644
--- a/DOC/Algorithm
+++ b/DOC/Algorithm
@@ -23,7 +23,7 @@ side and build up the full path using linear space and only doubling
 your work.
 
 Wiggle takes a different approach.  Finding where the snakes cross
-seemed awkward to me, and having two blocks of similiar but not
+seemed awkward to me, and having two blocks of similar but not
 identical code (one to search forward, one to search backwards) didn't
 appeal at all.
 
diff --git a/ReadMe.c b/ReadMe.c
index e76a04b..05d8ec2 100644
--- a/ReadMe.c
+++ b/ReadMe.c
@@ -29,10 +29,10 @@
 #include "wiggle.h"
 
 #ifndef VERSION
-#define VERSION "1.1"
+#define VERSION "1.2"
 #endif
 #ifndef VERS_DATE
-#define VERS_DATE "2017-09-28"
+#define VERS_DATE "2019-12-27"
 #endif
 
 char Version[] = "wiggle " VERSION " " VERS_DATE " GPL-2+ http://neil.brown.name/wiggle/\n";
@@ -58,6 +58,7 @@ struct option long_options[] = {
 	{"no-ignore",	0, 0, 'i'},
 	{"show-wiggles",0, 0, 'W'},
 	{"ignore-blanks",0,0, 'b'},
+	{"no-backup",   0, 0, NO_BACKUP },
 	{"self-test",   0, 0, SELF_TEST},
 	{"report-wiggles", 0, 0, REPORT_WIGGLES},
 	{0, 0, 0, 0}
@@ -96,6 +97,7 @@ char Help[] =  "\n"
 "   --quiet     -q    : don't print un-necessary messages.\n"
 "\n"
 "   --replace   -r    : replace first file with result of merger.\n"
+"   --no-backup       : Never save original file (as name.porig).\n"
 "\n"
 "   --strip=    -p    : number of path components to strip from file names.\n"
 "\n"
@@ -119,7 +121,7 @@ char HelpExtract[] = "\n"
 char HelpDiff[] = "\n"
 "wiggle --diff [-wl] [-p12] [-R]  file-or-patch [file-or-patch]\n"
 "\n"
-"The diff function will report the differencs and similarities between\n"
+"The diff function will report the differences and similarities between\n"
 "two files in a format similar to 'diff -u'.  With --word mode\n"
 "(the default) word-wise differences are displayed on lines starting\n"
 "with a '|'.  With --line mode, only whole lines are considered\n"
diff --git a/bestmatch.c b/bestmatch.c
index d1dcacf..eb35592 100644
--- a/bestmatch.c
+++ b/bestmatch.c
@@ -276,7 +276,7 @@ static void find_best(struct file *a, struct file *b,
  * in line-mode are interesting) and words that start with
  * and alphanumeric are interesting.  This excludes spaces and
  * special characters in word mode
- * Doing a best-fit comparision on only interesting words is
+ * Doing a best-fit comparison on only interesting words is
  * much faster than on all words, and is nearly as good
  */
 
diff --git a/ccan/hash/hash.c b/ccan/hash/hash.c
index 2659b92..cc58da6 100644
--- a/ccan/hash/hash.c
+++ b/ccan/hash/hash.c
@@ -9,7 +9,7 @@ if SELF_TEST is defined.  You can use this free for any purpose.  It's in
 the public domain.  It has no warranty.
 
 You probably want to use hashlittle().  hashlittle() and hashbig()
-hash byte arrays.  hashlittle() is is faster than hashbig() on
+hash byte arrays.  hashlittle() is faster than hashbig() on
 little-endian machines.  Intel and AMD are little-endian machines.
 On second thought, you probably want hashlittle2(), which is identical to
 hashlittle() except it returns two 32-bit hashes for the price of one.  
@@ -280,7 +280,7 @@ static uint32_t hashlittle( const void *key, size_t length, uint32_t *val2 )
      * rest of the string.  Every machine with memory protection I've seen
      * does it on word boundaries, so is OK with this.  But VALGRIND will
      * still catch it and complain.  The masking trick does make the hash
-     * noticably faster for short strings (like English words).
+     * noticeably faster for short strings (like English words).
      *
      * Not on my testing with gcc 4.5 on an intel i5 CPU, at least --RR.
      */
@@ -457,7 +457,7 @@ static uint32_t hashbig( const void *key, size_t length, uint32_t *val2)
      * rest of the string.  Every machine with memory protection I've seen
      * does it on word boundaries, so is OK with this.  But VALGRIND will
      * still catch it and complain.  The masking trick does make the hash
-     * noticably faster for short strings (like English words).
+     * noticeably faster for short strings (like English words).
      *
      * Not on my testing with gcc 4.5 on an intel i5 CPU, at least --RR.
      */
diff --git a/ccan/hash/hash.h b/ccan/hash/hash.h
index 0400e6a..5bbef5d 100644
--- a/ccan/hash/hash.h
+++ b/ccan/hash/hash.h
@@ -34,7 +34,7 @@
  *	#include <stdio.h>
  *	#include <string.h>
  *
- *	// Simple demonstration: idential strings will have the same hash, but
+ *	// Simple demonstration: identical strings will have the same hash, but
  *	// two different strings will probably not.
  *	int main(int argc, char *argv[])
  *	{
@@ -163,7 +163,7 @@ static inline uint32_t hash_string(const char *string)
  *	#include <stdio.h>
  *	#include <string.h>
  *
- *	// Simple demonstration: idential strings will have the same hash, but
+ *	// Simple demonstration: identical strings will have the same hash, but
  *	// two different strings will probably not.
  *	int main(int argc, char *argv[])
  *	{
diff --git a/debian/changelog b/debian/changelog
index 101c9c4..116d9d2 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+wiggle (1.2-1) UNRELEASED; urgency=low
+
+  * New upstream release.
+  * Drop patch typos.patch, present upstream.
+  * Drop patch gcc8-format-security.patch, present upstream.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Sat, 17 Jun 2023 16:16:48 -0000
+
 wiggle (1.1-1) unstable; urgency=medium
 
   * QA upload.
diff --git a/debian/patches/gcc8-format-security.patch b/debian/patches/gcc8-format-security.patch
deleted file mode 100644
index c48016e..0000000
--- a/debian/patches/gcc8-format-security.patch
+++ /dev/null
@@ -1,86 +0,0 @@
-From: Carlos Maddela <e7appew@gmail.com>
-Date: Fri, 25 Jan 2019 05:04:46 +1100
-Subject: Fix format overflow and truncation warnings with GCC-8.
-
-Description: Fix format overflow and truncation warnings with GCC-8.
-Author: Carlos Maddela <e7appew@gmail.com>
-Forwarded: https://github.com/neilbrown/wiggle/pull/11
-Last-Update: 2019-01-25
----
-This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
----
- extract.c | 26 ++++++++++++++++++--------
- vpatch.c  |  6 +++---
- 2 files changed, 21 insertions(+), 11 deletions(-)
-
-diff --git a/extract.c b/extract.c
-index a8068d2..c3c47e6 100644
---- a/extract.c
-+++ b/extract.c
-@@ -118,12 +118,17 @@ int split_patch(struct stream f, struct stream *f1, struct stream *f2)
- 			skip_eol(&cp, end);
- 			if (state == 1 || state == 3) {
- 				char *f;
--				char buf[20];
-+				int slen;
-+				/* Reserve enough space for 3 integers separated
-+				 * by a single space, and prefixed and terminated
-+				 * with a null character.
-+				 */
-+				char buf[(3*12)+1];
- 				buf[0] = 0;
- 				chunks++;
--				sprintf(buf+1, "%5d %5d %5d", chunks, a, acnt);
--				memcpy(r1.body+r1.len, buf, 18);
--				r1.len += 18;
-+				slen = sprintf(buf+1, "%5d %5d %5d", chunks, a, acnt)+1;
-+				memcpy(r1.body+r1.len, buf, slen);
-+				r1.len += slen;
- 				f = func;
- 				while (*f == ' ')
- 					f++;
-@@ -136,11 +141,16 @@ int split_patch(struct stream f, struct stream *f1, struct stream *f2)
- 				r1.body[r1.len++] = '\0';
- 			}
- 			if (state == 2 || state == 3) {
--				char buf[20];
-+				int slen;
-+				/* Reserve enough space for 3 integers separated
-+				 * by a single space, prefixed with a null character
-+				 * and terminated with a new line and null character.
-+				 */
-+				char buf[(3*12)+2];
- 				buf[0] = 0;
--				sprintf(buf+1, "%5d %5d %5d\n", chunks, c, bcnt);
--				memcpy(r2.body+r2.len, buf, 20);
--				r2.len += 20;
-+				slen = sprintf(buf+1, "%5d %5d %5d\n", chunks, c, bcnt)+2;
-+				memcpy(r2.body+r2.len, buf, slen);
-+				r2.len += slen;
- 			}
- 			if (state)
- 				func[0] = 0;
-diff --git a/vpatch.c b/vpatch.c
-index 2c574c8..88633ff 100644
---- a/vpatch.c
-+++ b/vpatch.c
-@@ -1680,8 +1680,8 @@ static int merge_window(struct plist *p, FILE *f, int reverse, int replace,
- 			attrset(A_NORMAL);
- 		}
- 		if (num >= 0) {
--			char buf[10];
--			snprintf(buf, 10, "%d ", num);
-+			char buf[12+1];
-+			snprintf(buf, sizeof(buf), "%d ", num);
- 			addstr(buf);
- 		}
- 		if (meta & META(0))
-@@ -2487,7 +2487,7 @@ static int get_next(int pos, struct plist *pl, int n, int mode,
- static void draw_one(int row, struct plist *pl, FILE *f, int reverse,
- 		     int ignore_blanks, int just_diff)
- {
--	char hdr[12];
-+	char hdr[2*12];
- 	hdr[0] = 0;
- 
- 	if (pl == NULL) {
diff --git a/debian/patches/series b/debian/patches/series
index baad0ca..e69de29 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,2 +0,0 @@
-typos.patch
-gcc8-format-security.patch
diff --git a/debian/patches/typos.patch b/debian/patches/typos.patch
deleted file mode 100644
index cff079a..0000000
--- a/debian/patches/typos.patch
+++ /dev/null
@@ -1,110 +0,0 @@
-From: Carlos Maddela <e7appew@gmail.com>
-Date: Thu, 24 Jan 2019 21:04:57 +1100
-Subject: Fix some typos.
-
-Description: Fix some typos.
-Author: Carlos Maddela <e7appew@gmail.com>
-Forwarded: https://github.com/neilbrown/wiggle/pull/10
-Last-Update: 2019-01-24
----
-This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
----
- DOC/Algorithm    | 2 +-
- ReadMe.c         | 2 +-
- bestmatch.c      | 2 +-
- ccan/hash/hash.c | 6 +++---
- ccan/hash/hash.h | 4 ++--
- 5 files changed, 8 insertions(+), 8 deletions(-)
-
-diff --git a/DOC/Algorithm b/DOC/Algorithm
-index 515ba07..cb2ec48 100644
---- a/DOC/Algorithm
-+++ b/DOC/Algorithm
-@@ -23,7 +23,7 @@ side and build up the full path using linear space and only doubling
- your work.
- 
- Wiggle takes a different approach.  Finding where the snakes cross
--seemed awkward to me, and having two blocks of similiar but not
-+seemed awkward to me, and having two blocks of similar but not
- identical code (one to search forward, one to search backwards) didn't
- appeal at all.
- 
-diff --git a/ReadMe.c b/ReadMe.c
-index e76a04b..c559a58 100644
---- a/ReadMe.c
-+++ b/ReadMe.c
-@@ -119,7 +119,7 @@ char HelpExtract[] = "\n"
- char HelpDiff[] = "\n"
- "wiggle --diff [-wl] [-p12] [-R]  file-or-patch [file-or-patch]\n"
- "\n"
--"The diff function will report the differencs and similarities between\n"
-+"The diff function will report the differences and similarities between\n"
- "two files in a format similar to 'diff -u'.  With --word mode\n"
- "(the default) word-wise differences are displayed on lines starting\n"
- "with a '|'.  With --line mode, only whole lines are considered\n"
-diff --git a/bestmatch.c b/bestmatch.c
-index d1dcacf..eb35592 100644
---- a/bestmatch.c
-+++ b/bestmatch.c
-@@ -276,7 +276,7 @@ static void find_best(struct file *a, struct file *b,
-  * in line-mode are interesting) and words that start with
-  * and alphanumeric are interesting.  This excludes spaces and
-  * special characters in word mode
-- * Doing a best-fit comparision on only interesting words is
-+ * Doing a best-fit comparison on only interesting words is
-  * much faster than on all words, and is nearly as good
-  */
- 
-diff --git a/ccan/hash/hash.c b/ccan/hash/hash.c
-index 2659b92..cc58da6 100644
---- a/ccan/hash/hash.c
-+++ b/ccan/hash/hash.c
-@@ -9,7 +9,7 @@ if SELF_TEST is defined.  You can use this free for any purpose.  It's in
- the public domain.  It has no warranty.
- 
- You probably want to use hashlittle().  hashlittle() and hashbig()
--hash byte arrays.  hashlittle() is is faster than hashbig() on
-+hash byte arrays.  hashlittle() is faster than hashbig() on
- little-endian machines.  Intel and AMD are little-endian machines.
- On second thought, you probably want hashlittle2(), which is identical to
- hashlittle() except it returns two 32-bit hashes for the price of one.  
-@@ -280,7 +280,7 @@ static uint32_t hashlittle( const void *key, size_t length, uint32_t *val2 )
-      * rest of the string.  Every machine with memory protection I've seen
-      * does it on word boundaries, so is OK with this.  But VALGRIND will
-      * still catch it and complain.  The masking trick does make the hash
--     * noticably faster for short strings (like English words).
-+     * noticeably faster for short strings (like English words).
-      *
-      * Not on my testing with gcc 4.5 on an intel i5 CPU, at least --RR.
-      */
-@@ -457,7 +457,7 @@ static uint32_t hashbig( const void *key, size_t length, uint32_t *val2)
-      * rest of the string.  Every machine with memory protection I've seen
-      * does it on word boundaries, so is OK with this.  But VALGRIND will
-      * still catch it and complain.  The masking trick does make the hash
--     * noticably faster for short strings (like English words).
-+     * noticeably faster for short strings (like English words).
-      *
-      * Not on my testing with gcc 4.5 on an intel i5 CPU, at least --RR.
-      */
-diff --git a/ccan/hash/hash.h b/ccan/hash/hash.h
-index 0400e6a..5bbef5d 100644
---- a/ccan/hash/hash.h
-+++ b/ccan/hash/hash.h
-@@ -34,7 +34,7 @@
-  *	#include <stdio.h>
-  *	#include <string.h>
-  *
-- *	// Simple demonstration: idential strings will have the same hash, but
-+ *	// Simple demonstration: identical strings will have the same hash, but
-  *	// two different strings will probably not.
-  *	int main(int argc, char *argv[])
-  *	{
-@@ -163,7 +163,7 @@ static inline uint32_t hash_string(const char *string)
-  *	#include <stdio.h>
-  *	#include <string.h>
-  *
-- *	// Simple demonstration: idential strings will have the same hash, but
-+ *	// Simple demonstration: identical strings will have the same hash, but
-  *	// two different strings will probably not.
-  *	int main(int argc, char *argv[])
-  *	{
diff --git a/diff.c b/diff.c
index 3d16e67..1deea20 100644
--- a/diff.c
+++ b/diff.c
@@ -614,7 +614,8 @@ struct csl *diff_patch(struct file a, struct file b)
 {
 	int ap, bp;
 	struct csl *csl = NULL;
-	if (a.list[0].start[0] != '\0' ||
+	if (a.elcnt == 0 || b.elcnt == 0 ||
+	    a.list[0].start[0] != '\0' ||
 	    b.list[0].start[0] != '\0')
 		/* this is not a patch */
 		return diff(a, b);
diff --git a/extract.c b/extract.c
index a8068d2..ac61421 100644
--- a/extract.c
+++ b/extract.c
@@ -118,12 +118,17 @@ int split_patch(struct stream f, struct stream *f1, struct stream *f2)
 			skip_eol(&cp, end);
 			if (state == 1 || state == 3) {
 				char *f;
-				char buf[20];
+				int slen;
+				/* Reserve enough space for 3 integers separated
+				 * by a single space, and prefixed and terminated
+				 * with a null character.
+				 */
+				char buf[(3*12)+1];
 				buf[0] = 0;
 				chunks++;
-				sprintf(buf+1, "%5d %5d %5d", chunks, a, acnt);
-				memcpy(r1.body+r1.len, buf, 18);
-				r1.len += 18;
+				slen = sprintf(buf+1, "%5d %5d %5d", chunks, a, acnt)+1;
+				memcpy(r1.body+r1.len, buf, slen);
+				r1.len += slen;
 				f = func;
 				while (*f == ' ')
 					f++;
@@ -136,11 +141,16 @@ int split_patch(struct stream f, struct stream *f1, struct stream *f2)
 				r1.body[r1.len++] = '\0';
 			}
 			if (state == 2 || state == 3) {
-				char buf[20];
+				int slen;
+				/* Reserve enough space for 3 integers separated
+				 * by a single space, prefixed with a null character
+				 * and terminated with a new line and null character.
+				 */
+				char buf[(3*12)+2];
 				buf[0] = 0;
-				sprintf(buf+1, "%5d %5d %5d\n", chunks, c, bcnt);
-				memcpy(r2.body+r2.len, buf, 20);
-				r2.len += 20;
+				slen = sprintf(buf+1, "%5d %5d %5d\n", chunks, c, bcnt)+2;
+				memcpy(r2.body+r2.len, buf, slen);
+				r2.len += slen;
 			}
 			if (state)
 				func[0] = 0;
@@ -189,6 +199,12 @@ int split_patch(struct stream f, struct stream *f1, struct stream *f2)
 				cp++;
 				copyline(&r2, &cp, end);
 				bcnt--;
+			} else if (*cp == '\n') {
+				/* Empty line - treat like " \n" - a blank line in both */
+				char *cp2 = cp;
+				copyline(&r1, &cp, end);
+				copyline(&r2, &cp2, end);
+				acnt --; bcnt--;
 			} else {
 				fprintf(stderr, "%s: bad unified patch at line %d\n",
 					Cmd, lineno);
diff --git a/merge2.c b/merge2.c
index 9682a90..49f43f6 100644
--- a/merge2.c
+++ b/merge2.c
@@ -224,7 +224,10 @@ int isolate_conflicts(struct file af, struct file bf, struct file cf,
 				 * might be after the last newline, if there
 				 * is one, or might be at the start
 				 */
-				for (k = m[j].al; k > 0; k--)
+				for (k = m[j].al; k > 0; k--) {
+					if (m[j].a + k >= af.elcnt)
+						/* FIXME impossible!*/
+						break;
 					if (ends_line(af.list[m[j].a+k-1])) {
 						if (firstk > m[j].al)
 							firstk = k;
@@ -234,6 +237,7 @@ int isolate_conflicts(struct file af, struct file bf, struct file cf,
 							break;
 						}
 					}
+				}
 				if (k > 0)
 					m[j].hi = k;
 				else if (j == 0)
@@ -380,7 +384,12 @@ int isolate_conflicts(struct file af, struct file bf, struct file cf,
 			if (m[i].type == End)
 				break;
 		}
-		for (k = 1; k < m[i].al; k++)
+		for (k = 1; k < m[i].al; k++) {
+			if (m[i].a + k >= af.elcnt)
+				/* FIXME this should be impossible, but
+				 * it happened.
+				 */
+				break;
 			if (words || ends_line(af.list[m[i].a+k])) {
 				if (unmatched)
 					unmatched--;
@@ -389,6 +398,7 @@ int isolate_conflicts(struct file af, struct file bf, struct file cf,
 				if (extraneous)
 					extraneous--;
 			}
+		}
 	}
 	if (!show_wiggles)
 		*wigglesp = wiggles;
@@ -615,7 +625,7 @@ static int printrange(FILE *out, struct file *f, int start, int len,
 		      int offset)
 {
 	int lines = 0;
-	while (len > 0) {
+	while (len > 0 && start < f->elcnt) {
 		struct elmnt e = f->list[start];
 		printword(out, e);
 		if (e.start[e.plen-1] == '\n' &&
diff --git a/parse.c b/parse.c
index 897d0f0..3ef8649 100644
--- a/parse.c
+++ b/parse.c
@@ -296,7 +296,7 @@ struct plist *parse_patch(FILE *f, FILE *of, int *np)
 			if (of)
 				fputc(c, of);
 
-		start = ftell(of ?: f);
+		start = ftell(of ? of : f);
 
 		if (c == EOF)
 			break;
@@ -312,7 +312,7 @@ struct plist *parse_patch(FILE *f, FILE *of, int *np)
 			else
 				pos = target2;
 		}
-		end = ftell(of ?: f);
+		end = ftell(of ? of : f);
 		if (pos > target2)
 			end -= (pos - target2) - 1;
 		plist = patch_add_file(plist, np,
diff --git a/split.c b/split.c
index 367a590..27f9b7e 100644
--- a/split.c
+++ b/split.c
@@ -125,9 +125,13 @@ struct file split_stream(struct stream s, int type)
 {
 	int cnt;
 	struct file f;
-
 	char *c, *end;
 
+	if (!s.body) {
+		f.list = NULL;
+		f.elcnt = 0;
+		return f;
+	}
 	end = s.body+s.len;
 	c = s.body;
 
diff --git a/vpatch.c b/vpatch.c
index 2c574c8..47e6319 100644
--- a/vpatch.c
+++ b/vpatch.c
@@ -801,7 +801,7 @@ static int mcontains(struct mpos pos,
 	struct elmnt e;
 	int found = 0;
 	struct mp mp;
-	int o;
+	int o = 0;
 	int len = strlen(search);
 
 	do {
@@ -1292,7 +1292,7 @@ static void *memdup(void *a, int len)
 }
 
 static int merge_window(struct plist *p, FILE *f, int reverse, int replace,
-			int selftest, int ignore_blanks, int just_diff)
+			int selftest, int ignore_blanks, int just_diff, int backup)
 {
 	/* Display the merge window in one of the selectable modes,
 	 * starting with the 'merge' mode.
@@ -1680,8 +1680,8 @@ static int merge_window(struct plist *p, FILE *f, int reverse, int replace,
 			attrset(A_NORMAL);
 		}
 		if (num >= 0) {
-			char buf[10];
-			snprintf(buf, 10, "%d ", num);
+			char buf[12+1];
+			snprintf(buf, sizeof(buf), "%d ", num);
 			addstr(buf);
 		}
 		if (meta & META(0))
@@ -1790,8 +1790,8 @@ static int merge_window(struct plist *p, FILE *f, int reverse, int replace,
 					ci.merger, 0, &p->wiggles);
 				p->chunks = p->conflicts;
 				save_merge(fm, fb, fa, ci.merger,
-					   p->outfile ?: p->file,
-					   p->outfile ? 0 : !p->is_merge);
+					   p->outfile ? p->outfile : p->file,
+					   backup && (p->outfile ? 0 : !p->is_merge));
 			}
 			if (!just_diff)
 				free(sm.body);
@@ -2347,7 +2347,7 @@ static int show_merge(char *origname, FILE *patch, int reverse,
 		      int is_merge, char *before, char *after,
 		      int replace, char *outfile,
 		      int selftest, int ignore_blanks,
-		      int just_diff)
+		      int just_diff, int backup)
 {
 	struct plist p = {0};
 
@@ -2366,7 +2366,7 @@ static int show_merge(char *origname, FILE *patch, int reverse,
 
 	freopen("/dev/null","w",stderr);
 	return merge_window(&p, patch, reverse, replace, selftest,
-			    ignore_blanks, just_diff);
+			    ignore_blanks, just_diff, backup);
 }
 
 static void calc_one(struct plist *pl, FILE *f, int reverse,
@@ -2427,7 +2427,7 @@ static void calc_one(struct plist *pl, FILE *f, int reverse,
 static int get_prev(int pos, struct plist *pl, int n, int mode)
 {
 	int found = 0;
-	if (pos == -1)
+	if (pos == -1 || pl == NULL)
 		return pos;
 	do {
 		if (pl[pos].prev == -1)
@@ -2487,7 +2487,7 @@ static int get_next(int pos, struct plist *pl, int n, int mode,
 static void draw_one(int row, struct plist *pl, FILE *f, int reverse,
 		     int ignore_blanks, int just_diff)
 {
-	char hdr[12];
+	char hdr[2*12];
 	hdr[0] = 0;
 
 	if (pl == NULL) {
@@ -2538,7 +2538,7 @@ static void draw_one(int row, struct plist *pl, FILE *f, int reverse,
 }
 
 static int save_one(FILE *f, struct plist *pl, int reverse,
-		    int ignore_blanks)
+		    int ignore_blanks, int backup)
 {
 	struct stream sp, sa, sb, sm;
 	struct file fa, fb, fm;
@@ -2559,7 +2559,7 @@ static int save_one(FILE *f, struct plist *pl, int reverse,
 	csl2 = diff_patch(fb, fa);
 	ci = make_merger(fm, fb, fa, csl1, csl2, 0, 1, 0);
 	return save_merge(fm, fb, fa, ci.merger,
-			  pl->file, 1);
+			  pl->file, backup);
 }
 
 static char *main_help[] = {
@@ -2613,8 +2613,8 @@ static char *saveall_query[] = {
 	"  Q = Don't quit just yet",
 	NULL
 };
-static void main_window(struct plist *pl, int *np, FILE *f, int reverse,
-			int replace, int ignore_blanks, int just_diff)
+static void main_window(struct plist *pl, int np, FILE *f, int reverse,
+			int replace, int ignore_blanks, int just_diff, int backup)
 {
 	/* The main window lists all files together with summary information:
 	 * number of chunks, number of wiggles, number of conflicts.
@@ -2669,7 +2669,6 @@ static void main_window(struct plist *pl, int *np, FILE *f, int reverse,
 
 	freopen("/dev/null","w",stderr);
 	term_init(1);
-	pl = sort_patches(pl, np);
 
 	while (1) {
 		if (refresh == 2) {
@@ -2694,7 +2693,7 @@ static void main_window(struct plist *pl, int *np, FILE *f, int reverse,
 				row = rows-1;
 			tpos = pos;
 			for (i = row; i > 1; i--) {
-				tpos = get_prev(tpos, pl, *np, mode);
+				tpos = get_prev(tpos, pl, np, mode);
 				if (tpos == -1) {
 					row = row - i + 1;
 					break;
@@ -2704,11 +2703,11 @@ static void main_window(struct plist *pl, int *np, FILE *f, int reverse,
 			tpos = pos;
 			for (i = row; i >= 1; i--) {
 				draw_one(i, &pl[tpos], f, reverse, ignore_blanks, just_diff);
-				tpos = get_prev(tpos, pl, *np, mode);
+				tpos = get_prev(tpos, pl, np, mode);
 			}
 			tpos = pos;
 			for (i = row+1; i < rows; i++) {
-				tpos = get_next(tpos, pl, *np, mode, f, reverse,ignore_blanks, just_diff);
+				tpos = get_next(tpos, pl, np, mode, f, reverse,ignore_blanks, just_diff);
 				if (tpos >= 0)
 					draw_one(i, &pl[tpos], f, reverse, ignore_blanks, just_diff);
 				else
@@ -2742,7 +2741,7 @@ static void main_window(struct plist *pl, int *np, FILE *f, int reverse,
 		case 'N':
 		case 'N'-64:
 		case KEY_DOWN:
-			tpos = get_next(pos, pl, *np, mode, f, reverse, ignore_blanks, just_diff);
+			tpos = get_next(pos, pl, np, mode, f, reverse, ignore_blanks, just_diff);
 			if (tpos >= 0) {
 				pos = tpos;
 				row++;
@@ -2753,7 +2752,7 @@ static void main_window(struct plist *pl, int *np, FILE *f, int reverse,
 		case 'P':
 		case 'P'-64:
 		case KEY_UP:
-			tpos = get_prev(pos, pl, *np, mode);
+			tpos = get_prev(pos, pl, np, mode);
 			if (tpos >= 0) {
 				pos = tpos;
 				row--;
@@ -2764,13 +2763,13 @@ static void main_window(struct plist *pl, int *np, FILE *f, int reverse,
 			if (getmouse(&mevent) != OK)
 				break;
 			while (row < mevent.y &&
-			       (tpos = get_next(pos, pl, *np, mode, f, reverse, ignore_blanks, just_diff))
+			       (tpos = get_next(pos, pl, np, mode, f, reverse, ignore_blanks, just_diff))
 			       >= 0) {
 				pos = tpos;
 				row++;
 			}
 			while (row > mevent.y &&
-			       (tpos = get_prev(pos, pl, *np, mode)) >= 0) {
+			       (tpos = get_prev(pos, pl, np, mode)) >= 0) {
 				pos = tpos;
 				row--;
 			}
@@ -2790,9 +2789,11 @@ static void main_window(struct plist *pl, int *np, FILE *f, int reverse,
 			} else {
 				int c;
 				if (pl[pos].is_merge)
-					c = merge_window(&pl[pos], NULL, reverse, 0, 0, ignore_blanks, just_diff);
+					c = merge_window(&pl[pos], NULL, reverse, 0, 0,
+					                 ignore_blanks, just_diff, backup);
 				else
-					c = merge_window(&pl[pos], f, reverse, 0, 0, ignore_blanks, just_diff);
+					c = merge_window(&pl[pos], f, reverse, 0, 0,
+					                 ignore_blanks, just_diff, backup);
 				refresh = 2;
 				if (c) {
 					pl[pos].is_merge = 1;
@@ -2822,7 +2823,7 @@ static void main_window(struct plist *pl, int *np, FILE *f, int reverse,
 		case 'q':
 			cnt = 0;
 			any = 0;
-			for (i = 0; i < *np; i++)
+			for (i = 0; i < np; i++)
 				if (pl[i].end && !pl[i].is_merge)
 					cnt++;
 				else if (pl[i].end)
@@ -2843,12 +2844,12 @@ static void main_window(struct plist *pl, int *np, FILE *f, int reverse,
 			if (ans < 0)
 				break;
 			if (ans) {
-				for (i = 0; i < *np; i++) {
+				for (i = 0; i < np; i++) {
 					if (pl[i].end
 					    && !pl[i].is_merge)
 						save_one(f, &pl[i],
 							 reverse,
-							ignore_blanks);
+							 ignore_blanks, backup);
 				}
 			} else
 				cnt = 0;
@@ -2879,7 +2880,7 @@ static void main_window(struct plist *pl, int *np, FILE *f, int reverse,
 				/* Already saved */
 				mesg = "File is already saved.";
 			} else {
-				if (save_one(f, &pl[pos], reverse, ignore_blanks) == 0) {
+				if (save_one(f, &pl[pos], reverse, ignore_blanks, backup) == 0) {
 					pl[pos].is_merge = 1;
 					snprintf(mesg_buf, cols,
 						 "Saved file %s.",
@@ -2900,6 +2901,8 @@ static void main_window(struct plist *pl, int *np, FILE *f, int reverse,
 				mesg = "Cannot restore a folder.";
 			else if (!pl[pos].is_merge)
 				mesg = "File has not been saved, cannot restore.";
+			else if (!backup)
+				mesg = "Backups are disabled, nothing to restore!";
 			else {
 				/* rename foo.porig to foo, and clear is_merge */
 				char *file = pl[pos].file;
@@ -2919,7 +2922,7 @@ static void main_window(struct plist *pl, int *np, FILE *f, int reverse,
 		case 'I': /* Toggle ignoring blanks */
 			ignore_blanks = ignore_blanks ? 0 : IgnoreBlanks;
 			refresh = 2;
-			for (i = 0; i < *np; i++)
+			for (i = 0; i < np; i++)
 				pl[i].calced = 0;
 			break;
 
@@ -3014,7 +3017,7 @@ static void term_init(int doraw)
 
 int vpatch(int argc, char *argv[], int patch, int strip,
 	   int reverse, int replace, char *outfilename,
-	   int selftest, int ignore_blanks)
+	   int selftest, int ignore_blanks, int backup)
 {
 	/* NOTE argv[0] is first arg...
 	 * Behaviour depends on number of args and 'patch'.
@@ -3071,7 +3074,9 @@ int vpatch(int argc, char *argv[], int patch, int strip,
 			fprintf(stderr, "%s: aborting\n", Cmd);
 			exit(2);
 		}
-		main_window(pl, &num_patches, in, reverse, replace, ignore_blanks, just_diff);
+		pl = sort_patches(pl, &num_patches);
+		main_window(pl, num_patches, in, reverse, replace, ignore_blanks,
+		            just_diff, backup);
 		plist_free(pl, num_patches);
 		fclose(in);
 		break;
@@ -3089,7 +3094,9 @@ int vpatch(int argc, char *argv[], int patch, int strip,
 				fprintf(stderr, "%s: aborting\n", Cmd);
 				exit(2);
 			}
-			main_window(pl, &num_patches, f, reverse, replace,ignore_blanks, just_diff);
+			pl = sort_patches(pl, &num_patches);
+			main_window(pl, num_patches, f, reverse, replace,
+			            ignore_blanks, just_diff, backup);
 			plist_free(pl, num_patches);
 		} else if (strlen(argv[0]) > 4 &&
 			 strcmp(argv[0]+strlen(argv[0])-4, ".rej") == 0) {
@@ -3097,34 +3104,34 @@ int vpatch(int argc, char *argv[], int patch, int strip,
 			origname[strlen(origname) - 4] = '\0';
 			show_merge(origname, f, reverse, 0, NULL, NULL,
 				   replace, outfilename,
-				   selftest, ignore_blanks, just_diff);
+				   selftest, ignore_blanks, just_diff, backup);
 		} else
 			show_merge(argv[0], f, reverse, 1, NULL, NULL,
 				   replace, outfilename,
-				   selftest, ignore_blanks, just_diff);
+				   selftest, ignore_blanks, just_diff, backup);
 
 		break;
 	case 2: /* an orig and a diff/.rej  or two files */
 		if (just_diff) {
 			show_merge(NULL, NULL, reverse, 0, argv[0], argv[1],
 				   replace, outfilename,
-				   selftest, ignore_blanks, just_diff);
+				   selftest, ignore_blanks, just_diff, backup);
 			break;
 		}
 		f = fopen(argv[1], "r");
-		check_dir(argv[1], fileno(f));
 		if (!f) {
 			fprintf(stderr, "%s: cannot open %s\n", Cmd, argv[0]);
 			exit(1);
 		}
+		check_dir(argv[1], fileno(f));
 		show_merge(argv[0], f, reverse, 0, NULL, NULL,
 			   replace, outfilename,
-			   selftest, ignore_blanks, just_diff);
+			   selftest, ignore_blanks, just_diff, backup);
 		break;
 	case 3: /* orig, before, after */
 		show_merge(argv[0], NULL, reverse, 0, argv[1], argv[2],
 			   replace, outfilename,
-			   selftest, ignore_blanks, just_diff);
+			   selftest, ignore_blanks, just_diff, backup);
 		break;
 	}
 
diff --git a/wiggle.1 b/wiggle.1
index 7437604..f14166f 100644
--- a/wiggle.1
+++ b/wiggle.1
@@ -3,6 +3,7 @@
 .\"
 .\" Copyright (C) 2003 Neil Brown <neilb@cse.unsw.edu.au>
 .\" Copyright (C) 2010-2013 Neil Brown <neilb@suse.de>
+.\" Copyright (C) 2018-2019 Neil Brown <neil@brown.name>
 .\"
 .\"
 .\"    This program is free software; you can redistribute it and/or modify
@@ -19,9 +20,9 @@
 .\"    along with this program.
 .\"
 .\"    Author: Neil Brown
-.\"    Email: <neilb@suse.de>
+.\"    Email: <neil@brown.name>
 .\"
-.TH WIGGLE 1 "" v1.1
+.TH WIGGLE 1 "" v1.2
 .SH NAME
 wiggle \- apply rejected patches and perform word-wise diffs
 .SH SYNOPSIS
@@ -211,6 +212,12 @@ mode, this instructs
 .I wiggle
 to always save the resulting merge when exiting.
 .TP
+.B \-\-no-backup
+Normally when an original file is replaced with the merged result, that
+file is renamed to have a ".porig" extension, so that it is preserved.
+If you don't want to keep the original, use this option to suppress
+the backup.
+.TP
 .BR \-o ", " \-\-output=
 Rather than writing the result to stdout or to replace the original
 file, this requests that the output be written to the given file.
@@ -358,13 +365,15 @@ If the
 .B \-r
 flag is given, the output is written to a file
 which replaces the original given file. In this case the original file
-is renamed to have a
+will normally be renamed to have a
 .B .porig
 suffix (for "patched original" which makes sense if you first use
 .I patch
 to apply a patch, and then use
 .I wiggle
-to wiggle the rejects in).
+to wiggle the rejects in).  This can be suppressed with the
+.B \-\-no\-backup
+uption.
 .P
 Further if the
 .B -o
diff --git a/wiggle.c b/wiggle.c
index 4289573..aed7ac9 100644
--- a/wiggle.c
+++ b/wiggle.c
@@ -543,6 +543,8 @@ static int do_merge(int argc, char *argv[], int obj, int blanks,
 			fprintf(stderr, "%s: %s already exists\n",
 				Cmd,
 				orignew);
+			free(replacename);
+			free(orignew);
 			return 2;
 		}
 		strcat(replacename, "XXXXXX");
@@ -552,6 +554,8 @@ static int do_merge(int argc, char *argv[], int obj, int blanks,
 				"%s: could not create temporary file for %s\n",
 				Cmd,
 				replacename);
+			free(replacename);
+			free(orignew);
 			return 2;
 		}
 		outfile = fdopen(fd, "w");
@@ -589,6 +593,24 @@ static int do_merge(int argc, char *argv[], int obj, int blanks,
 	if (outfilename)
 		fclose(outfile);
 	else if (replace) {
+		struct stat statbuf;
+
+		if (stat(argv[0], &statbuf) != 0) {
+			fprintf(stderr,
+				"%s: failed to stat original file. - %s\n",
+				Cmd, strerror(errno));
+			free(replacename);
+			free(orignew);
+			return 2;
+		}
+		if (fchmod(fileno(outfile), statbuf.st_mode) != 0) {
+			fprintf(stderr,
+				"%s: failed to change permission of new file. - %s\n",
+				Cmd, strerror(errno));
+			free(replacename);
+			free(orignew);
+			return 2;
+		}
 		fclose(outfile);
 		if (rename(argv[0], orignew) == 0 &&
 		    rename(replacename, argv[0]) == 0)
@@ -597,9 +619,13 @@ static int do_merge(int argc, char *argv[], int obj, int blanks,
 			fprintf(stderr,
 				"%s: failed to move new file into place.\n",
 				Cmd);
+			free(replacename);
+			free(orignew);
 			return 2;
 		}
 	}
+	free(replacename);
+	free(orignew);
 	if (show_wiggles)
 		return ci.conflicts + ci.wiggles > 0;
 	else
@@ -664,6 +690,7 @@ int main(int argc, char *argv[])
 	int mode = 0;
 	int obj = 0;
 	int replace = 0;
+	int backup = 1;
 	int which = 0;
 	int ispatch = 0;
 	int reverse = 0;
@@ -745,6 +772,9 @@ int main(int argc, char *argv[])
 		case 'r':
 			replace = 1;
 			continue;
+		case NO_BACKUP:
+			backup = 0;
+			continue;
 		case 'o':
 			outfile = optarg;
 			replace = 1;
@@ -802,7 +832,7 @@ int main(int argc, char *argv[])
 	if (mode == 'B') {
 		vpatch(argc-optind, argv+optind, ispatch,
 		       strip, reverse, replace, outfile, selftest,
-		       ignore_blanks);
+		       ignore_blanks, backup);
 		/* should not return */
 		exit(1);
 	}
diff --git a/wiggle.h b/wiggle.h
index 6b967f3..0de65b2 100644
--- a/wiggle.h
+++ b/wiggle.h
@@ -191,7 +191,7 @@ extern int do_trace;
 extern int vpatch(int argc, char *argv[], int patch, int strip,
 		  int reverse, int replace, char *outfile,
 		  int selftest,
-		  int ignore_blanks);
+		  int ignore_blanks, int backup);
 
 extern char *Cmd;
 extern char Version[];
@@ -200,6 +200,7 @@ extern struct option long_options[];
 enum other_options {
 	SELF_TEST = 300,
 	REPORT_WIGGLES = 301,
+	NO_BACKUP,
 };
 extern char Usage[];
 extern char Help[];
diff --git a/wiggle.spec b/wiggle.spec
index f2b6241..9849e25 100644
--- a/wiggle.spec
+++ b/wiggle.spec
@@ -1,6 +1,6 @@
 Summary: A tool for applying patches with conflicts
 Name: wiggle
-Version: 1.1
+Version: 1.2
 Release: 1
 License: GPL
 Group: Development/Tools 

Debdiff

[The following lists of changes regard files as different if they have different names, permissions or owners.]

Files in second set of .debs but not in first

-rw-r--r--  root/root   /usr/lib/debug/.build-id/ae/538f70e7620766f3dd98a42f2d3dcb40ceeb93.debug

Files in first set of .debs but not in second

-rw-r--r--  root/root   /usr/lib/debug/.build-id/12/441148e676fcb3442a7d5ba8b6269769ff03d7.debug
-rw-r--r--  root/root   /usr/share/doc/wiggle/changelog.gz

No differences were encountered between the control files of package wiggle

Control files of package wiggle-dbgsym: lines which differ (wdiff format)

  • Build-Ids: 12441148e676fcb3442a7d5ba8b6269769ff03d7 ae538f70e7620766f3dd98a42f2d3dcb40ceeb93

More details

Full run details