Re: [PATCH v2 3/6] Implement `scalar diagnose`
- From
Johannes Schindelin <johannes.schindelin@gmx.de>
- Date
- Feb 8, 2022, 12:08 UTC
- Message-ID
- <nycvar.QRO.7.76.6.2202081303230.347@tvgsbejvaqbjf.bet>
- In-Reply-To
- <ef70b87e-989b-e99c-b4ca-2b91c05defcf@web.de>
Hi René,
On Mon, 7 Feb 2022, René Scharfe wrote:
Show 16 quoted lines
> > Note: originally, Scalar was implemented in C# using the .NET API, where > > we had the luxury of a comprehensive standard library that includes > > basic functionality such as writing a `.zip` file. In the C version, we > > lack such a commodity. Rather than introducing a dependency on, say, > > libzip, we slightly abuse Git's `archive` command: Instead of writing > > the `.zip` file directly, we stage the file contents in a Git index of a > > temporary, bare repository, only to let `git archive` have at it, and > > finally removing the temporary repository. > > > > Also note: Due to the frequently-spawned `git hash-object` processes, > > this command is quite a bit slow on Windows. Should it turn out to be a > > big problem, the lack of a batch mode of the `hash-object` command could > > potentially be worked around via using `git fast-import` with a crafted > > `stdin`. > > The two paragraphs above are not in sync with the patch.
Whoopsie!
Show 27 quoted lines
> > + archiver_fd = xopen(zip_path.buf, O_CREAT | O_WRONLY | O_TRUNC, 0666);
> > + if (archiver_fd < 0 || dup2(archiver_fd, 1) < 0) {
> > + res = error_errno(_("could not redirect output"));
> > + goto diagnose_cleanup;
> > + }
> > +
> > + init_zip_archiver();
> > + strvec_pushl(&archiver_args, "scalar-diagnose", "--format=zip", NULL);
> > +
> > + strbuf_reset(&buf);
> > + strbuf_addstr(&buf,
> > + "--add-file-with-content=diagnostics.log:"
> > + "Collecting diagnostic info\n\n");
> > + get_version_info(&buf, 1);
> > +
> > + strbuf_addf(&buf, "Enlistment root: %s\n", the_repository->worktree);
> > + off = strchr(buf.buf, ':') + 1 - buf.buf;
> > + write_or_die(stdout_fd, buf.buf + off, buf.len - off);
> > + strvec_push(&archiver_args, buf.buf);
>
> Fun trick to reuse the buffer for both the ZIP entry and stdout. :) I'd
> have omitted the option from buf and added it like this, for simplicity:
>
> strvec_pushf(&archiver_args,
> "--add-file-with-content=diagnostics.log:%s", buf.buf);
>
> Just a thought.Oh, that's even better. I did not like that `off` pattern at all but forgot to think of `pushf()`. Thanks!
Show 22 quoted lines
> > + > > + if ((res = add_directory_to_archiver(&archiver_args, ".git", 0)) || > > + (res = add_directory_to_archiver(&archiver_args, ".git/hooks", 0)) || > > + (res = add_directory_to_archiver(&archiver_args, ".git/info", 0)) || > > + (res = add_directory_to_archiver(&archiver_args, ".git/logs", 1)) || > > + (res = add_directory_to_archiver(&archiver_args, ".git/objects/info", 0))) > > + goto diagnose_cleanup; > > + > > + strvec_pushl(&archiver_args, "--prefix=", > > + oid_to_hex(the_hash_algo->empty_tree), "--", NULL); > > + > > + /* `write_archive()` modifies the `argv` passed to it. Let it. */ > > + argv_copy = xmemdupz(archiver_args.v, > > + sizeof(char *) * archiver_args.nr); > > Leaking the whole thing would be fine as well for this command, but > cleaning up is tidier, of course. > > > + res = write_archive(archiver_args.nr, (const char **)argv_copy, NULL, > > + the_repository, NULL, 0); > > Ah -- no shell means no command line length limits. :)
Yes!!!
It also makes the command a ridiculous amount faster on Windows.
Show 12 quoted lines
> > + if (res) {
> > + error(_("failed to write archive"));
> > + goto diagnose_cleanup;
> > + }
> > +
> > + if (!res)
> > + printf("\n"
> > + "Diagnostics complete.\n"
> > + "All of the gathered info is captured in '%s'\n",
> > + zip_path.buf);
>
> Is this message appended to the ZIP file or does it go to stdout?It goes to `stdout`, this is for the user who runs `scalar diagnose`.
Hmm.
Now that you pointed it out, I think I want it to go to `stderr` instead.
> In any case: mixing write(2) and stdio(3) is not a good idea. Using > fwrite(3) instead of write_or_die above and doing the stdout dup(2) > dance only tightly around the write_archive call would help, I think.
Sure, but let's print this message to `stderr` instead, that'll be much cleaner, right?
Alternatively, I think I'd rather move the `printf()` below...
Show 7 quoted lines
>
> > +
> > +diagnose_cleanup:
> > + if (archiver_fd >= 0) {
> > + close(1);
> > + dup2(stdout_fd, 1);
> > + }... this re-redirection.
What do you think? `stdout` or `stderr`?
Thank you for your review! Dscho