[PATCH 2/3] stripspace: Implement --count-lines option

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



As suggested in the small project ideas [1], implement a --count-lines
options for git stripspace to be able to omit calling

  git stripspace --strip-comments < infile | wc -l

e.g. in git-rebase--interactive.sh. The above command can now be
replaced by:

  git stripspace --strip-comments --count-lines < infile

This will also make it easier to port git-rebase--interactive.sh to C
later on.

Furthermore, add the corresponding documentation and tests.

[1] https://git.wiki.kernel.org/index.php/SmallProjectsIdeas#implement_.27--count-lines.27_in_.27git_stripspace.27

Signed-off-by: Tobias Klauser <tklauser@xxxxxxxxxx>
---
 Documentation/git-stripspace.txt | 13 ++++++++-
 builtin/stripspace.c             | 57 ++++++++++++++++++++++------------------
 strbuf.c                         | 12 ++++++---
 strbuf.h                         |  5 ++--
 t/t0030-stripspace.sh            | 36 +++++++++++++++++++++++++
 5 files changed, 92 insertions(+), 31 deletions(-)

diff --git a/Documentation/git-stripspace.txt b/Documentation/git-stripspace.txt
index 60328d5..411e17c 100644
--- a/Documentation/git-stripspace.txt
+++ b/Documentation/git-stripspace.txt
@@ -9,7 +9,7 @@ git-stripspace - Remove unnecessary whitespace
 SYNOPSIS
 --------
 [verse]
-'git stripspace' [-s | --strip-comments] < input
+'git stripspace' [-s | --strip-comments] [-C | --count-lines] < input
 'git stripspace' [-c | --comment-lines] < input
 
 DESCRIPTION
@@ -44,6 +44,11 @@ OPTIONS
 	be terminated with a newline. On empty lines, only the comment character
 	will be prepended.
 
+-C::
+--count-lines::
+	Output the number of resulting lines after stripping. This is equivalent
+	to calling 'git stripspace | wc -l'.
+
 EXAMPLES
 --------
 
@@ -88,6 +93,12 @@ Use 'git stripspace --strip-comments' to obtain:
 |The end.$
 ---------
 
+Use 'git stripspace --count-lines' to obtain:
+
+---------
+|5$
+---------
+
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/builtin/stripspace.c b/builtin/stripspace.c
index f677093..7882edd 100644
--- a/builtin/stripspace.c
+++ b/builtin/stripspace.c
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "parse-options.h"
 #include "strbuf.h"
 
 static void comment_lines(struct strbuf *buf)
@@ -12,45 +13,51 @@ static void comment_lines(struct strbuf *buf)
 	free(msg);
 }
 
-static const char *usage_msg = "\n"
-"  git stripspace [-s | --strip-comments] < input\n"
-"  git stripspace [-c | --comment-lines] < input";
+static const char * const usage_msg[] = {
+	N_("git stripspace [-s | --strip-comments] [-C | --count-lines] < input"),
+	N_("git stripspace [-c | --comment-lines] < input"),
+	NULL
+};
 
 int cmd_stripspace(int argc, const char **argv, const char *prefix)
 {
 	struct strbuf buf = STRBUF_INIT;
-	int strip_comments = 0;
-	enum { INVAL = 0, STRIP_SPACE = 1, COMMENT_LINES = 2 } mode = STRIP_SPACE;
-
-	if (argc == 2) {
-		if (!strcmp(argv[1], "-s") ||
-		    !strcmp(argv[1], "--strip-comments")) {
-			strip_comments = 1;
-		} else if (!strcmp(argv[1], "-c") ||
-			   !strcmp(argv[1], "--comment-lines")) {
-			mode = COMMENT_LINES;
-		} else {
-			mode = INVAL;
-		}
-	} else if (argc > 1) {
-		mode = INVAL;
-	}
+	int comment_mode = 0, count_lines = 0, strip_comments = 0;
+	size_t lines = 0;
+
+	const struct option options[] = {
+		OPT_BOOL('s', "strip-comments", &strip_comments,
+			 N_("skip and remove all lines starting with comment character")),
+		OPT_BOOL('c', "comment-lines", &comment_mode,
+			 N_("prepend comment character and blank to each line")),
+		OPT_BOOL('C', "count-lines", &count_lines, N_("print line count")),
+		OPT_END()
+	};
 
-	if (mode == INVAL)
-		usage(usage_msg);
+	argc = parse_options(argc, argv, prefix, options, usage_msg,
+			     PARSE_OPT_KEEP_DASHDASH);
 
-	if (strip_comments || mode == COMMENT_LINES)
+	if (comment_mode && (count_lines || strip_comments))
+		usage_with_options(usage_msg, options);
+
+	if (strip_comments || comment_mode)
 		git_config(git_default_config, NULL);
 
 	if (strbuf_read(&buf, 0, 1024) < 0)
 		die_errno("could not read the input");
 
-	if (mode == STRIP_SPACE)
-		strbuf_stripspace(&buf, strip_comments);
+	if (!comment_mode)
+		lines = strbuf_stripspace(&buf, strip_comments);
 	else
 		comment_lines(&buf);
 
-	write_or_die(1, buf.buf, buf.len);
+	if (!count_lines)
+		write_or_die(1, buf.buf, buf.len);
+	else {
+		struct strbuf tmp = STRBUF_INIT;
+		strbuf_addf(&tmp, "%zu\n", lines);
+		write_or_die(1, tmp.buf, tmp.len);
+	}
 	strbuf_release(&buf);
 	return 0;
 }
