From: "Kristian Høgsberg" <krh@redhat.com>
To: git@vger.kernel.org
Cc: "Kristian Høgsberg" <krh@redhat.com>
Subject: [PATCH 6/9] Rewrite launch_editor, create_tag and stripspace to use strbufs.
Date: Wed, 5 Sep 2007 20:23:35 -0400 [thread overview]
Message-ID: <1189038225525-git-send-email-krh@redhat.com> (raw)
In-Reply-To: <11890382252522-git-send-email-krh@redhat.com>
Signed-off-by: Kristian Høgsberg <krh@redhat.com>
---
builtin-stripspace.c | 45 +++++++++++++-------------
builtin-tag.c | 84 +++++++++++++++++++++-----------------------------
builtin.h | 1 -
strbuf.c | 43 +++++---------------------
strbuf.h | 2 +
5 files changed, 68 insertions(+), 107 deletions(-)
diff --git a/builtin-stripspace.c b/builtin-stripspace.c
index 916355c..f0264a8 100644
--- a/builtin-stripspace.c
+++ b/builtin-stripspace.c
@@ -1,5 +1,6 @@
#include "builtin.h"
#include "cache.h"
+#include "strbuf.h"
/*
* Returns the length of a line, without trailing spaces.
@@ -34,34 +35,34 @@ static size_t cleanup(char *line, size_t len)
* If the input has only empty lines and spaces,
* no output will be produced.
*
- * If last line has a newline at the end, it will be removed.
+ * If the last line does not have a newline, one will be added.
*
* Enable skip_comments to skip every line starting with "#".
*/
-size_t stripspace(char *buffer, size_t length, int skip_comments)
+size_t stripspace(struct strbuf *sb, int skip_comments)
{
int empties = -1;
size_t i, j, len, newlen;
char *eol;
- for (i = j = 0; i < length; i += len, j += newlen) {
- eol = memchr(buffer + i, '\n', length - i);
- len = eol ? eol - (buffer + i) + 1 : length - i;
+ for (i = j = 0; i < sb->len; i += len, j += newlen) {
+ eol = memchr(sb->buf + i, '\n', sb->len - i);
+ len = eol ? eol - (sb->buf + i) + 1 : sb->len - i;
- if (skip_comments && len && buffer[i] == '#') {
+ if (skip_comments && len && sb->buf[i] == '#') {
newlen = 0;
continue;
}
- newlen = cleanup(buffer + i, len);
+ newlen = cleanup(sb->buf + i, len);
/* Not just an empty line? */
if (newlen) {
if (empties != -1)
- buffer[j++] = '\n';
+ sb->buf[j++] = '\n';
if (empties > 0)
- buffer[j++] = '\n';
+ sb->buf[j++] = '\n';
empties = 0;
- memmove(buffer + j, buffer + i, newlen);
+ memmove(sb->buf + j, sb->buf + i, newlen);
continue;
}
if (empties < 0)
@@ -69,31 +70,31 @@ size_t stripspace(char *buffer, size_t length, int skip_comments)
empties++;
}
- return j;
+ sb->len = j;
+ if (j > 0)
+ strbuf_add_char(sb, '\n');
+
+ return sb->len;
}
int cmd_stripspace(int argc, const char **argv, const char *prefix)
{
- char *buffer;
- unsigned long size;
+ struct strbuf sb;
int strip_comments = 0;
if (argc > 1 && (!strcmp(argv[1], "-s") ||
!strcmp(argv[1], "--strip-comments")))
strip_comments = 1;
- size = 1024;
- buffer = xmalloc(size);
- if (read_fd(0, &buffer, &size)) {
- free(buffer);
+ strbuf_init(&sb);
+ if (strbuf_read_fd(&sb, 0) < 0) {
+ strbuf_release(&sb);
die("could not read the input");
}
- size = stripspace(buffer, size, strip_comments);
- write_or_die(1, buffer, size);
- if (size)
- putc('\n', stdout);
+ stripspace(&sb, strip_comments);
+ write_or_die(1, sb.buf, sb.len);
+ strbuf_release(&sb);
- free(buffer);
return 0;
}
diff --git a/builtin-tag.c b/builtin-tag.c
index d6d38ad..1aff952 100644
--- a/builtin-tag.c
+++ b/builtin-tag.c
@@ -11,13 +11,14 @@
#include "refs.h"
#include "tag.h"
#include "run-command.h"
+#include "strbuf.h"
static const char builtin_tag_usage[] =
"git-tag [-n [<num>]] -l [<pattern>] | [-a | -s | -u <key-id>] [-f | -d | -v] [-m <msg> | -F <file>] <tagname> [<head>]";
static char signingkey[1000];
-static void launch_editor(const char *path, char **buffer, unsigned long *len)
+static void launch_editor(const char *path, struct strbuf *sb)
{
const char *editor, *terminal;
struct child_process child;
@@ -55,10 +56,9 @@ static void launch_editor(const char *path, char **buffer, unsigned long *len)
fd = open(path, O_RDONLY);
if (fd < 0)
die("could not open '%s': %s", path, strerror(errno));
- if (read_fd(fd, buffer, len)) {
- free(*buffer);
+ if (strbuf_read_fd(sb, fd) < 0) {
die("could not read message file '%s': %s",
- path, strerror(errno));
+ path, strerror(errno));
}
close(fd);
}
@@ -191,7 +191,7 @@ static int verify_tag(const char *name, const char *ref,
return 0;
}
-static ssize_t do_sign(char *buffer, size_t size, size_t max)
+static int do_sign(struct strbuf *sb)
{
struct child_process gpg;
const char *args[4];
@@ -219,17 +219,13 @@ static ssize_t do_sign(char *buffer, size_t size, size_t max)
if (start_command(&gpg))
return error("could not run gpg.");
- write_or_die(gpg.in, buffer, size);
+ write_or_die(gpg.in, sb->buf, sb->len);
close(gpg.in);
gpg.close_in = 0;
- len = read_in_full(gpg.out, buffer + size, max - size);
-
+ len = strbuf_read_fd(sb, gpg.out);
finish_command(&gpg);
- if (len == max - size)
- return error("could not read the entire signature from gpg.");
-
- return size + len;
+ return len;
}
static const char tag_template[] =
@@ -258,26 +254,24 @@ static void create_tag(const unsigned char *object, const char *tag,
char *message, int sign, unsigned char *result)
{
enum object_type type;
- char header_buf[1024], *buffer = NULL;
- int header_len, max_size;
- unsigned long size = 0;
+ struct strbuf sb;
+ int header_len;
type = sha1_object_info(object, NULL);
if (type <= OBJ_NONE)
die("bad object type.");
- header_len = snprintf(header_buf, sizeof(header_buf),
- "object %s\n"
- "type %s\n"
- "tag %s\n"
- "tagger %s\n\n",
- sha1_to_hex(object),
- typename(type),
- tag,
- git_committer_info(1));
-
- if (header_len > sizeof(header_buf) - 1)
- die("tag header too big.");
+ strbuf_init(&sb);
+ strbuf_printf(&sb,
+ "object %s\n"
+ "type %s\n"
+ "tag %s\n"
+ "tagger %s\n\n",
+ sha1_to_hex(object),
+ typename(type),
+ tag,
+ git_committer_info(1));
+ header_len = sb.len;
if (!message) {
char *path;
@@ -292,39 +286,31 @@ static void create_tag(const unsigned char *object, const char *tag,
write_or_die(fd, tag_template, strlen(tag_template));
close(fd);
- launch_editor(path, &buffer, &size);
+ launch_editor(path, &sb);
unlink(path);
free(path);
}
else {
- buffer = message;
- size = strlen(message);
+ strbuf_add(&sb, message, strlen(message));
}
- size = stripspace(buffer, size, 1);
-
- if (!message && !size)
+ if (stripspace(&sb, 1) <= header_len && !message)
die("no tag message?");
- /* insert the header and add the '\n' if needed: */
- max_size = header_len + size + (sign ? MAX_SIGNATURE_LENGTH : 0) + 1;
- buffer = xrealloc(buffer, max_size);
- if (size)
- buffer[size++] = '\n';
- memmove(buffer + header_len, buffer, size);
- memcpy(buffer, header_buf, header_len);
- size += header_len;
-
- if (sign) {
- size = do_sign(buffer, size, max_size);
- if (size < 0)
- die("unable to sign the tag");
- }
+ /* Debatable, but makes t7401-tag.sh pass. Creates an extra
+ * blank line after the header block for tags with empty
+ * messages. */
+ if (sb.len < header_len)
+ strbuf_add_char(&sb, '\n');
- if (write_sha1_file(buffer, size, tag_type, result) < 0)
+ if (sign && do_sign(&sb) < 0)
+ die("unable to sign the tag");
+
+ if (write_sha1_file(sb.buf, sb.len, tag_type, result) < 0)
die("unable to write tag file");
- free(buffer);
+
+ strbuf_release(&sb);
}
int cmd_tag(int argc, const char **argv, const char *prefix)
diff --git a/builtin.h b/builtin.h
index bb72000..91bc595 100644
--- a/builtin.h
+++ b/builtin.h
@@ -7,7 +7,6 @@ extern const char git_version_string[];
extern const char git_usage_string[];
extern void help_unknown_cmd(const char *cmd);
-extern size_t stripspace(char *buffer, size_t length, int skip_comments);
extern int write_tree(unsigned char *sha1, int missing_ok, const char *prefix);
extern void prune_packed_objects(int);
diff --git a/strbuf.c b/strbuf.c
index fcfc05e..ed2afea 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -6,7 +6,8 @@ void strbuf_init(struct strbuf *sb) {
sb->eof = sb->alloc = sb->len = 0;
}
-static void strbuf_begin(struct strbuf *sb) {
+void strbuf_release(struct strbuf *sb)
+{
free(sb->buf);
strbuf_init(sb);
}
@@ -35,7 +36,7 @@ static void strbuf_end(struct strbuf *sb) {
void read_line(struct strbuf *sb, FILE *fp, int term) {
int ch;
- strbuf_begin(sb);
+ strbuf_release(sb);
if (feof(fp)) {
sb->eof = 1;
return;
@@ -73,43 +74,15 @@ void strbuf_printf(struct strbuf *sb, const char *fmt, ...)
{
char buffer[2048];
va_list args;
- int len, size = 2 * sizeof buffer;
+ int len;
va_start(args, fmt);
len = vsnprintf(buffer, sizeof(buffer), fmt, args);
va_end(args);
- if (len > sizeof(buffer)) {
- /*
- * Didn't fit in the buffer, but this vsnprintf at
- * least gives us the required length back. Grow the
- * buffer acccordingly and try again.
- */
- strbuf_grow(sb, len);
- va_start(args, fmt);
- len = vsnprintf(sb->buf + sb->len,
- sb->alloc - sb->len, fmt, args);
- va_end(args);
- } else if (len >= 0) {
- /*
- * The initial vsnprintf fit in the temp buffer, just
- * copy it to the strbuf.
- */
- strbuf_add(sb, buffer, len);
- } else {
- /*
- * This vnsprintf sucks and just returns -1 when the
- * buffer is too small. Keep doubling the size until
- * it fits.
- */
- while (len < 0) {
- strbuf_grow(sb, size);
- va_start(args, fmt);
- len = vsnprintf(sb->buf + sb->len,
- sb->alloc - sb->len, fmt, args);
- va_end(args);
- size *= 2;
- }
- }
+ if (len > sizeof(buffer) || len < 0)
+ die("out of buffer space\n");
+
+ strbuf_add(sb, buffer, len);
}
diff --git a/strbuf.h b/strbuf.h
index 6e630ea..a93b9e1 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -8,10 +8,12 @@ struct strbuf {
};
extern void strbuf_init(struct strbuf *);
+extern void strbuf_release(struct strbuf *);
extern void read_line(struct strbuf *, FILE *, int);
extern void strbuf_add(struct strbuf *sb, const char *data, size_t len);
extern void strbuf_add_char(struct strbuf *sb, int ch);
extern void strbuf_printf(struct strbuf *sb, const char *fmt, ...);
extern int strbuf_read_fd(struct strbuf *sb, int fd);
+extern size_t stripspace(struct strbuf *sb, int skip_comments);
#endif /* STRBUF_H */
--
1.5.2.GIT
next prev parent reply other threads:[~2007-09-06 0:36 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-09-06 0:23 [PATCH 1/9] Enable wt-status output to a given FILE pointer Kristian Høgsberg
2007-09-06 0:23 ` [PATCH 2/9] Enable wt-status to run against non-standard index file Kristian Høgsberg
2007-09-06 0:23 ` [PATCH 3/9] Add strbuf_printf() to do formatted printing to a strbuf Kristian Høgsberg
2007-09-06 0:23 ` [PATCH 4/9] Introduce entry point for launching add--interactive Kristian Høgsberg
2007-09-06 0:23 ` [PATCH 5/9] Introduce strbuf_read_fd() Kristian Høgsberg
2007-09-06 0:23 ` Kristian Høgsberg [this message]
2007-09-06 0:23 ` [PATCH 7/9] Add strbuf_read_path() Kristian Høgsberg
2007-09-06 0:23 ` [PATCH 8/9] Export rerere() and launch_editor() Kristian Høgsberg
2007-09-06 0:23 ` [PATCH 9/9] Implement git commit as a builtin command Kristian Høgsberg
2007-09-06 16:59 ` Johannes Schindelin
2007-09-17 22:58 ` Kristian Høgsberg
2007-09-17 23:16 ` Johannes Schindelin
2007-09-17 23:56 ` Jeff King
2007-09-18 0:11 ` Kristian Høgsberg
2007-09-06 16:40 ` [PATCH 7/9] Add strbuf_read_path() Johannes Schindelin
2007-09-06 16:38 ` [PATCH 6/9] Rewrite launch_editor, create_tag and stripspace to use strbufs Johannes Schindelin
2007-09-17 22:59 ` Kristian Høgsberg
2007-09-06 16:31 ` [PATCH 4/9] Introduce entry point for launching add--interactive Johannes Schindelin
2007-09-17 23:13 ` Kristian Høgsberg
2007-09-17 23:27 ` Johannes Schindelin
2007-09-06 8:55 ` [PATCH 3/9] Add strbuf_printf() to do formatted printing to a strbuf Junio C Hamano
2007-09-06 9:43 ` Pierre Habouzit
2007-09-06 9:50 ` Pierre Habouzit
2007-09-06 16:27 ` [PATCH 1/9] Enable wt-status output to a given FILE pointer Johannes Schindelin
2007-09-17 23:30 ` Kristian Høgsberg
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1189038225525-git-send-email-krh@redhat.com \
--to=krh@redhat.com \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).