aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn O. Pearce <spearce@spearce.org>2007-01-18 13:14:27 -0500
committerShawn O. Pearce <spearce@spearce.org>2007-01-18 13:25:37 -0500
commit3b4dce02752d37c3cef9308eefb01ed758efe323 (patch)
tree9ff8ee1643c6527fa03601bd5868da1e955acd18
parente5808826c4abe183b4db9bae8f13445624696f66 (diff)
downloadgit-3b4dce02752d37c3cef9308eefb01ed758efe323.tar.gz
git-3b4dce02752d37c3cef9308eefb01ed758efe323.tar.xz
Support delimited data regions in fast-import.
During testing its nice to not have to feed the length of a data chunk to the 'data' command of fast-import. Instead we would prefer to be able to establish a data chunk much like shell's << operator and use a line delimiter to denote the end of the input. So now if a data command is started as 'data <<EOF' we will look for a terminator line containing only the string EOF on that line. Once found, we stop the data command. Everything between the two lines is used as the data value. The 'data <<' syntax is slower than 'data n', as we don't know how many bytes to expect and instead must grow our buffer on the fly. It also has the problem that the frontend must use a string which will not appear on a line by itself in the input, and the data region will always end in an LF. For these reasons real import frontends are encouraged to continue to use _only_ 'data n'. Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
-rw-r--r--fast-import.c64
1 files changed, 49 insertions, 15 deletions
diff --git a/fast-import.c b/fast-import.c
index 9a642f2e0..90adc6804 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -50,14 +50,21 @@ Format of STDIN stream:
# a new mark directive with the old idnum.
#
mark ::= 'mark' sp idnum lf;
+ data ::= (delimited_data | exact_data)
+ lf;
+
+ # note: delim may be any string but must not contain lf.
+ # data_line may contain any data but must not be exactly
+ # delim.
+ delimited_data ::= 'data' sp '<<' delim lf
+ (data_line lf)*
+ delim lf;
# note: declen indicates the length of binary_data in bytes.
- # declen does not include the lf preceeding or trailing the
- # binary data.
+ # declen does not include the lf preceeding the binary data.
#
- data ::= 'data' sp declen lf
- binary_data
- lf;
+ exact_data ::= 'data' sp declen lf
+ binary_data;
# note: quoted strings are C-style quoting supporting \c for
# common escapes of 'c' (e..g \n, \t, \\, \") or \nnn where nnn
@@ -1334,21 +1341,48 @@ static void cmd_mark(void)
static void* cmd_data (size_t *size)
{
- size_t n = 0;
- void *buffer;
size_t length;
+ char *buffer;
if (strncmp("data ", command_buf.buf, 5))
die("Expected 'data n' command, found: %s", command_buf.buf);
- length = strtoul(command_buf.buf + 5, NULL, 10);
- buffer = xmalloc(length);
-
- while (n < length) {
- size_t s = fread((char*)buffer + n, 1, length - n, stdin);
- if (!s && feof(stdin))
- die("EOF in data (%lu bytes remaining)", length - n);
- n += s;
+ if (!strncmp("<<", command_buf.buf + 5, 2)) {
+ char *term = xstrdup(command_buf.buf + 5 + 2);
+ size_t sz = 8192, term_len = command_buf.len - 5 - 2;
+ length = 0;
+ buffer = xmalloc(sz);
+ for (;;) {
+ read_next_command();
+ if (command_buf.eof)
+ die("EOF in data (terminator '%s' not found)", term);
+ if (term_len == command_buf.len
+ && !strcmp(term, command_buf.buf))
+ break;
+ if (sz < (length + command_buf.len)) {
+ sz = sz * 3 / 2 + 16;
+ if (sz < (length + command_buf.len))
+ sz = length + command_buf.len;
+ buffer = xrealloc(buffer, sz);
+ }
+ memcpy(buffer + length,
+ command_buf.buf,
+ command_buf.len - 1);
+ length += command_buf.len - 1;
+ buffer[length++] = '\n';
+ }
+ free(term);
+ }
+ else {
+ size_t n = 0;
+ length = strtoul(command_buf.buf + 5, NULL, 10);
+ buffer = xmalloc(length);
+ while (n < length) {
+ size_t s = fread(buffer + n, 1, length - n, stdin);
+ if (!s && feof(stdin))
+ die("EOF in data (%lu bytes remaining)", length - n);
+ n += s;
+ }
}
if (fgetc(stdin) != '\n')