commit f1c6967f90f720a023714672e6751755b755e2a5 from: Stefan Sperling date: Thu Mar 19 21:43:44 2020 UTC fix chopped display of git-server's progress output commit - e69674d80611af869c17b1ddc0b14f30896ce129 commit + f1c6967f90f720a023714672e6751755b755e2a5 blob - 8b9f1d33c0c131a2bcf34368195401b48de3bead blob + 43417f24df05740c8f026cd7b896c75491e9afc4 --- include/got_fetch.h +++ 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, blob - 1f30cd2190941327b8e9cfdaa88af0b083e996d6 blob + 0fa6534500d768ff92fdf0a5ec9d721d9c7af309 --- lib/fetch.c +++ lib/fetch.c @@ -409,6 +409,7 @@ got_fetch_pack(struct got_object_id **pack_hash, struc 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, struc } 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, struc *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); blob - 5f2e668bddbc081bb26a11e5a59669e6ffc63469 blob + ff77adba05310befc369700544a6520a6ce0dc1b --- libexec/got-fetch-pack/got-fetch-pack.c +++ 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 *p 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;