fix chopped display of git-server's progress output
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
diff --git a/include/got_fetch.h b/include/got_fetch.h
index 8b9f1d3..43417f2 100644
--- a/include/got_fetch.h
+++ b/include/got_fetch.h
@@ -24,6 +24,8 @@
#define GOT_FETCH_DEFAULT_REMOTE_NAME "origin"
+#define GOT_FETCH_PKTMAX 65536
+
/*
* Attempt to parse a URI into the following parts:
* A protocol scheme, hostname, port number (as a string), path on server,
diff --git a/lib/fetch.c b/lib/fetch.c
index 1f30cd2..0fa6534 100644
--- a/lib/fetch.c
+++ b/lib/fetch.c
@@ -409,6 +409,7 @@ got_fetch_pack(struct got_object_id **pack_hash, struct got_pathlist_head *refs,
char *ref_prefix = NULL;
size_t ref_prefixlen = 0;
char *path;
+ char *progress = NULL;
*pack_hash = NULL;
for (i = 0; i < nitems(tmpfds); i++)
@@ -546,6 +547,11 @@ got_fetch_pack(struct got_object_id **pack_hash, struct got_pathlist_head *refs,
}
packfile_size = 0;
+ progress = calloc(GOT_FETCH_PKTMAX, 1);
+ if (progress == NULL) {
+ err = got_error_from_errno("calloc");
+ goto done;
+ }
while (!done) {
struct got_object_id *id = NULL;
char *refname = NULL;
@@ -562,20 +568,45 @@ got_fetch_pack(struct got_object_id **pack_hash, struct got_pathlist_head *refs,
*pack_hash = id;
else
free(id);
- }
- else if (refname && id) {
+ } else if (refname && id) {
err = got_pathlist_append(refs, refname, id);
if (err)
goto done;
} else if (server_progress) {
- char *s, *s0 = server_progress;
- while ((s = strsep(&s0, "\r")) != NULL) {
- if (*s == '\0')
- continue;
+ char *p;
+ /*
+ * XXX git-daemon tends to send batched output with
+ * lines spanning separate packets. Buffer progress
+ * output until we see a CR or LF to avoid giving
+ * partial lines of progress output to the callback.
+ */
+ if (strlcat(progress, server_progress,
+ GOT_FETCH_PKTMAX) >= GOT_FETCH_PKTMAX) {
+ progress[0] = '\0'; /* discard */
+ continue;
+ }
+ while ((p = strchr(progress, '\r')) != NULL ||
+ (p = strchr(progress, '\n')) != NULL) {
+ char *s;
+ size_t n;
+ char c = *p;
+ *p = '\0';
+ if (asprintf(&s, "%s%s", progress,
+ c == '\n' ? "\n" : "") == -1) {
+ err = got_error_from_errno("asprintf");
+ goto done;
+ }
err = progress_cb(progress_arg, s,
packfile_size_cur, 0, 0, 0, 0);
+ free(s);
if (err)
break;
+ n = strlen(progress);
+ if (n < GOT_FETCH_PKTMAX - 1) {
+ memmove(progress, &progress[n + 1],
+ GOT_FETCH_PKTMAX - n - 1);
+ } else
+ progress[0] = '\0';
}
free(server_progress);
if (err)
@@ -714,6 +745,7 @@ done:
free(idxpath);
free(packpath);
free(ref_prefix);
+ free(progress);
TAILQ_FOREACH(pe, &have_refs, entry) {
free((char *)pe->path);
diff --git a/libexec/got-fetch-pack/got-fetch-pack.c b/libexec/got-fetch-pack/got-fetch-pack.c
index 5f2e668..ff77adb 100644
--- a/libexec/got-fetch-pack/got-fetch-pack.c
+++ b/libexec/got-fetch-pack/got-fetch-pack.c
@@ -39,6 +39,7 @@
#include "got_object.h"
#include "got_path.h"
#include "got_version.h"
+#include "got_fetch.h"
#include "got_lib_sha1.h"
#include "got_lib_delta.h"
@@ -51,8 +52,6 @@
#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
#endif
-#define GOT_PKTMAX 65536
-
struct got_object *indexed;
static char *fetchbranch;
static struct got_object_id zhash = {.sha1={0}};
@@ -451,7 +450,7 @@ fetch_pack(int fd, int packfd, struct got_object_id *packid,
struct got_pathlist_head *have_refs, struct imsgbuf *ibuf)
{
const struct got_error *err = NULL;
- char buf[GOT_PKTMAX];
+ char buf[GOT_FETCH_PKTMAX];
char hashstr[SHA1_DIGEST_STRING_LENGTH];
struct got_object_id *have, *want;
int is_firstpkt = 1, nref = 0, refsz = 16;