Junio C Hamano wrote: > "Victoria Dye via GitGitGadget" <gitgitgadget@xxxxxxxxx> writes: > >> From: Victoria Dye <vdye@xxxxxxxxxx> >> >> Create a '--diagnose' option for 'git bugreport' to collect additional >> information about the repository and write it to a zipped archive. >> >> The "diagnose" functionality was originally implemented for Scalar in >> aa5c79a331 (scalar: implement `scalar diagnose`, 2022-05-28). However, the >> diagnostics gathered are not specific to Scalar-cloned repositories and >> could be useful when diagnosing issues in any Git repository. >> >> Note that, while this patch appears large, it is mostly copied directly out >> of 'scalar.c'. Specifically, the functions >> >> - dir_file_stats_objects() >> - dir_file_stats() >> - count_files() >> - loose_objs_stats() >> - add_directory_to_archiver() >> - get_disk_info() > > Yup. As this does not "move" code across from older place to the > new home, it takes a bit of processing to verify the above claim, > but > > $ git blame -C -C -C -s -b master.. -- builtin/bugreport.c > > shows that these are largely verbatim copies. > >> +#ifndef WIN32 >> +#include <sys/statvfs.h> >> +#endif >> + >> +static int get_disk_info(struct strbuf *out) >> +{ >> +#ifdef WIN32 >> + struct strbuf buf = STRBUF_INIT; >> +... >> + strbuf_addf(out, "Available space on '%s': ", buf.buf); >> + strbuf_humanise_bytes(out, avail2caller.QuadPart); >> +... >> +#else >> +... >> + strbuf_addf(out, "Available space on '%s': ", buf.buf); >> + strbuf_humanise_bytes(out, st_mult(stat.f_bsize, stat.f_bavail)); >> +... >> +#endif >> + return 0; >> +} > > As a proper part of Git, this part should probably be factored out > so that a platform specific helper function, implemented in compat/ > layer, grabs "available disk space" number in off_t and the caller > of the above function becomes > > strbuf_realpath(&dir, ".", 1); > strbuf_addf(out, "Available space on '%s:' ", dir.buf); > strbuf_humanise_bytes(out, get_disk_size(dir.buf)); > > or something, without having to have #ifdef droppings. > This makes sense, I'll probably follow an approach similar to what was done with 'compat/compiler.h' in [1] (unless adding to 'git-compat-util.h' would be more appropriate?). [1] https://lore.kernel.org/git/20200416211807.60811-6-emilyshaffer@xxxxxxxxxx/ >> +static int create_diagnostics_archive(struct strbuf *zip_path) >> +{ > > Large part of this function is also lifted from scalar, and it looks > OK. One thing I noticed is that "res" is explicitly initialized to > 0, but given that the way the code is structured to use the "we > process sequencially in successful case, and branch out by 'goto' > immediately when we see a breakage" pattern, it may be better to > initialize it to -1 (i.e. assume error), or even better, leave it > uninitialized (i.e. let the compiler notice if a jump to cleanup is > made without setting res appropriately). > I'll go with the "uninitialized" approach in the re-roll; I like the simplicity of relying on the compiler to determine if it's unassigned. >> +diagnose_cleanup: >> + if (archiver_fd >= 0) { >> + close(1); >> + dup2(stdout_fd, 1); >> + } >> + free(argv_copy); >> + strvec_clear(&archiver_args); >> + strbuf_release(&buf); > > Hmph, stdout_fd is a copy of the file descriptor 1 that was saved > away at the beginning. Then archiver_fd was created to write into > the zip archive, and during the bulk of the function it was dup2'ed > to the file descriptor 1, to make anything written to the latter > appear in the zip output. > > When we successfully opened archive_fd but failed to dup2(), we may > close a wrong file desciptor 1 here, but we recover from that by > using the saved-away stdout_fd, so we'd be OK. If we did dup2(), > then we would be OK, too. > > I am wondering if archiver_fd itself is leaking here, though. > > Also, if we failed to open archiver_fd, then we have stdout_fd > leaking here, I suspect. > If I'm not mistaken, both 'archiver_fd' and 'stdout_fd' are always leaked if they're successfully created (they're never 'close()'d). There's also an unnecessary check for 'archiver_fd < 0', since 'xopen()' will die if it can't open the file. And, as you mentioned, the wrong file descriptor 1 is closed if the 'dup2()' of 'archiver_fd' fails. I'll clean this up for V2, thanks. >> + return res; >> +} > > Other than that, looks good to me.