diff --git a/strbuf.c b/strbuf.c
index 9583875..45ea933 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -775,11 +775,13 @@ static size_t cleanup(char *line, size_t len)
  *
  * Enable skip_comments to skip every line starting with comment
  * character.
+ *
+ * Returns the number of lines in the resulting strbuf.
  */
-void strbuf_stripspace(struct strbuf *sb, int skip_comments)
+size_t strbuf_stripspace(struct strbuf *sb, int skip_comments)
 {
 	int empties = 0;
-	size_t i, j, len, newlen;
+	size_t i, j, len, newlen, lines = 0;
 	char *eol;
 
 	/* We may have to add a newline. */
@@ -797,15 +799,19 @@ void strbuf_stripspace(struct strbuf *sb, int skip_comments)
 
 		/* Not just an empty line? */
 		if (newlen) {
-			if (empties > 0 && j > 0)
+			if (empties > 0 && j > 0) {
 				sb->buf[j++] = '\n';
+				lines++;
+			}
 			empties = 0;
 			memmove(sb->buf + j, sb->buf + i, newlen);
 			sb->buf[newlen + j++] = '\n';
+			lines++;
 		} else {
 			empties++;
 		}
 	}
 
 	strbuf_setlen(sb, j);
+	return lines;
 }
diff --git a/strbuf.h b/strbuf.h
index 5397d91..7d33f39 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -416,9 +416,10 @@ extern void strbuf_add_absolute_path(struct strbuf *sb, const char *path);
 
 /**
  * Strip whitespace from a buffer. The second parameter controls if
- * comments are considered contents to be removed or not.
+ * comments are considered contents to be removed or not. Returns the
+ * number of lines in the resulting buffer.
  */
-extern void strbuf_stripspace(struct strbuf *buf, int skip_comments);
+extern size_t strbuf_stripspace(struct strbuf *buf, int skip_comments);
 
 /**
  * Temporary alias until all topic branches have switched to use
diff --git a/t/t0030-stripspace.sh b/t/t0030-stripspace.sh
index 29e91d8..5471a5a 100755
--- a/t/t0030-stripspace.sh
+++ b/t/t0030-stripspace.sh
@@ -438,4 +438,40 @@ test_expect_success 'avoid SP-HT sequence in commented line' '
 	test_cmp expect actual
 '
 
+test_expect_success '--count-lines with newline only' '
+	printf "0\n" >expect &&
+	printf "\n" | git stripspace -C >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success '--count-lines with single line' '
+	printf "1\n" >expect &&
+	printf "foo\n" | git stripspace -C >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success '--count-lines with single line preceeded by empty line' '
+	printf "1\n" >expect &&
+	printf "\nfoo" | git stripspace -C >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success '--count-lines with single line followed by empty line' '
+	printf "1\n" >expect &&
+	printf "foo\n\n" | git stripspace -C >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success '--count-lines with multiple lines and consecutive newlines' '
+	printf "5\n" >expect &&
+	printf "\none\n\n\nthree\nfour\nfive\n" | git stripspace -C >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success '--count-lines combined with --strip-comments' '
+	printf "5\n" >expect &&
+	printf "\n# stripped\none\n#stripped\n\nthree\nfour\nfive\n" | git stripspace -s -C >actual &&
+	test_cmp expect actual
+'
+
 test_done
-- 
2.6.1.145.gb27dacc


--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]