builtin-stripspace.con commit describe: Break annotated tag ties by tagger date (03e8b54)
   1#include "builtin.h"
   2#include "cache.h"
   3
   4/*
   5 * Returns the length of a line, without trailing spaces.
   6 *
   7 * If the line ends with newline, it will be removed too.
   8 */
   9static size_t cleanup(char *line, size_t len)
  10{
  11        while (len) {
  12                unsigned char c = line[len - 1];
  13                if (!isspace(c))
  14                        break;
  15                len--;
  16        }
  17
  18        return len;
  19}
  20
  21/*
  22 * Remove empty lines from the beginning and end
  23 * and also trailing spaces from every line.
  24 *
  25 * Note that the buffer will not be NUL-terminated.
  26 *
  27 * Turn multiple consecutive empty lines between paragraphs
  28 * into just one empty line.
  29 *
  30 * If the input has only empty lines and spaces,
  31 * no output will be produced.
  32 *
  33 * If last line does not have a newline at the end, one is added.
  34 *
  35 * Enable skip_comments to skip every line starting with "#".
  36 */
  37void stripspace(struct strbuf *sb, int skip_comments)
  38{
  39        int empties = 0;
  40        size_t i, j, len, newlen;
  41        char *eol;
  42
  43        /* We may have to add a newline. */
  44        strbuf_grow(sb, 1);
  45
  46        for (i = j = 0; i < sb->len; i += len, j += newlen) {
  47                eol = memchr(sb->buf + i, '\n', sb->len - i);
  48                len = eol ? eol - (sb->buf + i) + 1 : sb->len - i;
  49
  50                if (skip_comments && len && sb->buf[i] == '#') {
  51                        newlen = 0;
  52                        continue;
  53                }
  54                newlen = cleanup(sb->buf + i, len);
  55
  56                /* Not just an empty line? */
  57                if (newlen) {
  58                        if (empties > 0 && j > 0)
  59                                sb->buf[j++] = '\n';
  60                        empties = 0;
  61                        memmove(sb->buf + j, sb->buf + i, newlen);
  62                        sb->buf[newlen + j++] = '\n';
  63                } else {
  64                        empties++;
  65                }
  66        }
  67
  68        strbuf_setlen(sb, j);
  69}
  70
  71int cmd_stripspace(int argc, const char **argv, const char *prefix)
  72{
  73        struct strbuf buf = STRBUF_INIT;
  74        int strip_comments = 0;
  75
  76        if (argc == 2 && (!strcmp(argv[1], "-s") ||
  77                                !strcmp(argv[1], "--strip-comments")))
  78                strip_comments = 1;
  79        else if (argc > 1)
  80                usage("git stripspace [-s | --strip-comments] < <stream>");
  81
  82        if (strbuf_read(&buf, 0, 1024) < 0)
  83                die_errno("could not read the input");
  84
  85        stripspace(&buf, strip_comments);
  86
  87        write_or_die(1, buf.buf, buf.len);
  88        strbuf_release(&buf);
  89        return 0;
  90}